前言
人人都想进大厂,当然我也不例外。早在春招的时候我就有向某某某大厂投岗了不少简历,可惜了,疫情期间都是远程面试,加上那时自身也有问题,导致屡投屡败。突然也意识到自己肚子里没啥货,问个啥都是卡卡卡卡,后期下定决心好好弥补我的知识与智商,天天扎在书堆里,再加上实操,自我感觉还是不错的,有进步。
尤其是这我啃了足足58天的[Java进阶架构核心知识集](文末有介绍,可分享),还是当初朋友面试进大厂后分享给我的。摸熟里边近30个分类的Java知识后,7月下旬鼓足勇气向抖音后端进击,123面(视频面)下来就像开挂了(幸运)。完事之后整理了一下抖音3面面经,我想大家可以参考看看。
配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 30000
配置一个连接在池中最大生存的时间,单位是毫秒
max-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM user
test-while-idle: true
test-on-borrow: true
test-on-return: false
是否缓存preparedStatement,也就是PSCache 官方建议MySQL下建议关闭 个人建议如果想用SQL防火墙 建议打开
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall’用于防火墙
filters: stat,wall,slf4j
filter:
stat:
merge-sql: true
slow-sql-millis: 5000
second:
username: root
password: 123456
url: jdbc:mysql://192.168.50.43:3306/mybatis_second?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
#初始化连接池的连接数量 大小,最小,最大
initial-size: 5
min-idle: 5
max-active: 20
#配置获取连接等待超时的时间
max-wait: 60000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 30000
配置一个连接在池中最大生存的时间,单位是毫秒
max-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM user
test-while-idle: true
test-on-borrow: true
test-on-return: false
是否缓存preparedStatement,也就是PSCache 官方建议MySQL下建议关闭 个人建议如果想用SQL防火墙 建议打开
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall’用于防火墙
filters: stat,wall,slf4j
filter:
stat:
merge-sql: true###
slow-sql-millis: 5000
#3.基础监控配置
web-stat-filter:
enabled: true
url-pattern: /*
#设置不统计哪些URL
exclusions: “.js,.gif,.jpg,.png,.css,.ico,/druid/*”
session-stat-enable: true
session-stat-max-count: 100
stat-view-servlet:
enabled: true
url-pattern: /druid/*
reset-enable: true
#设置监控页面的登录名和密码
login-username: admin
login-password: admin
allow: 127.0.0.1
#deny: 192.168.1.100
日志配置
logging:
level:
root: INFO
com:
bolingcavalry:
druidtwosource:
mapper: debug
- user的映射配置,请注意文件位置:
insert into user (id, name, age) values (#{id}, #{name}, #{age})
select id, name, age from user where name like concat(‘%’, #{name}, ‘%’)
delete from user where id= #{id}
- address的映射配置:
insert into address (id, city, street) values (#{id}, #{city}, #{street})
select id, city, street from address where city like concat(‘%’, #{cityname}, ‘%’)
delete from address where id= #{id}
- user表的实体类,注意swagger用到的注解:
package com.bolingcavalry.druidtwosource.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(description = “用户实体类”)
public class User {
@ApiModelProperty(value = “用户ID”)
private Integer id;
@ApiModelProperty(value = “用户名”, required = true)
private String name;
@ApiModelProperty(value = “用户地址”, required = false)
private Integer age;
@Override
public String toString() {
return “User{” +
“id=” + id +
“, name='” + name + ‘’’ +
“, age=” + age +
‘}’;
}
…省略get和set方法
}
- address表的实体类:
package com.bolingcavalry.druidtwosource.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(description = “地址实体类”)
public class Address {
@ApiModelProperty(value = “地址ID”)
private Integer id;
@ApiModelProperty(value = “城市名”, required = true)
private String city;
@ApiModelProperty(value = “街道名”, required = true)
private String street;
@Override
public String toString() {
return “Address{” +
“id=” + id +
“, city='” + city + ‘’’ +
“, street='” + street + ‘’’ +
‘}’;
}
…省略get和set方法
}
- 启动类DuridTwoSourceApplication.java,要注意的是排除掉数据源和事务的自动装配,因为后面会手动编码执行这些配置:
package com.bolingcavalry.druidtwosource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
@SpringBootApplication(exclude={
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
})
public class DuridTwoSourceApplication {
public static void main(String[] args) {
SpringApplication.run(DuridTwoSourceApplication.class, args);
}
}
- swagger配置:
package com.bolingcavalry.druidtwosource;
import springfox.documentation.service.Contact;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Tag;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
-
@Description: swagger配置类
-
@author: willzhao E-mail: zq2599@gmail.com
-
@date: 2020/8/11 7:54
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.tags(new Tag(“UserController”, “用户服务”),
new Tag(“AddressController”, “地址服务”))
.select()
// 当前包路径
.apis(RequestHandlerSelectors.basePackage(“com.bolingcavalry.druidtwosource.controller”))
.paths(PathSelectors.any())
.build();
}
//构建 api文档的详细信息函数,注意这里的注解引用的是哪个
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
//页面标题
.title(“MyBatis CURD操作”)
//创建人
.contact(new Contact(“程序员欣宸”, “https://github.com/zq2599/blog_demos”, “zq2599@gmail.com”))
//版本号
.version(“1.0”)
//描述
.description(“API 描述”)
.build();
}
}
- 数据源配置TwoDataSourceConfig.java,可见是通过ConfigurationProperties注解来确定配置信息,另外不要忘记在默认数据源上添加Primary注解:
package com.bolingcavalry.druidtwosource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
/**
-
@Description: druid配置类
-
@author: willzhao E-mail: zq2599@gmail.com
-
@date: 2020/8/18 08:12
*/
@Configuration
public class TwoDataSourceConfig {
@Primary
@Bean(name = “firstDataSource”)
@ConfigurationProperties(“spring.datasource.druid.first”)
public DataSource first() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = “secondDataSource”)
@ConfigurationProperties(“spring.datasource.druid.second”)
public DataSource second() {
return DruidDataSourceBuilder.create().build();
}
}
- 第一个数据源的mybatis配置类DruidConfigFirst.java,可以结合本篇的第一幅图来看,注意MapperScan注解的两个属性basePackages和sqlSessionTemplateRef是关键,它们最终决定了哪些mapper接口使用哪个数据源,另外注意要带上Primary注解:
package com.bolingcavalry.druidtwosource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
-
@Description: druid配置类
-
@author: willzhao E-mail: zq2599@gmail.com
-
@date: 2020/8/18 08:12
*/
@Configuration
@MapperScan(basePackages = “com.bolingcavalry.druidtwosource.mapper.first”, sqlSessionTemplateRef = “firstSqlSessionTemplate”)
public class DruidConfigFirst {
@Bean(name = “firstSqlSessionFactory”)
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier(“firstDataSource”) DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(“classpath:mappers/first/**/*Mapper.xml”));
return bean.getObject();
}
@Bean(name = “firstTransactionManager”)
@Primary
public DataSourceTransactionManager transactionManager(@Qualifier(“firstDataSource”) DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = “firstSqlSessionTemplate”)
@Primary
public SqlSessionTemplate sqlSessionTemplate(@Qualifier(“firstSqlSessionFactory”) SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
- 第二个数据源的mybatis配置DruidConfigSecond.java,注意不要带Primary注解:
package com.bolingcavalry.druidtwosource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
-
@Description: druid配置类
-
@author: willzhao E-mail: zq2599@gmail.com
-
@date: 2020/8/18 08:12
*/
@Configuration
@MapperScan(basePackages = “com.bolingcavalry.druidtwosource.mapper.second”, sqlSessionTemplateRef = “secondSqlSessionTemplate”)
public class DruidConfigSecond {
@Bean(name = “secondSqlSessionFactory”)
public SqlSessionFactory sqlSessionFactory(@Qualifier(“secondDataSource”) DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(“classpath:mappers/second/**/*Mapper.xml”));
return bean.getObject();
}
@Bean(name = “secondTransactionManager”)
public DataSourceTransactionManager transactionManager(@Qualifier(“secondDataSource”) DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = “secondSqlSessionTemplate”)
public SqlSessionTemplate sqlSessionTemplate(@Qualifier(“secondSqlSessionFactory”) SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
- user表的mapper接口类很简单,只有三个接口,注意package位置:
package com.bolingcavalry.druidtwosource.mapper.first;
import com.bolingcavalry.druidtwosource.entity.User;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserMapper {
int insertWithFields(User user);
List findByName(String name);
int delete(int id);
}
- address表的Mapper接口类:
package com.bolingcavalry.druidtwosource.mapper.second;
import com.bolingcavalry.druidtwosource.entity.Address;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
-
@Description: 地址实体的接口类
-
@author: willzhao E-mail: zq2599@gmail.com
-
@date: 2020/8/4 8:32
*/
@Repository
public interface AddressMapper {
int insertWithFields(Address address);
List
findByCityName(String cityName);int delete(int id);
}
- user表的service类:
package com.bolingcavalry.druidtwosource.service;
import com.bolingcavalry.druidtwosource.entity.User;
import com.bolingcavalry.druidtwosource.mapper.first.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
public class UserService {
@Autowired
UserMapper userMapper;
public User insertWithFields(User user) {
userMapper.insertWithFields(user);
return user;
}
public List findByName(String name) {
return userMapper.findByName(name);
}
public int delete(int id) {
return userMapper.delete(id);
}
}
- address表的service类:
package com.bolingcavalry.druidtwosource.service;
import com.bolingcavalry.druidtwosource.entity.Address;
import com.bolingcavalry.druidtwosource.entity.User;
import com.bolingcavalry.druidtwosource.mapper.first.UserMapper;
import com.bolingcavalry.druidtwosource.mapper.second.AddressMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AddressService {
@Autowired
AddressMapper addressMapper;
public Address insertWithFields(Address address) {
addressMapper.insertWithFields(address);
return address;
}
public List
findByCityName(String cityName) {return addressMapper.findByCityName(cityName);
}
public int delete(int id) {
return addressMapper.delete(id);
}
}
- user表的controller:
package com.bolingcavalry.druidtwosource.controller;
《一线大厂Java面试真题解析+Java核心总结学习笔记+最新全套讲解视频+实战项目源码》开源
写在最后
可能有人会问我为什么愿意去花时间帮助大家实现求职梦想,因为我一直坚信时间是可以复制的。我牺牲了自己的大概十个小时写了这片文章,换来的是成千上万的求职者节约几天甚至几周时间浪费在无用的资源上。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AddressService {
@Autowired
AddressMapper addressMapper;
public Address insertWithFields(Address address) {
addressMapper.insertWithFields(address);
return address;
}
public List
findByCityName(String cityName) {return addressMapper.findByCityName(cityName);
}
public int delete(int id) {
return addressMapper.delete(id);
}
}
- user表的controller:
package com.bolingcavalry.druidtwosource.controller;
《一线大厂Java面试真题解析+Java核心总结学习笔记+最新全套讲解视频+实战项目源码》开源
写在最后
可能有人会问我为什么愿意去花时间帮助大家实现求职梦想,因为我一直坚信时间是可以复制的。我牺牲了自己的大概十个小时写了这片文章,换来的是成千上万的求职者节约几天甚至几周时间浪费在无用的资源上。
[外链图片转存中…(img-K4r7NZiH-1649568309572)]
[外链图片转存中…(img-bT9X6rym-1649568309573)]