[Summary of St. Regis Takeaway 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
insert image description here

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]

Guess you like

Origin blog.csdn.net/weixin_52067659/article/details/127718863