以下内容纯属个人理解,不喜勿喷。
在实际项目开发过程中,程序在进行一些逻辑业务处理的时候,常常需要在程序指定的地方就退出程序(在这个指定的地方可能又调用了引用对象中的某个方法,具体的就是在执行这个方法的时候按照我们的逻辑是需要退出程序的,不再去执行后面的业务逻辑处理了),不在继续执行后面的程序了,怎么办呢,返回null或者对象都会有一定的复杂。怎么办呢?异常处理机制来解决这个问题。
@ControllerAdvice
使用此注解不用任何的配置,只要把这个类放在项目中,Spring能扫描到的地方。就可以实现全局异常的回调。
@ControllerAdvice是一个@Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。
@ExceptionHandler
优先级的问题:例如发生的是NullPointerException,但是声明的异常有RuntimeException和Exception,此时会根据异常的最近继承关系找到继承深度最浅的那个@ExceptionHandler注解方法,即标记了RuntimeException的方法
ExceptionHandlerMethodResolver内部若找不到@ExceptionHandler注解的话,会找@ControllerAdvice中的@ExceptionHandler注解方法
话不多说看代码
TestController
package app.springmvc.controller;
import app.beans.test2.Test2;
import custom.app.TestApp;
import custom.exception.MsgExceotion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.Request;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@RestController
@RequestMapping("/Test")
public class TestController
{
@Value(value="#{component_test2}")
private Test2 test2;
@RequestMapping(value="/test5",method={RequestMethod.GET},produces = "text/html;charset=utf-8")
public String test5()
throws MsgExceotion
{
String response_str = null;
TestApp test = new TestApp();
test.test();
return response_str;
}
@RequestMapping(value="/test4",method={RequestMethod.GET},produces = "text/html;charset=utf-8")
public String test4()
throws MsgExceotion
{
String response_str = null;
int i = 4/2;
if(i == 2)
{
throw new MsgExceotion(1001,"我是谁");
}
return response_str;
}
@RequestMapping(value="/test3",method={RequestMethod.GET},produces = "text/html;charset=utf-8")
public String test3()
{
String response_str = null;
response_str = String.valueOf(1/0);
return response_str;
}
@RequestMapping(value="/test2",method={RequestMethod.GET},produces = "text/html;charset=utf-8")
public String test2(HttpServletRequest request,HttpServletResponse response)
throws IOException
{
String response_str = null;
if(request.hashCode() == test2.getRequest().hashCode())
{
response_str += "<p>两次request是一致的</p>";
}else{
response_str += "<p>两次request不是一致的 current_http_request_hashcode : " + request.hashCode() + " infuse_http_request_hashcode : " + test2.getRequest().hashCode() +" </p>";
}
if(response.hashCode() == test2.getResponse().hashCode())
{
response_str += "<p>两次response是一致的</p>";
}else{
response_str += "<p>两次response不是一致的 current_http_response_hashcode : " + response.hashCode() + " infuse_http_response_hashcode : " + test2.getResponse().hashCode() + "</p>";
}
//response.setCharacterEncoding("utf-8");
//response.setHeader("content-type","text/html;charset=utf-8");
response.getOutputStream().write(new String("我是谁?").getBytes("UTF-8"));
return response_str;
}
@RequestMapping(value="/test1",method={RequestMethod.GET},produces="text/html;charset=utf-8")
public String test1(HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String test1_str = "test1 running : 第一次运行";
response.setCharacterEncoding("utf-8");
response.setHeader("content-type","text/html;charset=utf-8");
PrintWriter out = response.getWriter();
test1_str += "<p>response hashcode:" + response.hashCode() + "</p>" + "<p>request hashcode:" + request.hashCode() + "</p>";
out.write(test1_str);
return null;
}
}
MsgExceotion
package custom.exception;
import net.sf.json.JSONObject;
import java.util.HashMap;
public class MsgExceotion extends Exception
{
private String code;
private String msg;
public MsgExceotion() { }
public MsgExceotion(Object code,Object msg)
{
this.setCode(String.valueOf(code));
this.setMsg(String.valueOf(msg));
}
@Override
public String getMessage()
{
String res_msg = null;
String code = this.getCode();
String msg = this.getMsg();
if(code != null || msg != null)
{
HashMap<String,String> map = new HashMap<String,String>(2);
map.put("code",code);
map.put("msg",msg);
JSONObject json = JSONObject.fromObject(map);
res_msg = json.toString();
}
return res_msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
异常处理类,一定要放在spring mvc 解析地址下面,让spring mvc 能够扫描到他。
HandlerException.java
package app.springmvc.exception;
import custom.exception.MsgExceotion;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
@ResponseBody
public class HandlerException
{
@ExceptionHandler({MsgExceotion.class})
public String msgExceptionHandler(Exception e)
{
return e.getMessage();
}
@ExceptionHandler({Exception.class})
public String exceptionHandler(Exception e)
{
String response_str = null;
response_str = "报错信息error : " + e.getMessage();
return response_str;
}
}