【瑞吉外卖总结 SpringBoot项目构建】

一 、项目的总体构建

1.Mybatis Plus

Service :
MyService 继承 Iservice<MyEntity>
MyServiceImpl 继承 ServiceImpl<MyMapper, MyEntity> 实现 MyService
Mapper:
MyMapper 继承 BaseMapper<E>

// Mybatis plus 中的连接数据库的一些查询方法
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getUsername, employee.getUsername());
Employee emp = employeeService.getOne(queryWrapper);

querywrapper的常用方法
在这里插入图片描述

2. Filter

filterName: 随便起
urlPatterns: 要拦截的路径
要实现 Filter 接口
@WebFilter(filterName = “loginCheckFilter”, urlPatterns = “/*”)
// 因为有通配符,所以无法直接比较,要用到 路径匹配器(支持通配符)
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
// 进行匹配
boolean match = PATH_MATCHER.match(url, requestURI);
//通行
filterChain.doFilter(request, response);
// 回写数据
response.getWriter().write(JSON.toJSONString(R.error(“NOTLOGIN”)));
最后记得要在在启动类上添加
@ServletComponentScan

3. 多表查询事务控制

在方法前添加
@Transactional
在启动类上添加
@EnableTransactionManagement

二、 配置类

1. 静态资源映射(映射静态资源)&消息转换器(解决数据转换问题)

@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
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文件

spring:
	redis:
	  host: localhost
	  port: 6379
	  password: 123456
	  database: 0
	cache:
	  redis:
	    time-to-live: 1800000 #设置有效期

3. Mybatis Plus 配置

/**
 * 配置MP的分页插件
 */
@Configuration
public class MybatisPlusConfig {
    
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor (){
    
    
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

三、 公共类

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 自定义的
 */
public class CustomException extends RuntimeException {
    
    
    public CustomException(String message){
    
    
        super(message);
    }
}

3. 全局异常处理

/**
 * 全局异常处理
 */
@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对象映射器

/**
 * 对象映射器:基于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. 自定义元数据对象处理器

使用方法
在实体类的对应字段上添加
@TableField(fill = FieldFill.INSERT)、
@TableField(fill = FieldFill.INSERT_UPDATE)等注解

@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. 通用返回结果

/**
 * 通用返回结果,服务端响应的数据最终都会封装成此对象
 * @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;
    }
}

四、 优化工具

1. Redis 配置

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>

spring cache部分注解的解释

//启动类上需要加上
@EnableCaching
/**
 * @CachePut: 将方法返回值放入缓存
 * value: 缓存的名称,每个缓存名称下面可以有多个key
 * key: 缓存的key
**/
/**
 * @CacheEvict: 清理指定缓存
 * value: 缓存的名称,每个缓存名称下面可以有多个key
 * key: 缓存的key
 */
/**
 * @Cacheable: 在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
 * value: 缓存的名称,每个缓存名称下面可以有多个key
 * key: 缓存的key
 * condition: 条件,满足条件时才缓存数据
 * unless: 满足条件则不缓存
 */

3. Nginx 反向代理、负载均衡 (没有的可根据自己情况自行查询)

4. Swagger

5. Lombok

Lombok部分注解解释

@Data : 注在类上,提供类的get、set、equals、hashCode、canEqual、toString方法
@AllArgsConstructor : 注在类上,提供类的全参构造
@NoArgsConstructor : 注在类上,提供类的无参构造
@Setter : 注在属性上,提供 set 方法
@Getter : 注在属性上,提供 get 方法
@EqualsAndHashCode : 注在类上,提供对应的 equals 和 hashCode 方法
@Log4j/@Slf4j : 注在类上,提供对应的 Logger 对象,变量名为 log

6. Serializable 实体类序列化

7. 异步处理

AtomicInteger amount = new AtomicInteger(0);
amount.addAndGet() 相当于 amount +=

五、 项目部署(Linux)

1. 手工部署项目

1) 后台运行java -jar 命令,并将日志输出到log.log文件

nohup java -jar boot工程.jar &> log.log

2) 停止SpringBoot程序

ps -ef | grep java
kill -9 【进程号】

猜你喜欢

转载自blog.csdn.net/weixin_52067659/article/details/127718863