St. Regis takeaway summary SpringBoot project construction
1. The overall construction of the project
1.Mybatis Plus
Service :
MyService inherits Iservice<MyEntity>
MyServiceImpl inherits ServiceImpl<MyMapper, MyEntity> implements MyService
Mapper:
MyMapper inherits BaseMapper<E>
// Mybatis plus 中的连接数据库的一些查询方法
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getUsername, employee.getUsername());
Employee emp = employeeService.getOne(queryWrapper);
Common methods of querywrapper
2. Filter
filterName: random
urlPatterns: the path to be intercepted
to implement the Filter interface
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
// Because there are wildcards, they cannot be compared directly, and a path matcher (supporting wildcards) is required
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
// Match
boolean match = PATH_MATCHER.match(url, requestURI);
// pass
filterChain.doFilter(request, response);
// write back data
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")) );
Finally remember to add on the startup class
@ServletComponentScan
3. Multi-table query transaction control
Add before the method
@Transactional
Add on startup class
@EnableTransactionManagement
Two, configuration class
1. Static resource mapping (mapping static resources) & message converter (solving data conversion problems)
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始静态资源映射");
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 创建消息转换器对象
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
// 设置对象转换器,底层使用Jackson将Java对象转为json
// JacksonObjectMapper() 是自己写的
messageConverter.setObjectMapper(new JacksonObjectMapper());
// 将上面的消息转换器对象追加到mvc框架的转换器集合中
converters.add(0,messageConverter);
}
}
2. Redis configuration
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory connectionFactory){
RedisTemplate<Object,Object> redisTemplate = new RedisTemplate<>();
// 默认的Key序列化器为:JdkSerializationRedisSerializer
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
Pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
yml file
spring:
redis:
host: localhost
port: 6379
password: 123456
database: 0
cache:
redis:
time-to-live: 1800000 #设置有效期
3. Mybatis Plus configuration
/**
* 配置MP的分页插件
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor (){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
3. Public class
1. BaseContext
/**
* 基于ThreadLocal封装的工具类,用于保存和获取当前登录用户id
*/
public class BaseContext {
private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Long id){
threadLocal.set(id);
}
public static Long getCurrentId(){
return threadLocal.get();
}
}
2. Custom exceptions
/**
* 自定义业务异常 custom 自定义的
*/
public class CustomException extends RuntimeException {
public CustomException(String message){
super(message);
}
}
3. Global exception handling
/**
* 全局异常处理
*/
@Slf4j
@ResponseBody
@ControllerAdvice(annotations = {
RestController.class, Controller.class}) //要处理的注解
public class GlobalExceptionHandler {
/**
* 异常处理方法
* @param ex
* @return
*/
@ExceptionHandler
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error(ex.getMessage());
if(ex.getMessage().contains("Duplicate entry")){
String[] s = ex.getMessage().split(" ");
String msg = s[2] + " 已存在";
return R.error(msg);
}
return R.error("未知错误");
}
//自定义异常的处理方法
@ExceptionHandler
public R<String> customExceptionHandler(CustomException ex){
log.error(ex.getMessage());
return R.error(ex.getMessage());
}
}
4. json object mapper
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
5. Custom metadata object handler
How to use Add annotations such as @TableField(fill = FieldFill.INSERT), @TableField(fill = FieldFill.INSERT_UPDATE)
on the corresponding fields of the entity class
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入操作,自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充[insert]");
log.info(metaObject.toString());
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime", LocalDateTime.now());
Long id = BaseContext.getCurrentId();
metaObject.setValue("createUser", id);
metaObject.setValue("updateUser", id);
}
/**
* 更新操作,自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充[update]");
log.info(metaObject.toString());
Long id = BaseContext.getCurrentId();
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("updateUser", id);
}
}
6. General return result
/**
* 通用返回结果,服务端响应的数据最终都会封装成此对象
* @param <T>
*/
@Data
public class R<T> implements Serializable {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
private Map map = new HashMap(); //动态数据
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) {
this.map.put(key, value);
return this;
}
}
4. Optimization tools
1. Redis configuration
pom.xml
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.xml
# redis 配置
redis:
host: localhost # 配置连接地址
port: 6379 # 配置端口号
password: 123456 # 配置密码
database: 0
pom.xml
// 导入jedis 可选
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
2. Spring Cache
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Explanation of spring cache partial annotations
//启动类上需要加上
@EnableCaching
/**
* @CachePut: 将方法返回值放入缓存
* value: 缓存的名称,每个缓存名称下面可以有多个key
* key: 缓存的key
**/
/**
* @CacheEvict: 清理指定缓存
* value: 缓存的名称,每个缓存名称下面可以有多个key
* key: 缓存的key
*/
/**
* @Cacheable: 在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
* value: 缓存的名称,每个缓存名称下面可以有多个key
* key: 缓存的key
* condition: 条件,满足条件时才缓存数据
* unless: 满足条件则不缓存
*/
3. Nginx reverse proxy, load balancing (If you don’t have one, you can query it yourself according to your own situation)
4. Swagger
5. Lombok
Lombok partial annotation explanation
@Data : 注在类上,提供类的get、set、equals、hashCode、canEqual、toString方法
@AllArgsConstructor : 注在类上,提供类的全参构造
@NoArgsConstructor : 注在类上,提供类的无参构造
@Setter : 注在属性上,提供 set 方法
@Getter : 注在属性上,提供 get 方法
@EqualsAndHashCode : 注在类上,提供对应的 equals 和 hashCode 方法
@Log4j/@Slf4j : 注在类上,提供对应的 Logger 对象,变量名为 log
6. Serializable entity class serialization
7. Asynchronous processing
AtomicInteger amount = new AtomicInteger(0);
amount.addAndGet() is equivalent to amount +=
5. Project deployment (Linux)
1. Manually deploy the project
1) Run the java -jar command in the background and output the log to the log.log file
nohup java -jar boot工程.jar &> log.log
2) Stop the SpringBoot program
ps -ef | grep java
kill -9 [process number]