SpringMVC执行流程:
发起请求--->前端控制器--->调用处理器映射器获取具体的处理器---->
返回前端控制器--->处理器适配器--->
调用具体的处理器--->返回数据给前端控制器--->
视图解析器--->返回视图--->前端控制器处理视图返回给用户
@ResponseBody
响应正文,将方法的返回值作为正文返回,但是Java对象不能被网页所识别,为了识别这个数据,mvc提供了
httpmessageconvert来将Java对象转成http的正文数据,如果数据对象本身就是String类型,会原样输出,
如果是Java的其他对象,会进行转换,默认是通过jackson转成json数据但是可以更改。
@Controller
public class UserController {
@RequestMapping(value = "/test1")
@ResponseBody
public String test1(){
System.out.println("UserController.test");
int i = 10/0;//这里有一个异常,如果不处理会把异常信息直接暴露给用户
return "ok";
}
@RequestMapping(value = "/test2")
@ResponseBody
//这里处理了异常,但是不能每个方法都进行这样的处理,那样trycatch代码太多了
public String test2(){
System.out.println("UserController.test");
try {
int i = 10 / 0;
}catch (ArithmeticException e){
System.err.println("这里出现异常了");
e.printStackTrace();
return "系统正在维护,请联系管理员。。。";
}
return "ok";
}
这个是全局处理异常的一种方式,实现HandlerExceptionResolver接口 (这里还需要创建一个error.jsp用来给用户显示):
package com.qf.exception;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @Author kk
* @Date 2020/5/14 16:08
*/
@Component//这个类虽然创建了,但是还需要被Spring容器识别,因此加上该注解
public class ExceptionHandler implements HandlerExceptionResolver {
/**
* 全局异常处理的方法,项目里的异常都可以在这里处理
* @param httpServletRequest
* @param httpServletResponse
* @param o 某个bean出现的异常
* @param e 异常对象
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
System.out.println("ExceptionHandler.resolveException");
ModelAndView modelAndView = new ModelAndView();
//设置出现异常后调整的页面
modelAndView.setViewName("error");
modelAndView.addObject("errorMsg","系统正在维护,请联系管理员...");
return modelAndView;
}
}
这里是处理全局异常的另一种方式(常用),使用注解,写一个类:
package com.qf.exception;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
/**
* @Author kk
* @Date 2020/5/14 16:20
*/
@Component
@ControllerAdvice //全局异常处理的注解
public class ExceptionHandlerAnnotation {
//出现ArithmeticException异常,或者该异常的子类都会调用本方法
@ExceptionHandler(value = ArithmeticException.class)//只有出现这个异常,才会进入本方法
@ResponseBody
public Map<String,Object> exception( Exception e){
System.out.println("ExceptionHandlerAnnotation.exception" + e);
Map<String,Object> map = new HashMap<>();
map.put("status","error");
map.put("msg","系统出现了数学计算异常");
return map;
}
@ExceptionHandler(value = NullPointerException.class)//只有出现这个异常,才会进入本方法
@ResponseBody
public Map<String,Object> exception2( Exception e){
System.out.println("ExceptionHandlerAnnotation.exception" + e);
Map<String,Object> map = new HashMap<>();
map.put("status","error");
map.put("msg","系统出现了空指针异常");
return map;
}
}
总结:
1. 如果系统出现异常后SpringMVC默认的处理方式是把异常直接暴露给用户
2.可以在代码里写trycatch语句块进行捕获,但是最后try catch过多难以维护
3.全局异常的处理
a.使用注解实现
1)定义一个全局的异常处理Handler
2)类上面添加@ControllerAdvice
3)方法上面添加@ExceptionHandler(value = 异常的种类.class)
当出现当前异常或者当前异常的子类时,就会调用该方法
b.实现HandlerExceptionResolver接口
1)复写该接口中的方法,在这个方法里面还需要设置异常出现后的视图.jsp
2)缺点:只能返回错误视图,如果返回JSON数据比较复杂
3)这个类需要用@Component来修饰