跟着江南一点雨学习springmvc(3)
springmvc中的异常捕获
第一种方式,实现HandlerExceptionResolver 接口
package com.qfedu.deom.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;
/**
* 第一种全局异常处理器
* 这是一个全局异常处理类,使用的时候,只需要将这个类注册到 Spring 容器中即可
*/
//@Component
public class MyGlobalException implements HandlerExceptionResolver {
/**
* 当系统抛出异常的时候,会自动触发的方法
* @param request
* @param response
* @param handler 发生问题的处理器(具体的接口)
* @param ex 具体抛出的异常
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("error",ex.getMessage());
return modelAndView;
}
}
第二种方式,使用注解@ExceptionHandler(重点学习)
package com.qfedu.deom.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 第二种全局异常处理器
* 全局异常处理
* <p>
* 这个类的定义,和我们定义接口的规则是一模一样的
*
* 注意要是在过滤器中发生了异常,这三种全局异常处理器都是捕获不到的,因为那是一种Tomcat容器级别的异常,这三种全局异常处理方法都是处理spring
* 容器里的异常,都基于aop实现的。
*/
@RestControllerAdvice
public class MyGlobalException2 {
/**
* 这个异常处理方法的返回值,和定义接口时候的返回值的类型是一模一样的
* 这个方法的参数也和接口的参数基本一致,接口中的默认参数,这里也都可以直接添加后使用
*
* 默认情况下,即使系统抛出异常,调用了下面的方法,但是 HTTP 响应的状态码依然是 200
*
* @return
* @ExceptionHandler(ArithmeticException.class) 表示当系统发生 ArithmeticException 异常的时候,进入到当前的方法中进行处理
*/
//如果发生该类型异常 则进入下面这个方法
@ExceptionHandler(ArithmeticException.class)
//如果设置了下面这个注解里面的内容 浏览器状态码为500
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String error(Exception e){
return e.getMessage();
}
}
第三种方式,注册bean的方式
<!-- 这是第三种全局异常处理 但不能传参数 了解即可-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!-- 这是捕获的异常类型和跳转的页面 -->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
</bean>
springmvc中的拦截器
类似于过滤器,但又不一样。
Filter是Tomcat的组件,interceptor是在spring容器中的。interceptor在Filter之后执行,Filter过滤的是请求,interceptro拦截的是处理器。
实现HandlerInterceptor 接口就可以:
package com.qfedu.demo.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 类似于过滤器,但是不一样
* 1. Filter 是 Tomcat 容器中的工具;Interceptor 是 Spring 容器中的
* 2. Interceptor 是在 DispatcherServlet 中被调用的,Filter 则在 Servlet 之前执行,所以 Filter 在 Interceptor 之前执行。
* 3. Filter 拦截的是一个具体的请求;而 Interceptor 拦截的是处理器。
*/
@Component
public class MyInterceptor implements HandlerInterceptor {
/**
* 当处理器的执行被拦截下来之后,如果这个方法返回 true,就表示继续去执行处理器,如果这个方法返回 false,就表示处理器不执行了
* @param request
* @param response
* @param handler 这个就是处理器本身 HandlerMethod
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
/**
* 这个方法是在处理器执行之后执行
* @param request
* @param response
* @param handler
* @param modelAndView 处理器执行完毕之后,就会返回 ModelAndView,所以这个参数其实就是处理器返回的 ModelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
/**
* 这个是页面渲染完成后执行
* @param request
* @param response
* @param handler
* @param ex 渲染出错的异常
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
再到xml文件中配置:
<mvc:interceptors>
<mvc:interceptor>
<!--配置拦截器,设置 myInterceptor 这个拦截器可以拦截所有请求-->
<mvc:mapping path="/**"/>
<ref bean="myInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
Ajax跨域的问题解决:
使用注解解决
@RestController
public class HelloController {
@GetMapping("/hello")
//@CrossOrigin(origins = "http://localhost:8081") 表示允许处理来自 8081 这个接口的请求,本质上就是在响应头中添加一个 Access-Control-Allow-Origin 字段
@CrossOrigin(origins = "http://localhost:8081")
public String show(){
// int i = 1/0;
return "hello";
}
@PutMapping("/hello2")
@CrossOrigin(origins = "http://localhost:8081")
public String hello2() {
return "hello put";
}
}
使用xml文件解决
<!--一键解决跨域问题-->
<mvc:cors>
<mvc:mapping path="/**" allowed-origins="http://localhost:8081" allowed-methods="*"/>
</mvc:cors>