Spring--拦截器,字符编码过滤器

xiaoxiao2025-10-19  9

1. SpringMVC中的Interceptor

1.1. 练习目标

在主页显示的“用户名”位置添加超链接,点击后进入“个人中心”。

通过/user/info.do路径,可以显示“个人信息”页面,该页面需要登录后才允许访问。

1.2. 分析问题

一个项目中,可能绝大部分的功能都是需要登录后才允许使用的,但是,在这些功能的处理中,可能都需要执行:

// 判断Session中是否有username if (session.getAttribute("username") == null) { // 没有,则意味着没有登录,则重定向到登录页 return "redirect:login.do"; }

而大量的复制并粘贴以上代码的做法显然是不可取的!

1.3. 解决方案

拦截器(Interceptor)是SpringMVC中的组件,它是运行在DispatcherServlet之后、每个Controller之前的组件,并且,运行时,可以选择拦截或放行,则会导致某些请求可以被处理或不被处理!然后,拦截器还可以运行在每个Controller处理完请求之后。

基于拦截器这样的特点,可以在项目中添加“登录拦截器”,使得要求登录的请求都先经过“登录拦截器”进行判断,在“登录拦截器”中将判断Session是否有效,如果有效,则放行,如果没有有效的Session,则直接拦截,并重定向到登录页。

1.4. 使用方式

1.4.1. 创建拦截器

所有的自定义拦截器,都必须实现HandlerInterceptor接口,所以,在项目中创建cn.huang.spring.interceptor.LoginInterceptor,实现HandlerInterceptor:

public class LoginInterceptor implements HandlerInterceptor { 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()"); } }

1.4.2. 配置拦截器

在springmvc.xml中添加拦截器的配置:

<!-- 配置拦截器链 --> <mvc:interceptors> <!-- 配置第1个拦截器 --> <mvc:interceptor> <!-- 1. 拦截的路径 --> <mvc:mapping path="/user/info.do" /> <mvc:mapping path="/main/index.do" /> <!-- 2. 指定拦截器类 --> <bean class="cn.huang.spring.interceptor.LoginInterceptor" /> </mvc:interceptor> </mvc:interceptors>

1.4.3. 执行效果

当尝试访问以上拦截的路径时,可以看到拦截器的preHandle()方法被执行,且界面上显示一片空白,而没有被拦截器路径可以正常访问,拦截器中的任何方法都没有执行。

1.4.4. 完善登录拦截

在控制器中,成功登录时,会在Session中放入用户名,且存入时使用的名称是username,所以,判断是否登录,就是检查Session是否有名为username的值,如果值是存在的,即已经登录,如果值不存在,则没有登录,所以,在拦截器的preHandle()方法中:

public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("LoginInterceptor.preHandle()"); // 获取Session HttpSession session = request.getSession(); // 判断session中是否有登录信息 if (session.getAttribute("username") == null) { // 没有登录信息,则:重定向到登录页 response.sendRedirect("../user/login.do"); // 执行拦截 return false; } else { // 有登录信息,则:允许正常访问,直接放行 return true; } }

1.4.5. 拦截器的更多配置

在配置拦截器时,使用<mvc:mapping path="" />可以配置拦截哪些路径,同一个拦截器的配置中,可以有多个这样的节点。

在配置拦截路径时,可以使用*作为通配符,例如:

<mvc:mapping path="/user/*" />

以上配置将表示拦截/user之下的所有路径,例如:/user/login.do、/user/reg.do、/user/handler_login.do、/user/handler_reg.do、/user/inf.do等。

使用1个星号(*)只能通配1层路径,即以上配置对于/user/info/change.do这样的路径是不起作用的!如果需要无视路径的层级,应该使用2个星号(*),即配置为:

<mvc:mapping path="/user/**" />

使用以上配置,可适用于例如:/user/login.do、/user/info/change.do、/user/info/change/password.do等。

由于使用于通配符后,拦截的范围可能过大,还可以使用<mvc:exclude-mapping />节点来配置例外:

<mvc:interceptor> <!-- 1. 拦截的路径 --> <mvc:mapping path="/user/**" /> <mvc:mapping path="/main/index.do" /> <!-- 2. 例外的路径,不拦截的路径,即白名单--> <mvc:exclude-mapping path="/user/reg.do" /> <mvc:exclude-mapping path="/user/handle_reg.do" /> <mvc:exclude-mapping path="/user/login.do" /> <mvc:exclude-mapping path="/user/handle_reg.do" /> <!-- 3. 指定拦截器类 --> <bean class="cn.huang.spring.interceptor.LoginInterceptor" /> </mvc:interceptor>

这些例外可以通俗的理解为白名单,即拦截器对于这些路径的请求完全不受理。

注意:以上配置,必须先配置拦截路径,再配置例外,最后配置拦截器类。

2. 字符编码过滤器

使用SpringMVC框架时,默认并不支持中文,为了能够支持中文,需要通过request.setCharacterEncoding("utf-8")这类的语法来指定使用的字符编码!

这项任务不能够在控制器(Controller)中来完成,因为,指定编码必须在Servlet或其之前就执行,如果运行到Servlet时就已经乱码,然后,在控制器中再来调整,就已经晚了!也就意味着,通过SpringMVC的拦截器是无法实现编码的调整的!

解决方案是使用SpringMVC框架中自带的CharacterEncodingFilter类,这个类是一个过滤器类,是运行在所有的Servlet之前的,所以,通过过滤器指定了编码后,适用于所有的Servlet及后续的流程!

这个类并没有明显的指定使用的编码,所以,在配置时,还需要通过初始化参数来确定所使用的编码!

具体的配置是在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>
转载请注明原文地址: https://www.6miu.com/read-5038175.html

最新回复(0)