Serializable的用处
类实现了Serializable接口才能被序列化,Serializable接口内无内容,起标记作用,序列化主要在类被ObjectInputStream存储时发生,类如果没实现Serializable接口则无法被序列化,报java.io.NotSerializableException异常
Swagger构架的注解及作用
如何生成接口文档
官网:https://swagger.io/
- 引入依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter<artifactId>
</dependency>
- 声明配置类
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
/**
* 通过knife4j生成接口文档
* @return
*/
@Bean
public Docket docket1() {
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("管理端接口")
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.sky.controller.admin"))
.paths(PathSelectors.any())
.build();
return docket;
}
实体类相关注解
- @ApiModel注解
标记实体类代表的是什么,回显到doc.html - @ApiModelProperty注解
标记实体类中属性表示的内容,回显到doc.html
@Data
@ApiModel(description = "员工登录时传递的数据模型")
public class EmployeeLoginDTO implements Serializable {
@ApiModelProperty("用户名")
private String username;
@ApiModelProperty("密码")
private String password;
}
Controller相关注解
- @Api注解
用于描述Controller - @ApiOperation注解
用于描述Controller中的方法
@RestController
@RequestMapping("/admin/category")
@Api(tags = "分类相关接口")
@Slf4j
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 新增分类
* @param categoryDTO
* @return
*/
@PostMapping
@ApiOperation("新增分类")
public Result<String> save(@RequestBody CategoryDTO categoryDTO){
log.info("新增分类:{}", categoryDTO);
categoryService.save(categoryDTO);
return Result.success();
}
}
Lombok插件及其注解
- Lombok的引用:在pom.xml中引入以下代码
<dependency>
//加个版本
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
- @Getter,@Setter
给实体类增加get和set方法 - @Synchronized
作用范围是方法,自动把方法添加到同步机制,锁的不是方法,锁的是方法内代码块 - @NonNull
该注解快速判断是否为空,如果为空,则抛出java.lang.NullPointerException - @Data
该注解相当于同时加上以下注解@Setter @Getter,@ToString,@EqualsAndHashCode,@NoArgsConstructor作用于类中使用。 - @ToString
该方法大家应该非常熟悉,但需要注意的是:@ToString有多个属性可以进一步设置:
callSuper 是否输出父类的toString方法,默认为false
includeFieldNames 是否包含字段名称,默认为true
exclude 排除生成tostring的字段
代码实现:
@ToString(callSuper = true,exclude ={"name"})
public class Person {
private String name;
private String address;
}
- @Cleanup
用于确保IO流被关闭,帮助关闭IO流。
代码:
public void testCleanUp() {
try {
@Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(new byte[] {'Y','e','s'});
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
- @EqualsAndHashCode
生成toString和hashCode方法 - @NoArgsConstructor
无参构造 - @AllArgsConstructor
全参构造 - @NoArgsConstructor
生成包含final和@NonNull的无参构造方法 - @Builder
构造器方法
代码:
@Test
public void testUser() {
User6 user6 = User6.builder()
.id(1)
.username("itbaizhan")
.password("itbaizhan")
.build();
}
- @Slf4j,@Log
各种日志注解 - @SneakyThrows
作用于方法体上方用于捕捉和抛出异常 - @Value
@Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。更适合只读性的类。 - @Delegate
被@Delegate注释的属性,会把这个属性类型的公有非静态方法合到当前类 - @Singluar
不知道QAQ
事务的开启
- 启动类上添加@EnableTransactionManagement
- 在访问数据库的Service方法上添加注解 @Transactional 便可
@EnableCaching开启缓存与Redis
- @EnableCaching放置在Springboot启动类上用于开启缓存。
- @Cacheable放在需要缓存返回值的Controller方法上
- Redis配置需要配置类和yml参数
Interceptor拦截器
- 编写拦截器类,实现HandlerInterceptor接口
代码:
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties;
/**
* 校验jwt
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getUserTokenName());
//2、校验令牌
try {
//log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
BaseContext.setCurrentId(userId);
//log.info("当前用户id{}", userId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
}
- 配置类中注册自定义拦截器
代码:
@Autowired
private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
/**
* 注册自定义拦截器
*
* @param registry
*/
protected void addInterceptors(InterceptorRegistry registry) {
log.info("开始注册自定义拦截器...");
registry.addInterceptor(jwtTokenAdminInterceptor)
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/employee/login");
registry.addInterceptor(jwtTokenUserInterceptor)
.addPathPatterns("/user/**")
.excludePathPatterns("/user/user/login")
.excludePathPatterns("/user/shop/status");
}
全局异常处理器
- 工作原理为Interceptor/AOP
- @RestControllerAdvice
写在全局异常处理器类上,用于声明全局异常处理器 - @ExceptionHandler
写在处理类的方法上,用于异常类处理
定时任务处理器SpringTask
- @EnableScheduling放在启动类上,开启定时任务
- @Scheduled(cron = "0 * * * * ? ")放在定时任务方法上,开启定时方法。
@Component
@Slf4j
public class OrderTask {
@Autowired
private OrderMapper orderMapper;
@Scheduled(cron = "0 * * * * ? ")
public void processTimeoutOrder(){
log.info("定时处理超时订单:{}", LocalDateTime.now());
LocalDateTime time= LocalDateTime.now().plusMinutes(-15);
List<Orders> ordersList=orderMapper.getByStatusAndOrderTime(Orders.PENDING_PAYMENT,time);
if(ordersList!=null && !ordersList.isEmpty()){
for (Orders orders : ordersList) {
orders.setStatus(Orders.CANCELLED);
orders.setCancelReason("订单超时,自动取消");
orders.setCancelTime(LocalDateTime.now());
orderMapper.update(orders);
}
}
}
}