SpringMVC中的拦截器与乱码

拦截器

作用

拦截器是运行在DispatcherServlet之后,在每个Controller之前的,且运行结果可以选择放行或拦截!

除此以外,拦截器还会运行在Controller之后,关于拦截器,在处理某一个请求时,最多有3次执行!只不过,通常关注最多的是第1次执行,即在Controller之前的那次!

基本使用

自定义类,例如名为LoginInterceptor,实现HandlerInterceptor接口,重写3个抽象方法:

public class LoginInterceptor implements HandlerInterceptor { 
    //运行在controller之前
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
    Object handler) throws Exception {       
     System.out.println("LoginInterceptor.preHandle()");     
        return false;  
          }     
      
     public void postHandle(HttpServletRequest request, HttpServletResponse response, 
     Object handler, ModelAndView modelAndView) throws Exception {    
         System.out.println("LoginInterceptor.postHandle()");  
           }   
            
     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
     Object handler, Exception ex) throws Exception {     
        System.out.println("LoginInterceptor.afterCompletion()");   
         }
      }

拦截器需要在Spring的配置文件中进行配置后才可以生效!所以,需要添加配置:

配置拦截器链

<mvc:interceptors>
    <!-- 配置第1个拦截器 -->
    <mvc:interceptor>
        <!-- 指定拦截路径,不在拦截路径之内的将不予处理,即拦截器根本就不运行 -->
        <mvc:mapping path="/user/info.com"/>
        <mvc:mapping path="/user/password.com"/>
        <!-- 指定拦截器类 -->
        <bean class="cn.edu.spring.interceptor.LoginInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

在拦截器类中,运行在Controller之前的是preHandle()方法,该方法返回true表示放行,返回false表示拦截!
对于登录拦截器而言,可以判断Session中的用户数据,如果数据存在,视为已登录,可直接放行,如果没有数据,则视为没登录,需要重定向,并拦截:

public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("LoginInterceptor.preHandle()");
    // 判断Session中的数据,得知是否登录
    HttpSession session = request.getSession();
    if (session.getAttribute("username") == null) {
        // Session中没有用户名,即:没有登录,则:重定向,并拦截
        response.sendRedirect("../user/login.com");
        // 返回false表示拦截
        return false;
    }
    // 返回true表示放行
    return true;
}

在配置拦截器时,根节点是mvc:interceptors,用于配置拦截器链,即任何一个SpringMVC项目,都可以有若干个拦截器,从而形成拦截器链,如果某个请求符合多个拦截器的拦截配置,则会依次被各拦截器进行处理,任何一个拦截,都会导致后续不再将请求交给Controller去处理!

在mvc:interceptors(有s)节点子级,可以配置多个mvc:interceptor(没有s)子级节点,表示多个拦截器,拦截器链的执行顺序取决于这里各节点的配置先后顺序!

在mvc:interceptor中,节点用于指定拦截器类;mvc:mapping节点,用于配置拦截的请求路径,每个拦截器可以配置多个该节点,并且,在配置时,支持使用星号作为通配符,例如:<mvc:mapping path="/user/"/>,为了避免拦截范围过大,可以通过<mvc:exclude-mapping />配置排除在外的请求路径,可以理解为白名单,该节点也可以配置多个:

拦截器链
<mvc:interceptors>
    <!-- 配置第1个拦截器 -->
    <mvc:interceptor>
        <!-- 指定拦截路径,不在拦截路径之内的将不予处理,即拦截器根本就不运行 -->
        <mvc:mapping path="/user/*" />
        <!-- 指定白名单,列举的请求路径将不予处理,即拦截器根本就不运行 -->
        <mvc:exclude-mapping path="/user/reg.com" />
        <mvc:exclude-mapping path="/user/login.com" />
        <mvc:exclude-mapping path="/user/handle_reg.com" />
        <mvc:exclude-mapping path="/user/handle_login.com" />
        <!-- 指定拦截器类 -->
        <bean class="cn.edu.spring.interceptor.LoginInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

注意:以上配置黑名单或白名单时,都可以使用星号作为通配符,但是,它只能匹配1层路径(或者说只能通配任意资源)!例如配置的是/user/,可以匹配/user/reg.com或/user/login.com,却无法匹配到/user/a/reg.com或/user/a/b/c/login.com这样的路径!如果需要匹配多层路径,可以使用2个星期,即**,例如配置/user/**则可以匹配以上任意路径!

乱码

关于乱码

在处理中文或非ASCII字符(需要使用输入法才可以输入的)时,如果存、取时,使用的字符编码不统一,就会出现乱码!
所以,出现乱码原因就是因为字符编码不统一,而解决问题的方案就是使用统一的编码!

需要统一编码的位置有:项目源码、数据库、处理数据的服务端组件、数据传输过程、#显示界面

解决控制器中接收请求参数的乱码

通常,在Java EE项目中,解决问题的方式是:

request.setCharacterEncoding("utf-8");

由于Controller是运行在DispatcherServlet之后的,在Controller内部再执行更改编码格式已经晚了,事实上SpringMVC框架在DispatcherServlet之前就存在CharacterEncodingFilter可以确定请求与响应的编码格式,所以,在SpringMVC中,无法通过Controller或Interceptor来解决请求和响应的乱码问题。
在SpringMVC框架的CharacterEncodingFilter中,把使用的字符编码设计为变量,可以在web.xml中添加配置加以应用,来统一设置编码:

<!-- 配置字符编码过滤器 -->
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

拦截器与过滤器有什么区别

拦截器是Interceptor,过滤器是Filter;

拦截器是SpringMVC中的组件,过滤器是Java EE中的组件;

拦截器是配置在Spring的配置文件中的,过滤器是配置在web.xml中的;

拦截器是运行在DispatcherServlet之后、Controller之前的,且在Controller执行完后还会调用2个方法,而过滤器是运行在所有的Servlet之前的;

拦截器的配置非常灵活,可以配置多项黑名单,也可以配置多项白名单,过滤器的配置非常单一,只能配置1项过滤路径;

拦截器与过滤器也有很多相似之处,例如:都可拒绝掉某些访问,也可以选择放行;都可以形成链。

相比之下,在一个使用SpringMVC框架的项目中,拦截器会比过滤器要好用一些,但是,由于执行时间节点的原因,它并不能完全取代过滤器!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值