java学习笔记——springmvc 之 拦截器 与 异常处理 和 SpringMVC的运行流程总结 - Go语言中文社区

java学习笔记——springmvc 之 拦截器 与 异常处理 和 SpringMVC的运行流程总结


十二、 拦截器

1、自定义拦截器概述

  1. Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口
    1. preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false
    2. postHandle():这个方法在业务处理器处理完请求后,但是DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求request进行处理。

afterCompletion():这个方法 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。

 

2、实验代码(单个拦截器)

  • 自定义拦截器类

package com.atguigu.springmvc.interceptors;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

 

public class FirstHandlerInterceptor implements HandlerInterceptor {

 

@Override

public void afterCompletion(HttpServletRequest arg0,

HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {

System.out.println(this.getClass().getName() + " - afterCompletion");

}

 

@Override

public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,

Object arg2, ModelAndView arg3) throws Exception {

System.out.println(this.getClass().getName() + " - postHandle");

}

 

@Override

public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,

Object arg2) throws Exception {

System.out.println(this.getClass().getName() + " - preHandle");

return true;

}

  • 配置拦截器

<mvc:interceptors>

<!-- 声明自定义拦截器 -->

<bean id="firstHandlerInterceptor"

      class="com.atguigu.springmvc.interceptors.FirstHandlerInterceptor"></bean>

</mvc:interceptors>

  • 断点调试拦截器执行流程

  • 拦截器方法执行顺序(小总结)

 

 

3、实验代码(多个拦截器)

  • 自定义拦截器类(两个)

package com.atguigu.springmvc.interceptors;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

 

public class FirstHandlerInterceptor implements HandlerInterceptor {

 

@Override

public void afterCompletion(HttpServletRequest arg0,

HttpServletResponse arg1, Object arg2, Exception arg3)

throws Exception {

System.out.println(this.getClass().getName() + " - afterCompletion");

}

 

@Override

public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,

Object arg2, ModelAndView arg3) throws Exception {

System.out.println(this.getClass().getName() + " - postHandle");

}

 

@Override

public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,

Object arg2) throws Exception {

System.out.println(this.getClass().getName() + " - preHandle");

return true;

}

 

}

package com.atguigu.springmvc.interceptors;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

 

public class SecondHandlerInterceptor implements HandlerInterceptor {

 

@Override

public void afterCompletion(HttpServletRequest arg0,

HttpServletResponse arg1, Object arg2, Exception arg3)

throws Exception {

System.out.println(this.getClass().getName() + " - afterCompletion");

}

 

@Override

public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,

Object arg2, ModelAndView arg3) throws Exception {

System.out.println(this.getClass().getName() + " - postHandle");

}

 

@Override

public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,

Object arg2) throws Exception {

System.out.println(this.getClass().getName() + " - preHandle");

return true;

}

 

}

  • 配置自定义拦截器

<mvc:interceptors>

<!-- 声明自定义拦截器 -->

<bean id="firstHandlerInterceptor"

  class="com.atguigu.springmvc.interceptors.FirstHandlerInterceptor"></bean>

<!-- 配置拦截器引用 -->

<mvc:interceptor>                        

<mvc:mapping path="/empList"/>

<!-- <mvc:exclude-mapping path="/empList"/> -->

<bean id="secondHandlerInterceptor"

         class="com.atguigu.springmvc.interceptors.SecondHandlerInterceptor"></bean>

</mvc:interceptor>

</mvc:interceptors>

两个都是返回true :

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - preHandle

com.atguigu.springmvc.interceptors.SecondHandlerInterceptor - preHandle

************************************biz method*******************************

com.atguigu.springmvc.interceptors.SecondHandlerInterceptor - postHandle

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - postHandle

com.atguigu.springmvc.interceptors.SecondHandlerInterceptor - afterCompletion

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - afterCompletion

两个都是返回false:

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - preHandle

true,false

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - preHandle

com.atguigu.springmvc.interceptors.SecondHandlerInterceptor - preHandle

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - afterCompletion

false,true

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - preHandle

 

 

4、多个拦截方法的执行顺序

  • 关于执行顺序

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - preHandle

com.atguigu.springmvc.interceptors.SecondHandlerInterceptor – preHandle

************************************biz method*******************************

com.atguigu.springmvc.interceptors.SecondHandlerInterceptor - postHandle

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - postHandle

com.atguigu.springmvc.interceptors.SecondHandlerInterceptor - afterCompletion

com.atguigu.springmvc.interceptors.FirstHandlerInterceptor - afterCompletion

  • 执行顺序图解

 

  • 从源代码的执行角度分析流程:

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {

if (getInterceptors() != null) {

for (int i = 0; i < getInterceptors().length; i++) {

HandlerInterceptor interceptor = getInterceptors()[i];

if (!interceptor.preHandle(request, response, this.handler)) {

triggerAfterCompletion(request, response, null);

return false;

}

this.interceptorIndex = i;

}

}

return true;

}

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {

if (getInterceptors() == null) {

return;

}

for (int i = getInterceptors().length - 1; i >= 0; i--) {

HandlerInterceptor interceptor = getInterceptors()[i];

interceptor.postHandle(request, response, this.handler, mv);

}

}

 

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)

throws Exception {

 

if (getInterceptors() == null) {

return;

}

for (int i = this.interceptorIndex; i >= 0; i--) {

HandlerInterceptor interceptor = getInterceptors()[i];

try {

interceptor.afterCompletion(request, response, this.handler, ex);

}

catch (Throwable ex2) {

logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);

}

}

}

  • 源码分析:分析interceptorIndex的值情况

 

 

 

十三、 异常处理 

1、异常处理概述

  1. Spring MVC 通过 HandlerExceptionResolver  处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常。
  2. SpringMVC 提供的 HandlerExceptionResolver 的实现类

 

2、HandlerExceptionResolver

DispatcherServlet  默认装配的 HandlerExceptionResolver

  • 没有使用 <mvc:annotation-driven/> 配置:

  • 使用了 <mvc:annotation-driven/> 配置

ExceptionHandlerExceptionResolver是处理带有注释@ExceptionHandler(value={Exception.class})异常的

ResponseStatusExceptionResolver是处理带有注释@ResponseStatus(reason="runtionError", value=HttpStatus.NOT_FOUND)
class myRuntimeExceptionClass extends RuntimeException{ 的自定义异常类的

除去这两种以外的   都由默认的异常处理器DefaultHandlerExceptionResolver来处理

 

3、实验代码

  • 页面链接

<a href="testExceptionHandlerExceptionResolver?i=1">testExceptionHandlerExceptionResolver</a>

  • 控制器方法

package com.atguigu.springmvc.crud.handlers;

 

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

 

@Controller

public class ExceptionHandler {

@RequestMapping("/testExceptionHandlerExceptionResolver")

public String testExceptionHandlerExceptionResolver(@RequestParam("i") int i){

System.out.println("10/"+i+"="+(10/i));

return "success";

}

}

  • 测试,出现异常情况

处理异常,跳转到error.jsp

  • 在控制器中增加处理异常的方法

@ExceptionHandler(value={java.lang.ArithmeticException.class})

public String handleException(Exception ex){

System.out.println("出现异常啦L"+ex);

return "error";

}

  • 增加error.jsp

<h3>Error Page</h3>

 

4、如何将异常对象从控制器携带给页面,做异常信息的获取

  • 异常对象不能通过Map集合方式传递给成功页面。(Map不可以

// @ExceptionHandler(value={java.lang.ArithmeticException.class})

public String handleException(Exception ex,Map<String,Object> map){

System.out.println("出现异常啦:"+ex);

map.put("exception",ex);

return "error";

}

  • 可以通过ModelAndView将异常对象传递给成功页面上

@ExceptionHandler(value={java.lang.ArithmeticException.class})

public ModelAndView handleException(Exception ex){

System.out.println("出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

return mv;

}

 

5、匹配异常类型,执行顺序问题

@ExceptionHandler(value={java.lang.ArithmeticException.class})

public ModelAndView handleException(Exception ex){

System.out.println("出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

return mv;

}

 

@ExceptionHandler(value={java.lang.RuntimeException.class})

public ModelAndView handleException2(Exception ex){

System.out.println("RuntimeException-出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

return mv;

}

 

 6、公共的处理异常的类@ControllerAdvice

  1. 定义公共的处理异常的类

package com.atguigu.springmvc.exceptionAdvice;

 

import org.springframework.web.bind.annotation.ControllerAdvice;

import org.springframework.web.bind.annotation.ExceptionHandler;

import org.springframework.web.servlet.ModelAndView;

 

@ControllerAdvice

public class ExceptionAdviceHandler {

 

/*        

@ExceptionHandler(value={java.lang.ArithmeticException.class})

public ModelAndView handleException(Exception ex){

 

System.out.println("出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

 

return mv; 

}*/

 

@ExceptionHandler(value={java.lang.RuntimeException.class})

public ModelAndView handleException2(Exception ex){

 

System.out.println("RuntimeException-出现异常啦:"+ex);

ModelAndView mv = new ModelAndView("error");

mv.addObject("exception", ex);

 

return mv;

}

}

 

7、ExceptionHandlerExceptionResolver

  1. 主要处理 Handler 中用 @ExceptionHandler 注解定义的方法。
  2. @ExceptionHandler 注解定义的方法优先级问题:例如发生的是NullPointerException,但是声明的异常有 RuntimeException 和 Exception,此候会根据异常的最近继承关系找到继承深度最浅的那个 @ExceptionHandler 注解方法,即标记了 RuntimeException 的方法
  3. ExceptionHandlerMethodResolver 内部若找不到@ExceptionHandler 注解的话,会找 @ControllerAdvice 中的@ExceptionHandler 注解方法

 

8、异常处理_ResponseStatusExceptionResolver

  1. 在异常及异常父类中找到 @ResponseStatus 注解,然后使用这个注解的属性进行处理。
  2. 定义一个 @ResponseStatus 注解修饰的异常类
  3. 若在处理器方法中抛出了上述异常:若ExceptionHandlerExceptionResolver 不解析上述异常。由于触发的异常 UnauthorizedException 带有@ResponseStatus 注解。因此会被ResponseStatusExceptionResolver 解析到。最后响应HttpStatus.UNAUTHORIZED 代码给客户端。HttpStatus.UNAUTHORIZED 代表响应码401,无权限。 关于其他的响应码请参考 HttpStatus 枚举类型源码。

 

org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver

Implementation of the HandlerExceptionResolver interface that uses the @ResponseStatus annotation to map exceptions to HTTP status codes.

This exception resolver is enabled by default in the

 org.springframework.web.servlet.DispatcherServlet.

 

 

9、实验代码

  • 页面链接

<a href="testResponseStatusExceptionResolver?i=10">testResponseStatusExceptionResolver</a>

  • 自定义异常类

package com.atguigu.springmvc.exception;

 

import org.springframework.http.HttpStatus;

import org.springframework.web.bind.annotation.ResponseStatus;

 

/**

 * 自定义异常类

HttpStatus.FORBIDDEN 不允许的,禁用的

 */

@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名称和密码不匹配")

public class UsernameNotMatchPasswordException extends RuntimeException{}

  • 控制器方法

@RequestMapping(value="/testResponseStatusExceptionResolver")

public String testResponseStatusExceptionResolver(@RequestParam("i") int i){

if(i==13){

throw new UsernameNotMatchPasswordException();

}

System.out.println("testResponseStatusExceptionResolver...");

return "success";

}

  • 出现的错误消息
  1. 没使用注解时:@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名称和密码不匹配")

  1. 使用注解时:@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名称和密码不匹配")

  1. 测试在方法上使用注解

@ResponseStatus(value=HttpStatus.NOT_FOUND,reason="测试方法上设置响应状态码")

@RequestMapping(value="/testResponseStatusExceptionResolver")

public String testResponseStatusExceptionResolver(@RequestParam("i") int i){

if(i==13){

throw new UsernameNotMatchPasswordException();

}

System.out.println("testResponseStatusExceptionResolver...");

return "success";

}

  1. ResponseStatus

package org.springframework.web.bind.annotation;

 

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

 

import org.springframework.http.HttpStatus;

 

/**

 * Marks a method or exception class with the status code and reason that should be returned. The status code is applied

 * to the HTTP response when the handler method is invoked, or whenever said exception is thrown.

 *

 * @author Arjen Poutsma

 * @see org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver

 * @since 3.0

 */

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface ResponseStatus {

 

HttpStatus value();

 

String reason() default "";

 

}

  1. HttpStatus

 

 

10、异常处理_DefaultHandlerExceptionResolver

  1. 对一些特殊的异常进行处理,比如:
    1. NoSuchRequestHandlingMethodException、
    2. HttpRequestMethodNotSupportedException
    3. HttpMediaTypeNotSupportedException、
    4. HttpMediaTypeNotAcceptableException等。
  2. javadoc

org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

Default implementation of the HandlerExceptionResolver interface that resolves standard Spring exceptions and translates them to corresponding HTTP status codes.

This exception resolver is enabled by default in the org.springframework.web.servlet.DispatcherServlet.

 

 

11、实验代码

  • 增加页面链接:GET请求

<a href="testDefaultHandlerExceptionResolver">testDefaultHandlerExceptionResolver</a>

增加处理器方法

//@RequestMapping(value="/testDefaultHandlerExceptionResolver")

@RequestMapping(value="/testDefaultHandlerExceptionResolver",method=RequestMethod.POST)  //不支持GET请求

public String testDefaultHandlerExceptionResolver(){

System.out.println("testDefaultHandlerExceptionResolver...");

return "success";

}

  • 出现异常错误

  •  出现异常交给DefaultHandlerExceptionResolver处理

@Override

protected ModelAndView doResolveException(

HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

 

try {

if (ex instanceof NoSuchRequestHandlingMethodException) {

return handleNoSuchRequestHandlingMethod((NoSuchRequestHandlingMethodException) ex, request, response,

handler);

}

else if (ex instanceof HttpRequestMethodNotSupportedException) {

return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, request,

response, handler);

}

else if (ex instanceof HttpMediaTypeNotSupportedException) {

return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, request, response,

handler);

}

else if (ex instanceof HttpMediaTypeNotAcceptableException) {

return handleHttpMediaTypeNotAcceptable((HttpMediaTypeNotAcceptableException) ex, request, response,

handler);

}

else if (ex instanceof MissingServletRequestParameterException) {

return handleMissingServletRequestParameter((MissingServletRequestParameterException) ex, request,

response, handler);

}

else if (ex instanceof ServletRequestBindingException) {

return handleServletRequestBindingException((ServletRequestBindingException) ex, request, response,

handler);

}

else if (ex instanceof ConversionNotSupportedException) {

return handleConversionNotSupported((ConversionNotSupportedException) ex, request, response, handler);

}

else if (ex instanceof TypeMismatchException) {

return handleTypeMismatch((TypeMismatchException) ex, request, response, handler);

}

else if (ex instanceof HttpMessageNotReadableException) {

return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, request, response, handler);

}

else if (ex instanceof HttpMessageNotWritableException) {

return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, request, response, handler);

}

else if (ex instanceof MethodArgumentNotValidException) {

return handleMethodArgumentNotValidException((MethodArgumentNotValidException) ex, request, response, handler);

}

else if (ex instanceof MissingServletRequestPartException) {

return handleMissingServletRequestPartException((MissingServletRequestPartException) ex, request, response, handler);

}

else if (ex instanceof BindException) {

return handleBindException((BindException) ex, request, response, handler);

}

else if (ex instanceof NoHandlerFoundException) {

return handleNoHandlerFoundException((NoHandlerFoundException) ex, request, response, handler);

}

}

catch (Exception handlerException) {

logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);

}

return null;

}

 

12、异常处理_SimpleMappingExceptionResolver

如果希望对所有异常进行统一处理,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常

 

实验代码

  • 增加页面链接

<a href="testSimpleMappingExceptionResolver?i=1">testSimpleMappingExceptionResolver</a>

  • 增加控制器方法

@RequestMapping("/testSimpleMappingExceptionResolver")

public String testSimpleMappingExceptionResolver(@RequestParam("i") int i){

System.out.println("testSimpleMappingExceptionResolver..."); 

String[] s = new String[10]; 

System.out.println(s[i]); 

return "success";

}

  • 出现异常情况:参数i的值大于10

 

  • 配置异常解析器:自动将异常对象信息,存放到request范围内

<!-- 配置SimpleMappingExceptionResolver异常解析器 -->

<bean id="simpleMappingExceptionResolver"

 class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

<!-- exceptionAttribute默认值(通过ModelAndView传递给页面):

exception   ->  ${requestScope.exception}

public static final String DEFAULT_EXCEPTION_ATTRIBUTE = "exception";

-->

<property name="exceptionAttribute" value="exception"></property>

<property name="exceptionMappings">

<props>

<prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>

</props>

</property>

</bean>

 

error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

 "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body> 

<h3>Error Page</h3> 

${exception }

${requestScope.exception } 

</body>

</html>

 

 

  • 源码分析

SimpleMappingExceptionResolver    L187 L339 

@Override

protected ModelAndView doResolveException(HttpServletRequest request,

 HttpServletResponse response,Object handler, Exception ex) {

 

// Expose ModelAndView for chosen error view.

String viewName = determineViewName(ex, request);

if (viewName != null) {

// Apply HTTP status code for error views, if specified.

// Only apply it if we're processing a top-level request.

Integer statusCode = determineStatusCode(request, viewName);

if (statusCode != null) {

applyStatusCodeIfPossible(request, response, statusCode);

}

return getModelAndView(viewName, ex, request);

}else {

return null;

}

}

 

/**

 * Return a ModelAndView for the given view name and exception.

 * <p>The default implementation adds the specified exception attribute.

 * Can be overridden in subclasses.

 * @param viewName the name of the error view

 * @param ex the exception that got thrown during handler execution

 * @return the ModelAndView instance

 * @see #setExceptionAttribute

 */

protected ModelAndView getModelAndView(String viewName, Exception ex) {

ModelAndView mv = new ModelAndView(viewName);

if (this.exceptionAttribute != null) {

if (logger.isDebugEnabled()) {

logger.debug("Exposing Exception as model attribute '" + this.exceptionAttribute + "'");

}

mv.addObject(this.exceptionAttribute, ex);

}

return mv;

}

 

 

 

十四、 运行流程图解 

1、流程图   

 

2、Spring工作流程描述

  1. 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获;
  2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI:

判断请求URI对应的映射

    • 不存在:
      1. 再判断是否配置了mvc:default-servlet-handler
      2. 如果没配置,则控制台报映射查找不到,客户端展示404错误
      3. 如果有配置,则执行目标资源(一般为静态资源,如:JSP,HTML
    • 存在:
      1. 执行下面流程
  1. 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
  2. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter
  3. 如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法【正向】
  4. 提取Request中的模型数据,填充Handler入参,开始执行HandlerController)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
    • HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
    • 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
    • 数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
    • 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
  5. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
  6. 此时将开始执行拦截器的postHandle(...) 版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
    原文链接:https://blog.csdn.net/qq_25106373/article/details/82387869
    站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-13 13:59:24
  • 阅读 ( 1682 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢