跳至主要內容

转换、过滤、拦截、异常

荒流2021年2月18日大约 9 分钟约 2809 字

1. 转换器

1.1 场景

SpringMVC 默认已经提供了一些常用的类型转换器,例如客户端提交的参数总是字符串类型,SpringMVC 可以将数字自动转换成 int 类型。

然而并不提所有的数据类型都提供了转换器,没有提供的就需要自定义了。例如,不同风格的日期类型的数据就需要自定义转换器。

1.2 自定义类型转换器

自定义类型转换器的开发步骤:

  1. 定义转换器类,实现Converter接口;
  2. spring-mvc.xml配置文件中声明转换器;
  3. <annotation-driven>中引用转换器。

示例:

2. 全局乱码过滤器

Tomcat 在面对 post 请求时,中文数据会出现乱码,如下的一张表单:

姓名年龄
张三18
李四17

在提交后数据显示为

VO{userList=[User{username='??????', age=18}, User={username='??????', age=17}]}

在 SpringMVC 框架下解决乱码问题,可以设置一个过滤器来进行编码的过滤:

3. 拦截器

3.1 简介

拦截器(interceptor)的作用:SpringMVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理后处理

将拦截器按一定的顺序联结成一条链,即成为拦截器链(Interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

拦截器也是 AOP 思想的具体实现。

拦截器与过滤器的区别:

区别过滤器拦截器
使用范围是 Servlet 规范中的一部分,任何 Java Web 工程都可以使用是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用
拦截范围在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截只会拦截访问的控制器方法,如果访问的是 jsp、html、css、image、js,是不会进行拦截的

3.2 使用拦截器

当拥有多个拦截器时,其按照在 spring-mvc.xml 配置文件中出现的顺序先后执行,参照过滤器Filter

  1. 创建拦截器类,实现 HandlerInterceptor 接口:

    package com.itheima.interceptor;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    public class MyInterceptor implements HandlerInterceptor {
        /**
         * 在目标方法执行之前执行
         *
         * @return // 返回 true 代表放行,返回 false 代表拦截
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            System.out.println("preHandle.......");
            return false;
        }
        // 在目标方法执行之后、视图对象返回之前执行
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle......");
        }
        // 在流程都执行完毕后执行
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            System.out.println("afterCompletion......");
        }
    }
  2. 配置拦截器:spring-mvc.xml

    <!--  配置拦截器  -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--  对哪些资源执行拦截操作,这里设置全部  -->
            <mvc:mapping path="/*"/>
            <bean class="com.itheima.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
  3. 测试

    • 令 preHandle 返回 false 时:

      浏览器控制台输出
      localhost/target
      web 页面显示:
      preHandle.......
    • 令 preHandle 返回 true 时:

      浏览器控制台输出
      localhost/target
      web 页面显示:Hello World!itcast
      preHandle.......
      目标资源执行......
      postHandle......
      afterCompletion......

3.3 拦截器方法说明

方法说明
preHandle此方法在请求处理之前进行调用,其返回值为 Boolean 类型。当其返回 false,表示请求结束,后续的 Interceptor 和 Controller 都不会再执行;当返回 true,则会调用下一个 Interceptor 的 preHandle() 方法。
postHandle此方法在当前请求进行处理之后、DispatcherServlet 进行视图返回渲染之前被调用,前提是 preHandle() 方法的返回值为 true。此方法可用于对 Controller 处理之后的 ModelAndView 对象进行操作。
afterCompletion此方法在整个请求结束之后(也就是在 DispatcherServlet 渲染了对应的视图之后)执行,前提也是 preHandle() 方法的返回值为 true。

4. 静态资源访问

参见视频 https://www.bilibili.com/video/BV1WZ4y1H7du?p=102

SpringMVC 开放静态资源的访问有两种方式:

5. 异常处理机制

5.1 前言

参见视频 https://www.bilibili.com/video/BV1WZ4y1H7du?p=125

系统的 Dao、Service、Controller 出现异常时,都通过 throws Exception 向上抛出,最后由 SpringMVC 前端控制器交由异常处理器进行异常处理,如下图:

img
img

SpringMVC 异常处理的两种方式:

  1. 使用 SpringMVC 提供的简单异常处理器SimpleMappingExceptionResolver

  2. 自定义自己的异常处理器,需实现 Spring 的异常处理接口HandlerExceptionResolver

5.2 简单异常处理器SimpleMappingExceptionResolver

在使用时可以根据项目情况进行相应异常类型与视图的映射配置。

<!-- 配置简单映射异常处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
	<!-- 默认错误视图 -->
    <property name="fefaultErrorView" value="error" />
    <property name="exceptionMappings">
    	<map>
            <!-- 异常类型:com.itheima.exception.MyException 
                 错误视图:error
		    -->
        	<entry key="com.itheima.exception.MyException" value="error" />
            <entry key="java.lang.ClassCastException" value="error" />
        </map>
    </property>
</bean>

5.3 自定义异常处理

  1. 创建异常处理器类实现HandlerExceptionResolver

    package com.itheima.resolver;
    
    import com.itheima.exception.MyException;
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.
    ;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MyExceptionResolver implements HandlerExceptionResolver {
        /**
         * @param e:异常对象
         * @return ModelAndView:要跳转到的错误视图的信息
         */
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
            ModelAndView modelAndView = new ModelAndView();
            if (e instanceof MyException) {
                modelAndView.addObject("info", "自定义异常");
            } else if (e instanceof ClassCastException) {
                modelAndView.addObject("info", "类型转换异常");
            }
            modelAndView.setViewName("error");
            return modelAndView;
        }
    }
  2. 配置异常处理器(只要配置个 bean 就行,因为处理操作已在异常处理器内实现)——spring-mvc.xml

    <!-- 自定义异常处理器 -->
    <bean class="com.itheima.resolver.MyExceptionResolver"/>
  3. 编写异常页面——error.jsp;

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Error</title>
        </head>
        <body>
            <h1>通用的错误提示页面</h1>
            <h1>${info}</h1>
        </body>
    </html>
  4. 测试异常跳转 。