JavaWeb统一异常处理

JavaWeb统一异常处理

[toc]

处理方案

1. xml文件配置方式

web.xml配置

<error-page>
    <error-code>404</error-code>
    <location>/404</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/500</location>
</error-page>

<!-- 未捕获的错误,同样可指定其它异常类,或自定义异常类 -->
<error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/uncaughtException</location>
</error-page>


springmvc(applicationContext.xml)配置
<mvc:view-controller path="/400" view-name="400"/>
<mvc:view-controller path="/404" view-name="404"/>
<mvc:view-controller path="/500" view-name="500"/>
<mvc:view-controller path="/uncaughtException" view-name="uncaughtException"/>

SimpleMappingExceptionResolver

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
   
    <property name="exceptionMappings">
        <props>
            <!-- 异常类名,可以是全路径,错误页面或Controller路径! -->
            <prop key="NullPointerException">NullPointerException</prop>
            <prop key="IOException">IOException</prop>
        </props>
    </property>
    
     <!-- 表示当抛出异常但没有在exceptionMappings里面找到对应的异常时 返回名叫exception的视图-->  
    <property name="defaultErrorView" value="exception"/>
    
    <!-- 定义在发生异常时视图跟返回码的对应关系 --> 
    <property name="statusCodes"> 
        <props>  
            <prop key="number">500</prop>
            <prop key="null">503</prop>  
        </props>  
    </property>  
    <property name="defaultStatusCode" value="404"/>  
</bean>

2.代码拦截

自定义异常。

作统一异常处理。

自定义非检测异常,继承RuntimeException类,直接中断处理,不需要显示的捕捉和处理。例如参数错误等等无需进一步处理和恢复。

自定义检测异常, 继承Exception类,需要显示的捕捉或抛出。


public class BaseRuntimeException extends RuntimeException {

    private String message; //异常信息
    private Object[] args;  //相关参数等

   
    public BaseRuntimeException(String message) {
        super(message);
        this.message = message;
    }

   
    public BaseRuntimeException(String message, Throwable cause) {
        super(message, cause);
        this.message = message;
    }

   
    public BaseRuntimeException(String message, Object ... args) {
        super(message);
        this.message = message;
        this.args = args;
    }


    public BaseRuntimeException(String message, Throwable cause, Object ... args) {
        super(message, cause);
        this.message = message;
        this.args = args;
    }

 
    public String getMessage() {
        return message;
    }

    public Object[] getArgs() {
        return args;
    }
}


自定义异常处理器。
1.基于spring mvc 实现HandlerExceptionResolver接口


public class GlobalHandlerExceptionResolver implements HandlerExceptionResolver {   
 private static final Logger LOG = LoggerFactory.getLogger(GlobalHandlerExceptionResolver.class);                 
     
   @Override    
   public ModelAndView resolveException(HttpServletRequest req,                                         HttpServletResponse resp, Object o, Exception ex) {   
       ex.printStackTrace();     
       if (ex instanceof BaseRuntimeException) {
           printWrite(ex.getMessage, resp); 
        } else {          
             
           printWrite("ERROR!", resp);   
        }
        
         return new ModelAndView(); 
   }  

   /**     
   * 将错误信息写入到response中  
   * @param messsage     
   * @param response     
   * @throws IOException     
   */   
    public static void printWrite(String messsage, HttpServletResponse response) {      
         try {           
             PrintWriter pw = response.getWriter();        
             pw.write(messsage);       
             pw.flush();       
             pw.close();      
          } catch (Exception e) {          
             e.printStackTrace();      
          }   
    }
}


2. 注册异常处理器
<bean class="com.iot.learnssm.firstssm.exception.CustomExceptionResolver"></bean>
自定义拦截器

由于HandlerExceptionResolver接口只实现返回值为ModelAndView,前后端分离的话,可以采用拦截器HandlerInterceptor或者Filter。(springmvc还可以采用@ExceptionHandler注解来处理局部异常(注解应用于方法上),此处不多谈)

1. 基于spring mvc 实现HandlerInterceptor接口

public interface HandlerInterceptor {

//处理前,返回ture 进入postHandle, 返回false 进入afterCompletion
    boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception; 

//进入控制器
    void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;

//执行完控制器后调用
    void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception; 
}



public class MVCRequestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        return true;
    }

   @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

        httpServletResponse.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE");
        httpServletResponse.setHeader("Access-Control-Allow-Credentials","true");


        try {
            chain.doFilter(request, httpServletResponse);
        } catch (BaseRuntimeException e) {
            e1.printStackTrace();
            printMessage(httpServletResponse, e.getMessage);

        } catch (Exception e){
            e1.printStackTrace();
            printMessage(httpServletResponse, ExceptionUtils.getStackTrace(e));
        }


    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {


    }
    
    
    private void printMessage(httpServletResponse response, String message){
         PrintWriter out = httpServletResponse.getWriter();
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("success", false);
            map.put("msg", message);//获取详细错误信息
            out.println(JSONObject.toJSONString(map));
    }
}




2. 注册拦截器

<!-- 注册拦截器 -->
	<mvc:interceptors>
		<bean class="com.project.base.interceptor.ControlInterceptor" />
	</mvc:interceptors>


自定义Filter拦截器
1. 选择缘由
  • 框架由Struts2 改为 spring mvc,原代码并未改动,为了兼容两种控制器,实现javax.servlet的Filter接口,进行错误统一处理。
2.实现Filter 接口

@Component
public class GlobeExceptionFilter extends GenericFilterBean {

/*采用DelegatingFilterProxy代理管理自定义filter,可直接注入该service
    @Autowired
    private SysLoginLogService sysLoginLogService;
    */


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        httpServletResponse.setHeader("Access-Control-Allow-Origin","*");
        httpServletResponse.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE");
        httpServletResponse.setHeader("Access-Control-Allow-Credentials","true");


        try {
            filterChain.doFilter(servletRequest, httpServletResponse);

            int httpStatus = httpServletResponse.getStatus();
                if(httpStatus >=400){ //请求错误
                HttpServletRequest request = (HttpServletRequest) servletRequest;
                String requestURI = request.getRequestURI();
                String queryString = request.getQueryString();
                System.out.println("------>"+requestURI);
                System.out.println("--------->"+queryString);
                // throw new BaseRuntimeException("error", requestURI, queryString); //用于测试
            }


        } catch (BaseError e){ //内部自定义错误
            System.out.println(e.getMessage());
            System.out.println(Arrays.toString(e.getArgs()));
        } catch (BaseRuntimeException e){ //内部自定义异常

            System.out.println("messsage--->" +e.getMessage());
            System.out.println("args--->" +Arrays.toString(e.getArgs()));

           //追踪栈上信息
            StackTraceElement[] st = e.getStackTrace();
            if(st.length > 0){
                String exclass = st[0].getClassName();
                String method = st[0].getMethodName();
                System.out.println("calss----->" + exclass); //发生异常类
                System.out.println("method----->" + method); //方法
                System.out.println("method----->" + lineNumber); //行数 
            }
            printMessage(httpServletResponse, e.getMessage());

            } catch (Exception e){ //其他异常
            e.printStackTrace();

        
            printMessage(httpServletResponse, e.getMessage());
        }

    }
    
    
    private void printMessage(HttpServletResponse httpServletResponse, String message){
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        PrintWriter out = null;
        try {
            out = httpServletResponse.getWriter();
            Map<String,Object> map = new HashMap<String,Object>();
            map.put("success", false);
            map.put("msg", message);
            out.println(JSONObject.toJSONString(map));
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(out != null){
                out.close();
            }
        }

    }
}





3. xml配置
通过spring管理filter

采用DelegatingFilterProxy代理管理自定义filter ,filter内部可直接使用spring bean直接注入。




	<filter>
		<filter-name>globeExceptionFilter</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<init-param>
			<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由servlet container管理 -->
			<param-name>targetFilterLifecycle</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>globeExceptionFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


Spring中注册filter
    <!-- 全局异常处理 -->
	<bean id="globeExceptionFilter" class="com.project.base.filter.GlobeExceptionFilter" />



转载于:https://my.oschina.net/u/2500836/blog/1536094

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值