瑞吉外卖总结 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 【进程号】