play framework 处理统一异常

原创
2017/01/19 16:39
阅读数 502

play framework 1.2.x 处理全局异常

    采用@Catch标签,在处理统一异常的方法上添加此标签,用于捕获程序抛出的异常

    如果有Action方法抛出了异常,那么使用@Catch注解的方法就会执行,且抛出的异常会以参数的形式传递到@Catch注解的方法中。

    编写自定义ServiceException 类。

public class ServiceException extends RuntimeException {

	private String msg = "unknow error";

	public ServiceException(Exception e) {
		super(e);
	}

	public ServiceException(String msg) {
		super(msg);
	}

	public ServiceException(Exception e, String msg) {
		super(e);
		e.printStackTrace();
		this.setMsg(msg);
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

}

    编写一个简单的控制器测试类 TestExceptionController.java ,在控制器层添加抛出自定义异常方法:

public class TestExceptionController extends BaseController {

	public static void test1() { //不可修改为throws ServiceException
		try {
			int ka = 2 / 0;
			renderJSON(ka);
		} catch (Exception e) {
			throw new ServiceException(e, "数据格式错误");
		}

	}
}

    添加路由 route,否则无法访问新增的action

GET     /testA							test.TestExceptionController.test1

    编写一个统一处理异常的类   MyExceptionHandler.java,用于捕获到的异常

public class MyExceptionHandler extends Controller {

	/**
	 * 统一错误处理
	 * 
	 * @param se
	 */
	@Catch(ServiceException.class)
	public static void operateExp(ServiceException se) {
		Logger.error(se.getMessage());
		String accept = request.headers.get("accept").toString();
		String s[] = accept.split(",");
		if (s[0].equalsIgnoreCase("[text/html")) {
			render("@Application.errorFront");
		} else if (s[0].equalsIgnoreCase("[application/json")) {
			String err = se.getMessage();
			renderJSON(err);
		} else {
			render("@Application.errorFront");
		}
	}
}

    本例子中未区普通text/html和json等请求,实际中可根据不用的请求类型,进行不同的异常捕获处理

     使用@Catch注解和普通的Java异常处理程序一样,捕获父类往往可以获得更多的异常类型。如果拥有多个需要捕获的方法,可以通过指定优先级来确定他们的执行顺序。通过@Catch中的priority来定义

    查看@Catch标签的源码发现:

    第一个vlaue数组表示可以传入多个异常类型,第二个int类型的用来标示优先级,0最高

/**
 * Mark this method as @Catch interceptor
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Catch { 

    Class<?>[] value() default {};
    /**
     * Interceptor priority (0 is high priority)
     */
    int priority() default 0;

}

    好了,开始测试。。。。

   等等。。。千万不要以为完事了,可以运行了。。。现在这样无法捕获到 test1()中抛出的ServiceException

    因为没有MyExceptionHandler中用来捕获自定义异常ServiceException并处理方法并没有被调用,或者说并不会起作用。如何解决?有两种方法:

  1. 删掉 MyExceptionHandler.java,把里面的operateExp方法放到TestExceptionController.java 中,并在方法头上添加@Catch标签
    public class TestExceptionController extends BaseController {
    
    	/**
    	 * 统一错误处理
    	 * 
    	 * @param se
    	 */
    	@Catch(ServiceException.class)
    	public static void operateExp(ServiceException se) {
    		Logger.error(se.getMessage());
    		String accept = request.headers.get("accept").toString();
    		String s[] = accept.split(",");
    		if (s[0].equalsIgnoreCase("[text/html")) {
    			render("@Application.errorFront");
    		} else if (s[0].equalsIgnoreCase("[application/json")) {
    			String err = se.getMessage();
    			renderJSON(err);
    		} else {
    			render("@Application.errorFront");
    		}
    	}
    
    	public static void test1() {
    		try {
    			int ka = 2 / 0;
    			renderJSON(ka);
    		} catch (Exception e) {
    			throw new ServiceException(e, "数据格式错误");
    		}
    
    	}
    }

    这样,控制器中的捕获自定义异常的方法operateExp就能生效,打开浏览器,访问http://localhost:9001/testA,会发现页面被跳转到了定义好的错误页面

  2. 利用@With标签

    1. 使用@with注解增加更多拦截器

            如果某个控制器是其他一些类的父类,那么该控制器中定义的所有拦截器会影响到所有子类。由于Java不允许多重继承,对单纯通过继承来使用拦截器造成了一定的局限性。Play可以通过@With注解,调用其他控制器中已经定义好的拦截方法,从而突破这一局限。

    2. 在TestExceptionController.java中,添加@With标签。@With标签只能添加在类上,不能添加在方法/构造器中

    3. import play.mvc.With;
      
      @With(MyExceptionHandler.class)
      public class TestExceptionController extends BaseController {
      
      	public static void test1() {
      		try {
      			int ka = 2 / 0;
      			renderJSON(ka);
      		} catch (Exception e) {
      			throw new ServiceException(e, "数据格式错误");
      		}
      
      	}
      }

      通过添加了@With标签就可以调用到MyExceptionHandler中的处理异常的方法.

      打开浏览器,输入同样地址,同样,页面也被跳转到了指定错误页面。。。

 

    写的不是很详细,就大致说明了下思路。。。有空补上详细    

 

                    

     

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部