@Conditional 满足条件给容器注册Bean(在配置类 @Configuration 的类和方法上配置)
需要实现Condition接口, 实现matches方法
public class LdCondition implements Condition{
@Override
public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
//从这里获取配置文件中 active 的值,根据当前的 active 值决定是否加载类
String[] activeProfiles = environment.getActiveProfiles();
for (String active : activeProfiles) {
if(active.equals(ActiveEnum.open_active.getActive().toString())){
return true;
}
}
return false;
}
}
标注在类上:
一个类中可以注入很多实例,@Conditional标注在类上就决定了一批bean是否注入。
标记在方法上
@Configuration
public class BeanConfig {
//只有一个类时,大括号可以省略
//如果LdCondition的实现方法返回true,则注入这个bean
@Conditional({LdCondition.class})
@Bean("person")
public Person person(){
return new Person("ld",22);
}
}
@ConditionalOnMissingBean:
容器中没有就注入,有就不注入。
@ConditionalOnMissingBean:
容器中没有就不注入,有就注入。
FilterRegistrationBean 自定义过滤器(配置类 @Configuration 中)
使用FilterRegistrationBean来注册Filter:
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
FilterRegistrationBean<CorsFilter> corsFilter = new FilterRegistrationBean<>();
//设置优先级
corsFilter.setOrder(Ordered.HIGHEST_PRECEDENCE + 10);
//注册过滤器
corsFilter.setFilter(new CorsFilter());
//拦截路径
corsFilter.addUrlPatterns("/api/*");
return corsFilter;
}
SpringBoot 整合 Swagger2(配置类 @Configuration 上)
依赖:
implementation "io.springfox:springfox-swagger2:$swaggerVersion"
implementation "io.springfox:springfox-swagger-ui:$swaggerVersion"
一般 swagger 需要的权限(需要在对应的模块进行排除):
http://localhost:8080/swagger-resources/configuration/ui
http://localhost:8080/swagger-resources
http://localhost:8080/api-docs
http://localhost:8080/swagger-ui.html
http://localhost:8080/swagger-resources/configuration/security
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
@Api("评论接口"):
用在类上,说明该类的作用
@ApiOperation(value="获取评论", notes="根据id获取评论"):
用在方法上,说明方法的作用,标注在具体请求上。
value和notes的作用差不多,都是对请求进行说明;
tags则是对请求进行分类的,
比如你有好几个controller,分别属于不同的功能模块,那这里我们就可以使用tags来区分了。
@ApiImplicitParams:
用在方法上包含一组参数说明。
@ApiImplicitParam(name = "id", value = "12", required = true, dataType = "String"):
用在@ApiImplicitParams注解中,指定一个请求参数的各个方面。
@ApiResponses:
用于表示一组响应
@ApiResponse:
用在@ApiResponses中,一般用于表达一个错误的响应信息。
@ApiModel:
描述一个Model的信息
这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述时。
表明这是一个被swagger框架管理的model,用于class上。
@ApiModelProperty:
描述一个model的属性,就是标注在被标注了@ApiModel的class的属性上,
这里的value是对字段的描述,example是取值例子。
Swagger2配置:
@EnableSwagger2
@Configuration
public class SwaggerConfiguration {
@Bean
public Docket haloDefaultApi() {
return buildApiDocket("content",
"api.content",
"/api/content/**");
}
@Bean
public Docket haloAdminApi() {
return buildApiDocket("admin",
"api.admin",
"/api/admin/**");
}
private Docket buildApiDocket(@NonNull String groupName, @NonNull String basePackage, @NonNull String antPattern) {
Assert.hasText(groupName, "Group name must not be blank");
Assert.hasText(basePackage, "Base package must not be blank");
Assert.hasText(antPattern, "Ant pattern must not be blank");
return new Docket(DocumentationType.SWAGGER_2)
.groupName(groupName)
.select()
.apis(RequestHandlerSelectors.basePackage(basePackage))
.paths(PathSelectors.ant(antPattern))
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API Documentation")
.description("Documentation for API")
.version("1.0")
.build();
}
}
启动后访问:
http://localhost:8080/swagger-ui.html
@EnableWebMvc 用于导入 Spring Web MVC configuration(配置类 @Configuration 上)
将此注释添加到 @Configuration 类将导入来自 WebMvcConfigurationSupport 的 Spring MVC配置。
@EnableWebMvc == @Import({DelegatingWebMvcConfiguration.class})
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "controller")
@PropertySource(value = "classpath:application.yaml", ignoreResourceNotFound = true, encoding = "UTF-8")
public class WebMvcAutoConfiguration implements WebMvcConfigurer {
//文件协议
private static final String FILE_PROTOCOL = "file:///";
//配置信息实体
private final HaloProperties haloProperties;
//自动注入HaloProperties
public WebMvcAutoConfiguration(HaloProperties haloProperties) {
this.haloProperties = haloProperties;
}
/**
* Spring Boot底层通过HttpMessageConverters(依靠Jackson库)将Java实体类输出为JSON格式。
*
* MappingJackson2HttpMessageConverter可以将Java对象转换为application/json。
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.stream()
.filter(c -> c instanceof MappingJackson2HttpMessageConverter)
// ifPresent():如果存在一个值,则使用该值执行给定的操作,否则什么也做不成
.findFirst().ifPresent(converter ->
{
// MappingJackson2HttpMessageConverter:读写Json转换器
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter;
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
// JsonComponentModule 来扫描被 @JsonComponent 注解的类,
// 并自动注册 JsonSerializer 和 JsonDeserializer。
JsonComponentModule module = new JsonComponentModule();
// addSerializer():为序列化模块添加自定义序列化程序来处理特定类型的值。
// PageJacksonSerializer:Page对象的序列化
module.addSerializer(PageImpl.class, new PageJacksonSerializer());
// builder.modules():指定序列化模块
ObjectMapper objectMapper = builder.modules(module).build();
// 设置自定义 objectMapper,未设置则使用默认 objectMapper
mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
});
}
/**
* 自定义参数处理器
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new AuthenticationArgumentResolver());
}
/**
* 配置静态资源路径
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String workDir = FILE_PROTOCOL + haloProperties.getWorkDir();
//映射 /** 的请求到 addResourceLocations() 指定的目录
registry.addResourceHandler("/**")
.addResourceLocations(workDir + "templates/themes/")
}
/**
* 添加转换器(Converter)和格式器(Formatters)
*/
@Override
public void addFormatters(FormatterRegistry registry) {
//ConverterFactory:range范围转换器的工厂(可以将对象从S转换为R的子类型)
registry.addConverterFactory(new StringToEnumConverterFactory());
}
/**
* 配置 freemarker
*/
@Bean
public FreeMarkerConfigurer freemarkerConfig(HaloProperties haloProperties) throws IOException, TemplateException {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
//设置模板路径与字符集
configurer.setTemplateLoaderPaths(FILE_PROTOCOL + haloProperties.getWorkDir() + "templates/", "classpath:/templates/");
configurer.setDefaultEncoding("UTF-8");
Properties properties = new Properties();
properties.setProperty("auto_import", "/common/macro/common_macro.ftl as common,/common/macro/global_macro.ftl as global");
configurer.setFreemarkerSettings(properties);
return configurer;
}
/**
* 配置视图解析器来转换基于字符串的视图名称
*/
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setCache(false);
resolver.setSuffix(HaloConst.SUFFIX_FTL);
resolver.setContentType("text/html; charset=UTF-8");
registry.viewResolver(resolver);
}
}
@PropertySource 加载指定的配置文件到 Spring 的 Environment 中(配置类 @Configuration 上)
@PropertySource(value = "classpath:application.yaml",
ignoreResourceNotFound = true, encoding = "UTF-8") //true表示属性源是可选的
用于 PropertySource 在 Spring 的上 添加 Environment。与 @Configuration 类一起使用。
获取配置文件中的值通过 Environment 具体使用方法:
@Autowired
private Environment env;
或者
使用 @value 注解,从配置文件读取值:
@Value("${test.value}")
HandlerMethodArgumentResolver 自定义参数解析
自定义解析器需要实现 HandlerMethodArgumentResolver 接口。
实现自定义参数解析器步骤:1、自定义注解 2、自定义参数解析器 3、注册 4、在需要注入属性的 controller 添加注解
自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface UserToken {String value() default "user";}
自定义参数解析器:
@Component
public class AuthenticationArgumentResolver implements HandlerMethodArgumentResolver {
/**
* 解析器是否支持当前参数
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 指定参数如果被应用 UserToken 注解,则使用该解析器。
// 如果直接返回true,则代表将此解析器用于所有参数
return parameter.hasParameterAnnotation(UserToken.class);
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {}
}
注册:
public class WebMvcAutoConfiguration implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new AuthenticationArgumentResolver());
}
}
序列化和反序列化
层次低的一种是 Byte <---> Message,二进制与程序内部消息对象之间的转换,就是常见的序列化/反序列化。
另外一种是 Message <---> Message,程序内部对象之间的转换,比较高层次的序列化/反序列化。
Http序列化和反序列化(高层次)的核心是HttpMessageConverter。
@JsonSerialize @JsonDeserialize @JsonComponent
如果使用 Jackson 序列化和反序列化 JSON 数据,
您可能需要编写自己的 JsonSerializer 和 JsonDeserializer 类。
自定义序列化程序通常通过模块向 Jackson 注册,
但 Spring Boot 提供了另一种 @JsonComponent 注释,可以更容易地直接注册 Spring Beans。
您可以直接在 JsonSerializer 或 JsonDeserializer 实现上使用 @JsonComponent 注释。
您还可以在包含 JsonSerializer 或 JsonDeserializer 作为内部类的类上使用它。
@JsonSerialize:
可以实现数据转换功能,此注解用于属性或者 getter() 方法上。
@JsonDeserialize:
此注解用于属性或者 setter() 方法上,用于在反序列化时可以嵌入我们自定义的代码。
@JsonComponent:
注释允许我们将带注释的类公开为Jackson序列化器和/或反序列化器,而无需手动将其添加到ObjectMapper。
@JsonSerialize(using = JsonDateSerialize.class)
@JsonDeserialize(using = JsonDateDeserialize.class)
private Date birthday;