`

使用 SpringMVC 优雅的处理异常

阅读更多

1. 背景

小黄:

不同的 Controller 发生不同的异常, 我想要做不同的动作, 能不能简单配置优雅的实现?

比如 com.feilong.psi.controller.channel.ChannelController 如果出现com.feilong.psi.exception.SignNotEqualsException 那么跳转到404 页面 如果出现com.feilong.psi.exception.TradeStatusCanNotPayException 那么跳转到 首页

2. 实现

good question, 一看小黄就是个有追求的孩子, let's go~~

我们先来看如何实现,再来看原理

第1步 , 项目依赖 feilong spring

项目 pom.xml 添加 feilong spring 依赖

注: feilong spring 4.0.3 ,need spring 4 version

<project>
	....
	<properties>
		<version.feilong-spring>4.0.3</version.feilong-spring>
		....
	</properties>

	....
	<repositories>
		<repository>
			<id>feilong-repository</id>
			<url>https://raw.github.com/venusdrogon/feilong-platform/repository</url>
		</repository>
	</repositories>

	....
	<dependencies>
		....
		<dependency>
			<groupId>com.feilong.platform.spring</groupId>
			<artifactId>feilong-spring-all</artifactId>
			<version>${version.feilong-spring}</version>
		</dependency>
		....
	</dependencies>
	....

第2步 使用 com.feilong.spring.web.servlet.handler.SimpleMappingHandlerMethodExceptionResolver

新建个 springmvc-pay-channel-exception.xml 文件

...
<!-- 通道异常解决器 -->
<bean id="channelExceptionResolver" class="com.feilong.spring.web.servlet.handler.SimpleMappingHandlerMethodExceptionResolver">
    <property name="order" value="1" />
    <property name="preventResponseCaching" value="true" />
    <property name="mappedHandlerClasses">
        <array>
            <value>com.feilong.psi.controller.channel.ChannelController</value>
        </array>
    </property>

    <property name="exceptionMappings">
        <props>
            <!-- 安全签名参数不正确的异常. -->
            <prop key="com.feilong.psi.exception.SignNotEqualsException">redirect:/errors/404</prop>

            <!-- 交易的状态不能去支付的异常.
             since 20180920 change from 500 to /
             -->
            <prop key="com.feilong.psi.exception.TradeStatusCanNotPayException">redirect:/</prop>
        </props>
    </property>
</bean>
...

第3步 加载上面配置的 channelExceptionResolver

springmvc-exceptionResolver.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <import resource="classpath:springmvc/pay/springmvc-pay-channel-exception.xml" />
	<import resource="classpath:springmvc/pay/springmvc-pay-redirect-exception.xml" />
	<import resource="classpath:springmvc/pay/springmvc-pay-notify-exception.xml" />

    <!-- exceptionResolver -->
    <bean id="exceptionResolver" class="com.baozun.exception.ExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="com.baozun.exception.BusinessException">forward:/errors/error</prop>
                <prop key="java.lang.Throwable">forward:/errors/error</prop>
            </props>
        </property>
    </bean>

</beans>

注意 要保证公司全局的 com.baozun.exception.ExceptionResolver 在最下面

3. 原理

feilong com.feilong.spring.web.servlet.handler.SimpleMappingHandlerMethodExceptionResolver 借鉴于 SimpleMappingExceptionResolver , 并在此基础上进行了扩展 ,参见扩展5

4. 扩展- 使用自定义 view

小李:

我看到在上面的 xml 中可以直接配置 redirect:/errors/404 就跳转到404 页面, 我现在有个支付通知controller , 如果业务正常处理, 响应支付网关 Continnue 字符串, 如果有异常 我要返回 stop 字符串, 这个 stop 我想在 xml 中配置 该如何实现呢?

good question

你可以使用feilong spring 自定义的 printwrite view

springmvc-viewResolver-printwrite.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

    <bean class="com.feilong.spring.web.servlet.view.printwriter.PrintWriterViewResolver">
        <property name="order" value="-1" />
        <property name="prefix" value="printwrite:" />
    </bean>
</beans>

springmvc-pay-notify-exception.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

    <!-- doku notify异常解决器 -->
    <bean id="dokuNotifyExceptionResolver" class="com.feilong.spring.web.servlet.handler.SimpleMappingHandlerMethodExceptionResolver">
        <property name="order" value="1" />
        <property name="preventResponseCaching" value="true" />
        <property name="mappedHandlerClasses">
            <array>
                <value>com.feilong.psi.doku.controller.notify.DokuNotifyController</value>
            </array>
        </property>

        <property name="exceptionMappings">
            <props>
                <!-- STOP -->
                <prop key="com.feilong.psi.exception.PsiNotifyException">printwrite:STOP</prop>
                <prop key="java.lang.Throwable">printwrite:STOP</prop>
            </props>
        </property>
    </bean>
</beans>

5. 扩展- 使用自定义 exceptionAndExceptionViewNameBuilderMap

在实际的业务场景中, 简单的 properties 结构的 exceptionMappings 可能不能满足业务需求

比如,跳转的url 地址需要使用部分参数

此时你使用 exceptionAndExceptionViewNameBuilderMap 属性, 配置成如下格式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

    <!-- Doku Redirect 异常解决器 -->
    <bean id="redirectExceptionResolver" class="com.feilong.spring.web.servlet.handler.SimpleMappingHandlerMethodExceptionResolver">
        <property name="order" value="1" />
        <property name="preventResponseCaching" value="true" />
        <property name="mappedHandlerClasses">
            <array>
                <value>com.feilong.psi.doku.controller.redirect.DokuRedirectController</value>
            </array>
        </property>

        <property name="exceptionAndExceptionViewNameBuilderMap">
            <map>
                <entry key="com.feilong.psi.exception.PayResultStatusNotPaidException" value-ref="payResultStatusNotPaidExceptionViewNameBuilder"/>
            </map>
        </property>
    </bean>

	<bean id="payResultStatusNotPaidExceptionViewNameBuilder" class="com.baozun.store.web.controller.payment.builder.PayResultStatusNotPaidExceptionViewNameBuilder"/>

</beans>

关于 PayResultStatusNotPaidExceptionViewNameBuilder

public class PayResultStatusNotPaidExceptionViewNameBuilder extends AbstractExceptionViewNameBuilder{

    @Override
    public String build(HandlerMethod handlerMethod,Exception exception,HttpServletRequest request,HttpServletResponse response){
        PayResultStatusNotPaidException notPaidException = (PayResultStatusNotPaidException) exception;
        return buildViewName(request,notPaidException);
    }

    private String buildViewName(HttpServletRequest request,PayResultStatusNotPaidException notPaidException){
        String tradeNo = notPaidException.getTradeNo();
        String s = PaymentSecureBuilder.buildS(getMemberId(request).toString(), S_NAME_RESULT, tradeNo);
        return "redirect:" + SECURE_PAYMENT_FAIL_URL + "?transactionId=" + tradeNo + "&s=" + s;
    }
    ...
}

注意 : 优先级 exceptionAndExceptionViewNameBuilderMap > exceptionMappings 属性

 

0
0
分享到:
评论

相关推荐

    SpringMVC 中的拦截器与异常处理

    在SpringMVC中,异常处理可以帮助我们优雅地管理可能出现的错误情况,提供统一的错误页面和反馈。 1. 声明式异常处理:可以通过在控制器方法上使用`@ExceptionHandler`注解来指定特定异常的处理逻辑。这种方法适用...

    springmvc 异常统一处理的三种方式详解.docx

    本篇文章将详细探讨Spring MVC处理异常的三种主要方法:SimpleMappingExceptionResolver、自定义HandlerExceptionResolver以及@ExceptionHandler注解。 1. SimpleMappingExceptionResolver Spring MVC提供了内置的...

    完整版 Java开发实训课程系列-SpringMVC框架技术教程 第6章 异常处理 (共12页).pptx

    **SpringMVC框架中的异常处理**是Java开发中不可或缺的一部分,它确保了应用程序在遇到错误时能够优雅地处理并提供有用的反馈。在SpringMVC框架中,异常处理机制允许开发者集中处理可能出现的各种异常,提高代码的可...

    SpringMVC详解

    SpringMVC提供了优雅的异常处理机制,允许开发者定义全局或特定Controller的异常处理器,将异常信息转换为用户友好的错误页面。 10. **SpringMVC的新特性** 随着版本的更新,SpringMVC不断引入新的特性和改进,...

    燕青老师springmvc的课堂教案

    11. **异常处理**:SpringMVC提供了一种优雅的异常处理机制,通过@ControllerAdvice和@ExceptionHandler注解,可以全局处理特定类型的异常。 12. **上传下载**:SpringMVC支持文件的上传和下载,通过MultipartFile...

    使用springmvc做的增删改查

    使用@ControllerAdvice和@ExceptionHandler可以全局处理异常。对于数据验证,可以利用JSR-303/JSR-349提供的Bean Validation,或使用Hibernate Validator实现表单验证。 九、整合测试 使用JUnit和Mockito进行单元...

    SpringMVC完整demo.zip

    可以通过定义`@ControllerAdvice`注解的类来全局处理异常,或者在特定控制器中使用`@ExceptionHandler`注解来捕获和处理特定类型的异常。 6. **视图层技术**: SpringMVC可以与各种视图技术集成,如JSP、...

    springmvc框架源码.zip

    9. **异常处理**:SpringMVC提供了一套优雅的异常处理机制,允许开发者定义全局和特定异常的处理策略。 10. **参数绑定**:自动将请求参数绑定到控制器方法的参数上,支持基本类型、复杂类型以及自定义类型转换器。...

    SpringMVC简单源码实现

    SpringMVC提供了一种优雅的方式来处理应用中的异常。通过`@ExceptionHandler`注解,可以在控制器中定义特定异常的处理方法。此外,全局异常处理器(`@ControllerAdvice`)可以捕获所有控制器的异常,实现统一的错误...

    spring mvc 事务配置+异常处理

    Spring MVC提供了多种方式来处理异常,包括传统的Java异常捕获机制、自定义异常处理器和使用`@ExceptionHandler`注解。 - **传统异常捕获**:通过在Controller方法内部使用try-catch语句来捕获和处理异常。 - **...

    一个简单的springMVC入门项目

    8. **异常处理**:SpringMVC提供了一种优雅的方式处理程序中的异常,可以定义全局的异常处理器,或者在Controller方法上使用`@ExceptionHandler`注解来捕获特定异常。 9. **国际化与本地化**:SpringMVC支持多语言...

    SpringMVC3+jsp

    - 可以使用`@ExceptionHandler`注解定义异常处理器,或者配置`&lt;exception-type&gt;`元素来全局处理异常。 - `@ControllerAdvice`注解可以创建一个全局的异常处理器,应用于所有Controller。 6. **视图层增强**: - ...

    SpringMVC包

    SpringMVC提供了一套优雅的异常处理机制,允许开发者定义全局或特定类型的异常处理器。 11. **国际化** SpringMVC支持多语言环境,通过ResourceBundle和MessageSource接口,可以轻松实现应用程序的国际化。 12. ...

    jetbrick-springmvc jar包(包含源码)

    5. **异常处理**:提供了一套统一的异常处理机制,将系统异常转化为用户友好的错误页面,便于进行异常管理和用户体验优化。 6. **国际化**:内置了便捷的国际化支持,可以轻松实现多语言环境下的应用开发。 7. **...

    SpringMVC实现网上报名

    5. **@Repository**:在数据访问层,用于标记DAO(数据访问对象)类,这使得Spring能够处理数据库操作中的异常。 6. **Hibernate**:是一个强大的ORM(对象关系映射)框架,它简化了数据库操作,允许开发者以面向...

    SpringMVC(十一)异常处理器和注解配置SpringMVC

    Spring MVC提供了一种优雅的方式来处理这些异常,而不是让它们直接导致服务器崩溃。我们可以通过实现`HandlerExceptionResolver`接口或者使用`@ExceptionHandler`注解来定义自定义的异常处理器。通过这种方式,我们...

    springmvc课堂笔记(两天)

    10. **异常处理**:了解如何定义全局和局部的异常处理器,以优雅地处理程序中的错误。 第二天的课堂笔记则可能进一步深入: 1. **视图技术**:详细探讨如何集成JSP、FreeMarker、Thymeleaf等视图技术,以及它们...

    达内SpringMVC代码例子+笔记2

    - 可以全局或局部定义异常处理器,统一处理异常情况。 笔记部分可能会涵盖以上概念的详细解释和使用案例,帮助我们理解每个知识点的实践应用。代码部分则提供了实际的编程示例,让我们有机会亲手操作,加深理解。...

    Spring In Action SpringMVC 提交表单

    通过`@ExceptionHandler`注解,我们可以优雅地处理错误并返回合适的视图。 六、源码分析 SpringMVC的源码中,`DispatcherServlet`是核心组件,它负责调度请求到相应的Controller。`HandlerMapping`和`...

Global site tag (gtag.js) - Google Analytics