SpringMVC学习之Exception处理

背景 开发过程中,会出现很多异常情况,比如RPC调用异常、请求参数异常,SpringMVC是如何处理异常信息的? Spring处理异常的方式 Spring采用了全局的异常捕获统一处理的方式,虽然JAVA的异常机制一直有争议,但是Spring还是选择基于实际开发需要使用抛异常后捕获统一处理的方式 HandlerExceptionResolver登场 HandlerExceptionResolver 是SpringMVC提供的解析Handler调用过程抛出异常的解析器,只提供了一个解析异常的方法 resovleException Spring提供了哪些ExceptionResolver? 经典的Interface-Abstract方式的实现类 Resolver Desc SimpleMappingExceptionResolver 提供exception class name到view的映射 DefaultHandlerExceptionResolver 默认Resolver实现,用于解析标准的SpringMVC异常并转换成对应的Http状态码 ResponseStatusExceptionResolver 基于 @ResponseStatus 注解来映射异常与Http状态码 ExceptionHandlerExceptionResolver 基于 @ExceptionHalder 注解来解析处理异常信息 直接实现HandlerExceptionResolver的类 Resolver Desc DefaultErrorAttributes 默认错误属性实现 HandlerExceptionResolverComposite 代理其它Resolver集合的ExceptionResolver HandlerExceptionResolverComposite 中包含了一个解析列表,可以判断是会排序后顺序调用,以找到第一个可以处理的Resolver 具体异常处理流程 异常处理的核心逻辑都在 processHandlerException 方法中,Spring处理完请求后,如果有异常抛出,则会把异常信息传给 processHandlerException 方法, processHandlerException 遍历持有的 handlerExceptionResolvers 进行对异常的解析,如果解析成功则直接返回对应的 ModelAndView(此返回与正常的handler处理返回保持了一致) handlerExceptionResolvers 有哪些? 在 SpringMVC启动时会调用 initHandlerExceptionResolvers 方法来查找所有可用的 handlerExceptionResolver 并保存到 handlerExceptionResolvers 变量中。SpringMVC配置了两个 resolver 来提供异常解析 errorAttributes 此Resolver是在 ErrorMvcAutoConfiguration 进行实例化的 此实现的 resolverExcption 方法逻辑简单,直接返回了null,不是关注重点 handlerExceptionResolver 此Resolver真正的实现类为 HandlerExceptionResolverComposite ,也就是持有多个ExceptionResolver列表的 Resolver,它是在 WebMvcConfigurationSupport 实例化的 ...

April 14, 2025 · 1 min · 139 words · tomyli

SpringMVC统一配置接口WebMvcConfigurer功能

接口说明 WebMvcConfigurer是Spring提供的统一配置接口,用于自定义Spring MVC的配置,全局更改服务的行为,提供的可配置项: 方法名称 参数 用途 addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) List<HandlerMethodArgumentResolver> argumentResolvers 添加自定义的 HandlerMethodArgumentResolver 用于解析方法参数。 addCorsMappings(CorsRegistry registry) CorsRegistry registry 配置跨域资源共享 (CORS) addFormatters(FormatterRegistry registry) FormatterRegistry registry 添加自定义的格式化程序和转换器 addInterceptors(InterceptorRegistry registry) InterceptorRegistry registry 添加自定义的拦截器 addRequestMappings(RequestMappingInfo customization, Class<Controller> controllerClass) RequestMappingInfo customization, Class<Controller> controllerClass 关联自定义请求映射到具控制器类 addResourceHandlers(ResourceHandlerRegistry registry) ResourceHandlerRegistry registry 配置资源处理,如静态资源路径 addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) List<HandlerMethodReturnValueHandler> returnValueHandlers 添加自定义的 HandlerMethodReturnValueHandler 用于处理方法返回值 addViewControllers(ViewControllerRegistry registry) ViewControllerRegistry registry 注册视图控制器 configureAsyncSupport(AsyncSupportConfigurer configurer) AsyncSupportConfigurer configurer 配置异步支持 configureContentNegotiation(ContentNegotiationConfigurer configurer) ContentNegotiationConfigurer configurer 配置内容协商策略 configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) DefaultServletHandlerConfigurer configurer 启用默认 Servlet 处理 configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) List<HandlerExceptionResolver> exceptionResolvers 配置异常处理程序 configureMessageConverters(List<HttpMessageConverter<?>> converters) List<HttpMessageConverter<?>> converters 配置自定义的 HttpMessageConverter configurePathMatch(PathMatchConfigurer configurer) PathMatchConfigurer configurer 配置路径匹配规则 configureViewResolvers(ViewResolverRegistry registry) ViewResolverRegistry registry 配置视图解析器 extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) List<HandlerExceptionResolver> exceptionResolvers 扩展异常处理程序 extendMessageConverters(List<HttpMessageConverter<?>> converters) List<HttpMessageConverter<?>> converters 扩展自定义的 HttpMessageConverter extendInterceptors(List<HandlerInterceptor> interceptors) List<HandlerInterceptor> interceptors 扩展拦截器 extendArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) List<HandlerMethodArgumentResolver> argumentResolvers 扩展自定义的 HandlerMethodArgumentResolver 用于解析方法参数。 extendReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) List<HandlerMethodReturnValueHandler> returnValueHandlers 扩展自定义的 HandlerMethodReturnValueHandler 用于处理方法返回值。 extendViewResolvers(List<ViewResolver> viewResolvers) List<ViewResolver> viewResolvers 扩展视图解析器 关联类 WebMvcConfigurationSupport EnableWebMvc 接口常用方法 接口提供了将近20个方法对Spring的配置进行调整,本次只针对常用的Rest接口开发相关内容进行展开学习研究 ...

March 28, 2025 · 3 min · 461 words · tomyli

基于Spring initializr实现自己的项目模板

介绍 先前通过 Apache Maven Archetype 生成了一个项目脚手架1.0版本,模板比较固定,无法根据需要进行灵活定制,经过调研后,发现可基于Spring Starter项目进行定制,脚手架2.0版本也就应运而生。 目标 快速创建最小可运行工程 基础组件依赖管理 版本管理 帮助信息 按需生成项目结构 最终效果 实现 主流程 获取配置 通过请求服务根路径获取脚手架信息,对应接口代码 如请求: http://localhost:8080 会返回以下内容信息 接口返回了服务支持配置的元数据信息 生成工程代码 用户选择配置相应功能后,点击生成按钮,会调用 http://localhost:8080/start.zip 接口将配置信息传给服务,服务根据信息生成代码 核心功能实现 项目工程由以下几方面组成: application.yml文件 工程目录(controller, servier…) auto_publish相关目录 trpc_java.yaml文件 配置相关 日志配置文件 web服务相关 httpApi接口 httpApi实现类StartController Maven依赖管理 主启动程序自定义 测试辅助开发相关自定义 applicationTest 依赖管理 根据现有常用的 Peacock 框架功能包,依赖管理配置以下模块: Starter Integration Provider Data Testing MQ Job 实践 生成一个最小可运行Web应用 命令行快速生成 curl -L 'http://localhost:8080/start.zip?type=peacock-project&bootVersion=1.5.7.RELEASE&groupId=com.yuewen.bookcoop&artifactId=solution_demo&name=solution_demo101&version=1.0.0-SNAPSHOT&language=java&packageName=com.yuewen.bookcoop.solution_demo&javaVersion=1.8&packaging=jar&description=solution_demo101&dependencies=integration-web&dependencies=peacock-test&dependencies=integration-common&dependencies=starter' -o solution_demo.zip 具体的依赖库元信息可以在根路径下请求获得,具体依赖信息为dependencies值对应id的值 IDEA中生成 Idea配置脚手架地址 使用本地地址如: http://localhost:8080 配置工程信息 填写好相关的业务信息与版本信息 选择依赖模块 Web应用需选择以下模块: Peacock Trpc Starter Integration Web Integration Common Peacock Test 选择完成后点击 生成 按钮生成代码 ...

October 15, 2024 · 1 min · 100 words · tomyli

Springwebflux源码学习-服务启动流程

学习目标 理解WebFlux核心组件HttpHandler、WebHandler的创建过程 理解DispatcherHandler如何映射请求url及参数的过程 理解Netty服务的主要启动节点 此次学习的Spring boot版本为2.6.6,对应的Spring webflux版本为5.3.18 入口 Springboot工程入口方法为 SpringApplication.run() ,从此方法开始进行分析。 public static void main(String[] args) { SpringApplication.run(Main.class, args); } 决定启动的web应用类型 整个服务的web应用类型是在构造 SpringApplication 类时进行确定的,具体代码如下: this.webApplicationType = WebApplicationType.deduceFromClasspath(); 判断应用类型的逻辑 org.springframework.web.reactive.DispatcherHandler存在 org.springframework.web.servlet.DispatcherServlet不存在 org.glassfish.jersey.servlet.ServletContainer不存在 即确认webApplicationType为 Reactive if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) { return WebApplicationType.REACTIVE; } 创建具体的ApplicationContext 根据webApplicationType(Reactive)确定创建的ApplicationContext为AnnotationConfigReactiveWebServerApplicationContext,此Context支持 @Component 和 JSR-330规范中 @Inject 形式的依赖注解 SpringAplication.createApplicationContext() switch (webApplicationType) { case SERVLET: return new AnnotationConfigServletWebServerApplicationContext(); case REACTIVE: return new AnnotationConfigReactiveWebServerApplicationContext(); default: return new AnnotationConfigApplicationContext(); } 最主要的ApplicationContext.refresh()方法 refresh的Refresh阶段 刷新操作是在 AbstractApplicationContext 类的refresh方法中进行,在调用invokeBeanFactoryPostProcessors方法时会有对controller注解的扫描与处理 ...

May 24, 2022 · 2 min · 351 words · tomyli