• Halo(二)


    @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;
    
  • 相关阅读:
    [LeetCode] 456. 132 Pattern
    [LeetCode] 606. Construct String from Binary Tree
    [LeetCode] 536. Construct Binary Tree from String
    [LeetCode] 925. Long Pressed Name
    [LeetCode] 652. Find Duplicate Subtrees
    [LeetCode] 743. Network Delay Time
    [LeetCode] 1209. Remove All Adjacent Duplicates in String II
    [LeetCode] 1047. Remove All Adjacent Duplicates In String
    [LeetCode] 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit
    [LeetCode] 859. Buddy Strings
  • 原文地址:https://www.cnblogs.com/loveer/p/11875388.html
Copyright © 2020-2023  润新知