zoukankan      html  css  js  c++  java
  • SSM框架全局捕获异常

    我们都知道,项目有两种异常,一种是ERROR,一种是Exception,ERROR导致项目直接崩盘,无法运行,且不能捕获,Exception可以捕获且不影响项目运行,今天要做的就是捕获Exception,当前项目开发使用SSM框架,我原本使用的方法是Controller控制层每一个类每一个方法都有一个try-catch捕获当前方法异常,虽然这种可用,但是会有几个问题:

    向前端如何返回异常?
    即如何保证发生异常时向前端返回的数据统一,因为是不同人员开发,很可能A人员直接将异常扔给前端,而B人员将异常处理之后返回前端一个标识
    如何记录异常信息?
    我们要考虑到系统中每一处代码都有发生异常的可能性(在这里先仅考虑Controller层),即使我们编写异常记录的工具类,难道我们在每处发生异常的地方都调用吗?(不谈资源浪费的情况下,如何确保每个开发人员记录格式相同?如何确保每处Exception都会被记录?)
    基于以上两点,我基于SSM框架做了一个Exception的全局异常捕获,邮件提醒(亲测有效)
    在这里即使用GlobalExceptionHandler类捕获控制层的异常,代码如下:

    package com.single.cong.exception;
    
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.mail.SimpleMailMessage;
    import org.springframework.mail.javamail.JavaMailSender;
    import org.springframework.security.access.AccessDeniedException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseStatus;
    import lombok.extern.slf4j.Slf4j;
    /**
     * 全局捕获异常
     */
    @Slf4j
    @ControllerAdvice(basePackages = "com.single.cong.controller")
    public class GlobalExceptionHandler {
    
    	@Autowired
    	private JavaMailSender javaMailSender;
    
    	/**
    	 * 异常信息转化为String类型,等同于e.printStackTrace()输出参数
    	 * 
    	 * @param t
    	 *            异常
    	 * @return 异常详细信息
    	 * @author single-聪
    	 * @date 2019年4月15日
    	 * @version 1.0.0
    	 */
    	public String getTrace(Throwable t) {
    		StringWriter stringWriter = new StringWriter();
    		PrintWriter writer = new PrintWriter(stringWriter);
    		t.printStackTrace(writer);
    		StringBuffer buffer = stringWriter.getBuffer();
    		SimpleMailMessage mailMessage = new SimpleMailMessage();
    		mailMessage.setFrom("123456789@qq.com");
    		mailMessage.setTo("1234567890@qq.com");
    		mailMessage.setSubject("系统Bug,及时修复");
    		mailMessage.setText(buffer.toString());
    		javaMailSender.send(mailMessage);
    		return buffer.toString();
    	}
    	
    	/**
    	 * 全局异常捕获,暂时区分两种异常类型,所有运行时异常统一在此方法中
    	 * 
    	 * @param e
    	 *            异常
    	 * @author single-聪
    	 * @date 2019年4月15日
    	 * @version 1.0.0
    	 * 
    	 */
    	@ExceptionHandler(RuntimeException.class)
    	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    	public void runtimeException(Exception e) {
    		log.info("全局捕获运行时异常,同时写入日志文件");
    		e.printStackTrace();
    		log.error(getTrace(e));
    	}
    
    	/**
    	 * 账号权限信息不足
    	 * 
    	 * @param e
    	 *            异常
    	 * @author single-聪
    	 * @date 2019年4月15日
    	 * @version 1.0.0
    	 * 
    	 */
    	@ExceptionHandler(AccessDeniedException.class)
    	@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
    	public void accessDeniedException(Exception e) {
    		log.info("账号权限信息不足");
    		e.printStackTrace();
    		log.error(getTrace(e));
    	}
    }
    

    @ControllerAdvice注解将作用在所有注解了@RequestMapping的控制器的方法上,basePackages代表指定包下面的方法,可以使用不同的类处理不同的异常。
    @ExceptionHandler(RuntimeException.class)用于全局处理控制器里的异常,在这里我们只处理运行时异常以及权限验证异常。
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)返回状态码
    参数里面加上Exception之后就可以使用e.printStackTrace()在控制台打印出异常,在这里将打印出的异常存储进日志文件(SpringBoot使用logback)方便查看,这样我们就不需要在每个控制层方法里面写多余的代码了。

    注意,邮件发送部分需要更换成自己的账号信息,同时需要配置key。

    在使用这个全局方法之前,我的控制层代码如下:

    // 删除
    @RequestMapping(value = "/delete.sose", consumes = "application/json;charset=UTF-8")
    public Map<String, Object> delete(@RequestBody String c) throws ParseException {
    	java.util.Map<String, Object> map = new HashMap<>();
    	try {
    		// 获取前端传回删除数据Id
    		JSONObject strj = new JSONObject(c);
    		evolveService.delete(strj.getInt("id"));
    		map.put("info", "success");
    	} catch (Exception e) {
    		e.printStackTrace();
    		map.put("info", e);
    	}
    	return map;
    }
    

      使用异常捕获机制之后,只要你能够将系统中的异常罗列出来,那么就可以根据异常类型决定返回指定的状态码,前端只处理状态码为200的数据,一旦状态码不是200就可以认为服务器端数据处理失败。至于具体的错误信息需不需要返回前端可以根据业务决定。

  • 相关阅读:
    PAT L2-014【二分】
    CodeForces 137C【贪心+优先队列】
    CodeForces 131D【图特性+BFS】
    CodeForces 125D【鸽巢原理】
    PAT1060【大模拟啊】
    CodeForces 124C【连通块】
    PAT 1071【STL string应用】
    CodeForces 116C 【BFS】
    CodeForces 116B【二分匹配】
    CodeForces 118C 【模拟】
  • 原文地址:https://www.cnblogs.com/wzihan/p/14108975.html
Copyright © 2011-2022 走看看