学习记录:DAY35
《技术学习笔记:Swagger、SpringBoot配置与AOP实践》
前言
昨天熬死我了,md,舍友不睡觉搁那敲鼠标,byd哪里买的那么响的鼠标,铛铛铛把我血压都敲高了,我想找都找不到。又要在睡眠上投资了。
开始调整生物钟的计划,今天很困,但是必须顶到晚上才能睡觉,再顶个一俩天就好了。
byd舍友最好早点回去,不然留你和我,你看我把不把你当日本人整。
日程
9:00,很困,先趁着还有点状态学会习。
22:42,刚好学完Day3的内容,写会笔记就可以准备睡觉了。困了一天了,今天舍友应该恶心不到我了
学习内容
《省流》
- Swagger
- SpringBoot 多配置文件,配置类
- SpringAOP 实现自动化字段填充
- SpringBoot 消息转换器
- 基于Bean管理的工具类设计
1.Swagger
根据代码反射自动化生成接口并进行在线调试。
导入依赖
<knife4j>3.0.2</knife4j>
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>${knife4j}</version>
</dependency>
在配置类进行相关配置
/*** 配置类,注册web层相关组件*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {@Autowiredprivate JwtTokenAdminInterceptor jwtTokenAdminInterceptor;/*** 通过knife4j生成接口文档* @return*/@Beanpublic Docket docket() {ApiInfo apiInfo = new ApiInfoBuilder().title("苍穹外卖项目接口文档").version("2.0").description("苍穹外卖项目接口文档").build();Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).select().apis(RequestHandlerSelectors.basePackage("com.sky.controller")).paths(PathSelectors.any()).build();return docket;}/*** 设置静态资源映射* @param registry*/protected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}
}
常用注解
注解 | 说明 |
---|---|
@Api | 用在类上,例如Controller,表示对类的说明 |
@ApiModelProperty | 用在类上,例如Entity、DTO、VO |
@ApiModelProperty | 用在属性上,描述属性信息 |
@ApiOperation | 用在方法上,例如Controller的方法,说明方法的用途、作用 |
2.SpringBoot 多配置文件,配置类
1)SpringBoot是可以在主配置文件中引用其他配置文件的。
application.yml
spring:profiles:active: dev #main:allow-circular-references: truedatasource:druid:driver-class-name: ${sky.datasource.driver-class-name} #通过插值表达式引用url: jdbc:mysql://${sky.datasource.host}:${sky.datasource.port}/${sky.datasource.database}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: ${sky.datasource.username}password: ${sky.datasource.password}
application-dev.yml
sky:datasource:driver-class-name: com.mysql.cj.jdbc.Driverhost: localhostport: 3306database: sky_take_outusername: rootpassword: root
2)配置类
配置类是配置文件到Java实体类的映射
设置映射的配置文件位置
@ConfigurationProperties(prefix = "sky.alioss")
完整示例
@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;}
3.SpringAOP 实现自动化字段填充
首先要设置一个注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {OperationType value();
}
创建AOP切面,根据注解过滤,通过参数获取反射方法,注入参数
@Aspect
@Component
@Slf4j
public class AutoFillAspect {/*** 切入点*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillCutPoint(){}/*** 公共字段赋值*/@Before("autoFillCutPoint()")public void autoFill(JoinPoint joinPoint) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {//获取拦截方法的数据库操作类型MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();AutoFill autoFill = methodSignature.getMethod().getAnnotation(AutoFill.class);OperationType operationType = autoFill.value();//获取参数Object[] args = joinPoint.getArgs();if(args == null || args.length == 0) return;Object entity = args[0];//赋值参数LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();if(operationType == OperationType.INSERT){Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);setCreateTime.invoke(entity, now);setUpdateTime.invoke(entity, now);setCreateUser.invoke(entity, currentId);setUpdateUser.invoke(entity, currentId);}else {Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);setUpdateTime.invoke(entity, now);setUpdateUser.invoke(entity, currentId);}}
}
4.SpringBoot 消息转换器
消息转换器(HttpMessageConverter)是 Spring MVC 中用于处理 HTTP 请求和响应的组件,负责将 HTTP 消息(如 JSON、XML)与 Java 对象相互转换。
重写SpringBoot的extendMessageConverters方法,将Http的Json数据处理交给自定义的对象转换器处理
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {/*** 消息转换器*/protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {log.info("扩展消息转换器...");//创建消息转换器对象MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();//设置对象转换器,底层使用Jackson将Java对象转为jsonmessageConverter.setObjectMapper(new JacksonObjectMapper());//将上面的消息转换器对象追加到converters中converters.add(0, messageConverter);}
}
Jackson的实现:将时间序列化
/*** 对象映射器:基于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_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";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(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.基于Bean管理的工具类设计
这是一个带状态的工具类,通过Properties配置类注入配置信息,并交给Bean管理(@ConditionalOnMissingBean
实际的效果类似于单例模式)
@Configuration
@Slf4j
public class OssConfiguration {@Bean@ConditionalOnMissingBeanpublic AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){log.info("开始创建阿里云文件上传工具类对象:{}", aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
}
结语
明天的目标是学完Day5和Day6,内容相对会比较多(今天比较水)
明天一定要爬起来啊😭