# flyingbearcloud **Repository Path**: wangfengbj/flyingbearcloud ## Basic Information - **Project Name**: flyingbearcloud - **Description**: spring生态圈代码,SpringBoot-2.7.X、SpringCloud-2021.0.3 - **Primary Language**: Java - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2022-08-14 - **Last Updated**: 2024-10-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: Java, Spring, SpringBoot, SpringCloud ## README # FlyingBearCloud ## 介绍 Spring系列代码 ## 官方文档 1. SpringBoot [文档](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/) 2. SpringBootStarts [列表](https://docs.spring.io/spring-boot/docs/2.5.0/reference/htmlsingle/#using.build-systems.starters) [源码](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-starters) 3. SpringBootAutoConfiguration [列表](https://docs.spring.io/spring-boot/docs/2.7.2/reference/html/auto-configuration-classes.html#appendix.auto-configuration-classes) 4. [springCloudAlibaba版本对应](https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E) 5. [SpringGuides](https://spring.io/guides) 6. [Spring对JDK版本支持](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Versions#jdk-version-range) 7. [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.6.10/maven-plugin/reference/html/) 8. [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.6.10/maven-plugin/reference/html/#build-image) 9. [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/2.6.10/reference/htmlsingle/#using.devtools) 10. [Spring Configuration Processor](https://docs.spring.io/spring-boot/docs/2.6.10/reference/htmlsingle/#appendix.configuration-metadata.annotation-processor) 11. [OAuth2 Resource Server](https://docs.spring.io/spring-boot/docs/2.6.10/reference/htmlsingle/#web.security.oauth2.server) 12. [OAuth2 Client](https://docs.spring.io/spring-boot/docs/2.6.10/reference/htmlsingle/#web.security.oauth2.client) 13. [Validation](https://docs.spring.io/spring-boot/docs/2.6.10/reference/htmlsingle/#io.validation) 14. [Quartz Scheduler](https://docs.spring.io/spring-boot/docs/2.6.10/reference/htmlsingle/#io.quartz) 15. [Cloud Bootstrap](https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/) 16. [Spring REST Docs](https://docs.spring.io/spring-restdocs/docs/current/reference/html5/) 17. [Eureka Server](https://docs.spring.io/spring-cloud-netflix/docs/current/reference/html/#spring-cloud-eureka-server) 18. [Configure the Spring AOT Plugin](https://docs.spring.io/spring-native/docs/0.11.5/reference/htmlsingle/#spring-aot-maven) ## 服务说明 ### 配置中心config【端口:8006】 配置中心从git读取配置文件,刷新微服务 ### 监控admin 【端口:8003】 1. [网站](https://github.com/codecentric/spring-boot-admin) ,服务监控,服务在线状态,日志,JVM等信息 2. http://localhost:8003/ 查看服务状态 ### 注册中心eureka【端口:8000】 开启SpringSecurity登录认证:admin admin [访问](http://localhost:8000) springSecurity的formLogin自动配置的url: 1. /login (get):登录页面 2. /login (post):登录接口,在登录页面点击登录,会请求这个接口 3. /login?error:用户名或密码错误,跳转到该页面 4. /:登录成功后,默认跳转的页面,/会重定向到index.html,这个页面要你自己实现 5. /logout(post):注销接口 6. /login?logout:注销成功跳转页面 ### 内嵌服务Embedded 1. Redis 【单机端口6379】 2. Kafka ### gateway网关 【端口9000】 0. 核心流程:client->HttpWebHandlerAdapter组装网关上下文->DispatcherHandler遍历mapping找到handler->RoutePredicateHandlerMapping负责路由查找->FilteringWebHandler创建过滤器链->执行filter->到达服务->返回结果给client 主要配置:GatewayAutoConfiguration 1. API网关应具备路由转发、负载均衡[需要注册中心]、限流、熔断、权限控制、轨迹追踪和实时监控等功能;Finchley之前使用Zuul1作为API网关,之后更推荐使用Gateway 2. 负载均衡LoadBalancerClientFilter:lb开头;底层以前ribbon、现在loadbalancer 3. yml全局超时配置、局部超时配置 4. yml跨域配置或者启动类代码跨域配置 5. RedisRateLimiter限流【令牌桶限流】:pom、yml、启动类 6. Actuator监控:pom、yml;访问/actuator/gateway/routes/laker;全部详细路由信息禁用【spring.cloud.gateway.actuator.verbose.enabled=false】 ``` /actuator/gateway/routes/{id} ,method=[DELETE] 删除单个路由 /actuator/gateway/routes/{id},method=[POST] 新增单个路由 /actuator/gateway/routes/{id},method=[GET] 查看单个路由 /actuator/gateway/routes ,method=[GET] 查看路由列表 /actuator/gateway/refresh,method=[POST] 路由刷新 /actuator/gateway/globalfilters,method=[GET]获取全局过滤器列表 /actuator/gateway/routefilters,method=[GET] 路由过滤器工厂列表 ``` 7. 熔断降级:旧Hystrix、新CircuitBreaker【有重试、限速功能】、Sentinel org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j spring.cloud.circuitbreaker.resilience4j.enabled: true ``` filters: -name: CircuitBreaker # 设置熔断器 args: name: testCircuitBreaker # 熔断器名字,无所谓 fallbackUri: forward:/fallbackCircuitBreaker # 熔断之后跳转,本项目或其他项目配置 ``` 8. 重试【也算断路器的一种】:yml 9. 503改404:spring.cloud.gateway.loadbalancer.use404=true 10. swagger2的支持 11. 自定义全局异常 12. 全局过滤器、局部过滤器、免认证 13. 请求头修改、body内容获取 14. 灰度发布通过权重实现 ``` - id: weight2 uri: http://localhost:6601 predicates: - Path=/api/** - Weight=group1,2 filters: - StripPrefix=1 - id: weight8 uri: http://localhost:6602 predicates: - Path=/api/** - Weight=group1,8 filters: - StripPrefix=1 - AddRequestHeader= X-Request-id, 99999 # 增加请求头、请求参数 - AddRequestHeader= X-Request-author, kevin - AddRequestParameter= param-id,99999 - AddRequestParameter= param-author, kevin - AddResponseHeader=rep-id, 99999 - AddResponseHeader=req-author,kevin - SetRequestHeader=X-Request-id,9999 # 设置请求头,没有则新增,有则修改 - RemoveRequestHeader= X-Request-id # 移除请求头 - RemoveRequestParameter=X-Request # 请求参数 - MapRequestHeader=from-Header,to-Header # 先从header取from-Header,如果有则赋值给to-Header,如果没from-Header则无效果 - RedirectTo=302,http://www.baidu.com # 状态码跳转地址 - PrefixPath=/prefix # 增加前缀路径 - name: RequestSize # 设置请求大小 args: # 控制请求的大小,超过则返回413.请求最大默认5000000 约5M maxSize: 1000 #1KB - SaveSession # 集成SpringSession来实现共享Session功能,如果还使用Spring Security框架。如果希望安全验证信息可以转发到远程应用,那么这个配置是必须的 ``` 15. 执行核心过滤器 GatewayLoadBalancerClientAutoConfiguration中LoadBalancerClientFilter负载均衡,RibbonLoadBalancerClient实现LoadBalancerClient NettyRoutingFilter执行服务 NettyWriteResponseFilter回写响应 ### JPA多数据源MultipleDataSource 【端口9002】 1. JpaRepository接口继承->PagingAndSortingRepository接口继承->CrudRepository接口继承->Repository接口 2. 整合H2 [访问H2控制台](http://localhost:9002/h2) 3. 整合sqlite [访问JPA整合Sqlite](http://localhost:9002/jpa10) 4. jpa+hibernate [JpaRepository](http://localhost:9002/jpa1) [Repository+@Query](http://localhost:9002/jpa2) [CrudRepository](http://localhost:9002/jpa3) [PagingAndSortingRepository](http://localhost:9002/jpa4) [JpaSpecificationExecutor](http://localhost:9002/jpa5) 5. 整合servlet、filter、listener [访问DemoServlet](http://localhost:9002/demo) [访问WfServlet](http://localhost:9002/wf) 6. 整合SpringCache【有配置类】 [缓存然后查看redis](http://localhost:9002/jpa0) 默认提供StringRedisTemplate的采用String的序列化策略只支持存字符串,RedisTemplate采用JDK的序列化策略支持存对象;SpringCache对读模式都进行处理, 解决了缓存击穿,缓存穿透,缓存雪崩的问题,但是对写模式并没有去处理。缓存穿透通过缓存null值,缓存击穿sync=true加锁,缓存雪崩时间加随机数。写模式引入 Canal感知到mysql的更新去更新或者读多写多的直接去数据库查询。 @CacheEvict(value = "student",allEntries = true) allEntries=true表示删除student分区下所有数据 @CacheEvict(value = "student",key = "'saveCache01'") 注意单引号 @Caching(evict = {@CacheEvict(value = "student", key = "'saveCache01'"), @CacheEvict(value = "student", key = "'saveCache02'")}) 7. 整合redis【有配置类RedisConfig】 (1)Jedis是Redis官方推荐的面向Java的操作Redis的客户端,但是直连redis非线程安全,需要使用连接池 (2)RedisTemplate是SpringDataRedis中对JedisApi的高度封装 (3)SpringDataRedis相对于Jedis来说可以方便地更换Redis的Java客户端,比Jedis多了自动管理连接池的特性,方便与其他Spring框架进行搭配使用如:SpringCache (4)Lettuce的连接是基于Netty,多个线程间可以并发访问,StatefulRedisConnection是线程安全的 (5)RedisAutoConfiguration会创建RedisTemplate和StringRedisTemplate;重新定义RedisTemplate,定义key和value序列化和反序列化策略因为默认采用jdk的序列化和反序列策略 8. 整合thymeleaf【这里使用error.html,使用方法也在该页面】 官方推荐的,通过他特定语法对html的标记做渲染,如果引入必须把html页面放到templates,不引入可以放到static下 9. 整合Scheduled【注解方式】 // @EnableScheduling // 开启Scheduled,如果没有执行可以添加该注解,默认不需要 10. 多数据源另外的实现方式 ``` /** *实现注解选择数据源 */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } } @Before(value = "@annotation(source)") ``` ### 认证服务Oauth21【端口9004】 1. FilterChainProxy入口、Authentication[认证]、Authorization[授权] 2. JWT=header[声名签名算法]+payload[明文数据]+signture[签名部分JWS];JWK是JWT的密钥、JWE是payload加密的JWT、JWKset非对称加密 3. 令牌管理服务:OAuth2AuthorizationService、客户端id、用户名与权限关联关系管理:OAuth2AuthorizationConsentService、客户端管理服务:RegisteredClientRepository 4. org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration 5. 获取code[client_secret可以不携带]:http://127.0.0.1:9004/oauth2/authorize?client_id=userClient&response_type=code&scope=message.read&redirect_uri=http://www.baidu.com 6. 获取token:http://127.0.0.1:9004/oauth2/token?grant_type=authorization_code&redirect_uri=http://www.baidu.com&code= postman认证选择basic auth输入userClient/123456 7. 刷新token:http://127.0.0.1:9004/oauth2/token?grant_type=refresh_token&refresh_token= postman认证选择basic auth输入userClient/123456 8. 获取令牌信息:http://127.0.0.1:9004/oauth2/introspect?token_type_hint=access_token&token=xxx postman认证选择basic auth输入userClient/123456 9. 撤销token:http://127.0.0.1:9004/oauth2/revoke?token_type_hint=access_token&token=xxx http://127.0.0.1:9004/oauth2/revoke?token_type_hint=refresh_token&token=xxx postman认证选择basic auth输入userClient/123456 10. 获取加密公钥:/oauth2/jwks 11. OAuth2AuthorizationCodeRequestAuthenticationProvider.requireAuthorizationConsent是否需要授权同意判断逻辑源码 12. 原理 ``` 1.由OAuth2AuthorizedClientArgumentResolver#resolveArgument 解析 @RegisteredOAuth2AuthorizedClient注解 组装 OAuth2AuthorizeRequest 2.OAuth2AuthorizedClientManager#authorize 将 OAuth2AuthorizeRequest 转换为 OAuth2AuthorizationContext 3.OAuth2AuthorizedClientProvider#authorize 调用 OAuth2AccessTokenResponseClient#getTokenResponse 向授权服务器发起请求 `http://localhost:9000/oauth2/token`获取 OAuth2AccessTokenResponse,并将OAuth2AccessTokenResponse 回填至 OAuth2AuthorizedClient参数中 4.然后使用webclient将获取到的OAuth2AuthorizedClient作为请求参数调用资源服务器 ``` ### 客户端 Oauth21-client 【端口9006】 1. 自动配置类 OAuth2ClientAutoConfiguration ``` /** * OAuth2ClientRegistrationRepositoryConfiguration中 * ClientRegistrationRepository:维护ClientRegistration客户端注册信息 * SpringBoot默认提供InMemoryClientRegistrationRepository */ @Bean @ConditionalOnMissingBean(ClientRegistrationRepository.class) InMemoryClientRegistrationRepository clientRegistrationRepository(OAuth2ClientProperties properties) { List registrations = new ArrayList<>( OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(properties).values()); return new InMemoryClientRegistrationRepository(registrations); } /** * OAuth2WebSecurityConfiguration中 * OAuth2AuthorizedClientService:维护OAuth2AuthorizedClient即 ClientRegistration关联AccessToken等信息 * SpringBoot默认注册InMemoryOAuth2AuthorizedClientService,即基于内存管理 */ @Bean @ConditionalOnMissingBean OAuth2AuthorizedClientService authorizedClientService(ClientRegistrationRepository clientRegistrationRepository) { return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository); } /** * OAuth2WebSecurityConfiguration中 * 跟OAuth2AuthorizedClientService类似,主要是在Request之间维护未认证的OAuth2AuthorizedClient * SpringBoot默认注册AuthenticatedPrincipalOAuth2AuthorizedClientRepository */ @Bean @ConditionalOnMissingBean OAuth2AuthorizedClientRepository authorizedClientRepository(OAuth2AuthorizedClientService authorizedClientService) { return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService); } OAuth2AuthorizationRequestRedirectFilter 1. 该过滤器处理 /oauth2/authorization 路径,主要场景是默认或手动配置的 oauth2login 路径 2. 它会将上述路径处理转发给 认证中心 对应的路径 /oauth2/authorize OAuth2AuthorizationCodeGrantFilter 1. 该过滤器负责处理 认证中心 的授权码回调请求,主要场景就是 认证中心 生成授权码后的回调请求 2. 这里会进行诸如 回调地址重定向、OAuth2AuthorizedClient 的创建等处理 OAuth2LoginAuthenticationFilter 1. 处理 /login/oauth2/code/* 路径,默认的授权码回调路径,此过滤器会向 认证中心 请求对应的 Token 信息 DefaultLoginPageGeneratingFilter 1. 用于生成默认登录页面。 ``` ### 资源服务器Oauth21-resource 【端口9005】 1. OAuth2ResourceServerJwtConfiguration类基于OAuth2ResourceServerProperties配置,配置JWTToken解码的JwtDecoder: 使用AuthorizationServer的JWKSetURI端点进行解码,使用spring.security.oauth2.resourceserver.jwt.jwk-set-uri配置; 使用AuthorizationServer的keyStore的公钥进行解码,使用spring.security.oauth2.resourceserver.jwt.public-key-location配置; ### 模板服务Template【端口9001】 1. 集成web [首页](http://localhost:9001/index) 2. 集成SpringBootTest 3. 集成actuator [健康状况](http://localhost:9001/actuator/health) 4. 使用@Configuration(proxyBeanMethods = false) proxyBeanMethods = false,同一个Configuration中如果存在bean之间方法调用每调用一次就是一个新对象,如果内部没有相互调用设置为false提高SpringBoot加载速度 5. 集成SpringSecurity、自定义登录页面、自定义User、基于内存或者基于数据库操作;user/123456 [用户信息](http://localhost:9001/getUser) DelegatingFilterProxy包裹FilterChainProxy执行SecurityFilterChain 默认配置会创建一个springSecurityFilterChain的Filter【保护URL、验证用户名密码、重定向登录表单等】 SecurityAutoConfiguration、SecurityFilterAutoConfiguration 默认情况下SpringSecurity会跟session关联,可以使用分布式session解决分布式中认证和鉴权问题 RequestAttributeSecurityContextRepository SecurityContextHolderFilter ``` // SpringSecurity跟SpringMVC集成,没有使用引导【SpringBoot】。@EnableWebSecurity // Spring Security provides the configuration using Spring MVC’s WebMvcConfigurer. This means that // if you are using more advanced options, like integrating with WebMvcConfigurationSupport directly, // then you will need to manually provide the Spring Security configuration. // 配置文件相当于web.xml,让Spring容器加载redis等 public class SecurityInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class[] getRootConfigClasses() { return new Class[] { WebSecurityConfig.class }; } @Override protected Class[] getServletConfigClasses() { return new Class[] { RootConfiguration.class, WebMvcConfiguration.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } } ``` 主要filter顺序:ForceEagerSessionCreationFilter->AbstractPreAuthenticatedProcessingFilter->UsernamePasswordAuthenticationFilter->DigestAuthenticationFilter->BasicAuthenticationFilter->SessionManagementFilter->ExceptionTranslationFilter->FilterSecurityInterceptor[验证身份]->SwitchUserFilter DaoAuthenticationProvider是一种AuthenticationProvider利用UserDetailsService和PasswordEncoder来验证用户名和密码的实现。UsernamePasswordAuthenticationToken->AuthenticationManager->ProviderManager->AuthenticationProvider[DaoAuthenticationProvider] SecurityContextRepository接口->HttpSessionSecurityContextRepository将SecurityContext相关联HttpSession;NullSecurityContextRepository不会关联到 HttpSession使用OAuth可以使用这种;RequestAttributeSecurityContextRepository保存SecurityContext为请求属性 6. 集成H2数据库 [控制台](http://localhost:9001/h2) jdbc:h2:mem:wf sa 7. 集成SpringSession,实现JSON序列化 RedisSessionRepository负责session操作 RedisOperations负责序列化和反序列化 @EnableConfigurationProperties(RedisSessionProperties.class) // 使用RedisSession配置 @EnableSpringHttpSession // 使用spring封装实现的session,@EnableConfigurationProperties+@EnableSpringHttpSession自定义=@EnableRedisHttpSession @EnableRedisHttpSession,创建一个名为springSessionRepositoryFilter ``` // SpringSession集成HttpSession,不使用SpringBoot @EnableRedisHttpSession public class Config { @Bean public LettuceConnectionFactory connectionFactory() { return new LettuceConnectionFactory(); } } // Servlet容器初始化,向Servlet容器中添加springSessionRepositoryFilter,不使用SpringBoot public class SessionInitializer extends AbstractHttpSessionApplicationInitializer { } // Servlet容器初始化,添加springSecurityFilterChain,不使用SpringBoot public class SessionSecurityInitializer extends AbstractSecurityWebApplicationInitializer { // AbstractAnnotationConfigDispatcherServletInitializer如果使用,就不需要这个了 public SessionSecurityInitializer() { super(SecurityCommonConfig.class, SessionConfig.class); } } // Servlet容器初始化,集成MVC,不使用SpringBoot public class SecurityInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class[] getRootConfigClasses() { return new Class[] { Config.class, WebSecurityConfig.class, HttpSessionConfig.class }; } @Override protected Class[] getServletConfigClasses() { return new Class[] { RootConfiguration.class, WebMvcConfiguration.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } } ``` ### 自动生成代码 autoCode【端口:9007】 1. [AJ-Captcha验证码](https://gitee.com/anji-plus/captcha) 2. SliderCaptcha基于前端js生成行为验证码 3. [tianaiCaptcha](https://gitee.com/tianai/tianai-captcha) 4. mybatisPlus实体类注解:@TableName(value="sys_org")、@TableId(value = "id", type = IdType.AUTO) ### 测试生成代码服务 autoCodeTest 【端口:8888】 查看暴露路径:http://localhost:8888/actuator 追踪启动信息:http://localhost:8888/actuator/startup 下载dump文件:http://localhost:8888/actuator/heapdump 查看应用信息:http://localhost:8888/actuator/info ### kafka[端口9003] 1. kerberos认证路径问题解决、生产者和消费者、 2. KafkaMessageListenerContainer.doPoll->KafkaConsumer.poll->KafkaConsumer.updateAssignmentMetadataIfNeeded[自动提交入口] ### officeToPdf【端口:9004】 1. 使用office转换文档为pdf,建议使用office2016以上,dll文件放到jre/bin下 ### page页面 【端口:8888】 ### 定时任务管理quartz【端口:9008】 1. QuartzAutoConfiguration中SchedulerFactoryBean调度器创建,使用SpringBeanJobFactory工厂 2. MethodInvokingJobDetailFactoryBean使用jdbc时候会报无法序列化问题因此建议JobDetailFactoryBean 3. spring-boot-starter-validation验证框架 @Valid用在model中有model的上面 @Validated:Spring Validator,可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上,不支持嵌套检测 @Valid:Hibernate validation,可以用在方法、构造函数、方法参数和成员属性(字段)上,支持嵌套检测 分组校验、自定义枚举校验@EnumCheck 4. 单独使用quartz代码 5. pagehelper基于ThreadLocal,如果报错会影响其它操作,增加CommonFilter开始时候清除分页 6. ErrorConfig错误映射到页面 ### seata 【阿里分布式事务】 [account8013]、[business8014]、[order8015]、[storage8016] ### mybatis的例子【端口:7777,比较老的cloud】 swagger2、druid及监控日志、mybatis及分页、logback配置、devtools随机端口、切面编程、InitResource初始化资源、defaultServlet找不到就抛出异常、 JacksonNullConfig对null处理、MyHealthCheckHandler自定义健康状况、MyWebMvcConfigurer自定义拦截器、TrimEditorConfig截取前端传字符串前后空格、配置错误对应页面、 hystrix方法熔断和调用熔断、SpringCache、SpringIntegration分布式锁、jedis锁、redission锁 1. druid监控:http://localhost:9000/druid/login.html 2. swagger2:http://localhost:8888/swagger-ui.html http://localhost:9000/swagger-ui.html ## 服务能力 1. hystrix熔断降级 2. actuator 3. SpringSession 4. swagger2支持 5. logback日志配置 logback-spring.xml,SpringBoot会默认加载此文件,为什么不配置logback.xml,因为logback.xml会先application.properties加载, 而logback-spring.xml会后于application.properties加载,这样我们在application.properties文中设置日志文件名称和文件路径才能生效 6. docker打包插件 7. admin客户端 8. 单元测试 @RunWith(SpringJUnit4ClassRunner.class) 让junit和spring整合 @SpringBootTest(classes={启动类.class}) 9. SpringBootMVC全局异常处理:org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration (1)src/main/resources/templates目录下创建error.html页面,th:text="${exception}" (2)单@ExceptionHandle在Controller中 (3)全局异常处理@ControllerAdvice+@ExceptionHandler (4)SimpleMappingExceptionResolver处理异常,在@Configuration全局类(只需要这一注解)中,写处理方法 (5)实现HandlerExceptionResolver接口,@Configuration标注类,实现resolverException方法 ## 初始化顺序 构造器-->自动注入-->PostConstrut-->InitializingBean-->init方法-->CommandLineRunner接口方法 ## FastJson使用 ``` @JSONField(format = "yyyy-MM-dd HH:mm:ss") private Date created; ``` ```java import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; /** * FastJson生效,以及中Null处理 */ @Configuration public class MyFastJsonConfig extends WebMvcConfigurationSupport { @Override public void configureMessageConverters(List> converters) { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures( // 保留map空的字段 SerializerFeature.WriteMapNullValue, // 将String类型的null转成"" SerializerFeature.WriteNullStringAsEmpty, // 将Number类型的null转成0 SerializerFeature.WriteNullNumberAsZero, // 将List类型的null转成[] SerializerFeature.WriteNullListAsEmpty, // 将Boolean类型的null转成false SerializerFeature.WriteNullBooleanAsFalse, // json格式化 // SerializerFeature.PrettyFormat, // 避免循环引用 SerializerFeature.DisableCircularReferenceDetect); // config.setDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); // 全局日期格式化 converter.setFastJsonConfig(config); // 设置编码 converter.setDefaultCharset(Charset.forName("UTF-8")); List mediaTypeList = new ArrayList<>(); // 解决中文乱码问题,相当于在Controller上的@RequestMapping中加了个属性produces = "application/json" mediaTypeList.add(MediaType.APPLICATION_JSON); converter.setSupportedMediaTypes(mediaTypeList); converters.add(converter); } } ``` ## 新知识 容器测试:testcontainers 原生镜像:[SpringNative](https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/) SpringMVC处理程序映射匹配请求路径的默认策略已从AntPathMatcher更改为PathPatternParser