### 1. 使用Session

通常,会在Session中存放:

1. 客户端(用户)的身份标识,通常是用户的id;
2. 使用频率非常高的数据,例如显示在页面中的用户名、头像等;
3. 其它的不便于使用其它存储方案来存取或传递的数据。

关于Session的使用,和`ModelMap`几乎一样,即在处理请求的方法中添加`HttpSession`参数,并在方法体中操作该参数对象即可。

### 2. 拦截器:Interceptor

Spring MVC中的拦截器(Interceptor)与Java EE中的过滤器(Filter)比较相似,可以对某些请求尝试拦截,由开发者自行编写拦截的逻辑,使得某些请求可以执行,而某些请求将不允许执行,实现统一管理的效果。

在使用时,必须先自定义拦截器类,实现`HandlerInterceptor`接口,然后在Spring的配置文件中进行配置。

当实现`HandlerInterceptor`接口后,需要重写3个未实现的方法,其中,`public boolean preHandle()`方法是起到拦截作用的,在运行在控制器之前的,该方法的返回值是boolean类型的,表示是否放行,即返回true则放行,返回false则拦截!一旦拦截,控制器方法将不会被执行,并且拦截器中剩下的2个方法也不会被执行,如果通过浏览器进行访问,界面将显示一片空白!

注意:即使执行重定向语法,如果拦截器`return true;`,依然会执行控制器中的方法和拦截器中另2个方法,则没有拦截效果,所以,当符合拦截条件时,应该`return false;`。

关于拦截器的配置大致如下:

  1. <!-- 拦截器链 -->
  2. <mvc:interceptors>
  3. <!-- 第1个拦截器 -->
  4. <mvc:interceptor>
  5. <!-- 拦截路径 -->
  6. <mvc:mapping path="/user/index.do"/>
  7. <!-- 拦截器类 -->
  8. <bean class="cn.tedu.spring.interceptor.LoginInterceptor"></bean>
  9. </mvc:interceptor>
  10. <!-- 第2个拦截器 -->
  11. <!-- 第3个拦截器 -->
  12. <!-- 第N个拦截器 -->
  13. </mvc:interceptors>

即:SpringMVC是支持**拦截器链**的,在同一个项目中,允许存在多个拦截器,形成拦截器链,多个拦截器的执行先后顺序取决于配置的先后顺序。

在配置每一个拦截器的`<mvc:interceptor>`节点中,`<mvc:mapping>`节点用于配置需要拦截的路径,该节点可以存在若干个,例如:

  1. <mvc:interceptor>
  2. <!-- 拦截路径 -->
  3. <mvc:mapping path="/user/index.do"/>
  4. <mvc:mapping path="/user/logout.do"/>
  5. <!-- 拦截器类 -->
  6. <bean class="cn.tedu.spring.interceptor.LoginInterceptor"></bean>
  7. </mvc:interceptor>

并且,在配置路径时,是支持通配符的,例如:

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

即:例如`/user/reg.do`、`/user/login.do`、`/user/handle_reg.do`等这些路径都在拦截范围之内!

但是,需要注意的是:1个星号表示的通配符只能匹配1层路径,例如`/user/*`不可以匹配到`/user/news/list.do`这样的路径!如果要匹配若干层路径,可以使用2个星号,例如配置为`/user/**`。

除此以外,在配置时,还可以添加`<mvc:exclude-mapping>`节点,以配置例外,例如:

  1. <!-- 拦截路径 -->
  2. <mvc:mapping path="/user/*"/>
  3. <!-- 添加例外 -->
  4. <mvc:exclude-mapping path="/user/reg.do"/>
  5. <mvc:exclude-mapping path="/user/login.do"/>
  6. <mvc:exclude-mapping path="/user/handle_reg.do"/>
  7. <mvc:exclude-mapping path="/user/handle_login.do"/>

关于`<mvc:exclude-mapping>`的配置方式,与`<mvc:mapping>`相同,也可以使用通配符。

以上`<mvc:mapping>`也可以理解为**拦截名单**,而`<mvc:exclude-mapping>`就是**白名单**。

以上配置是必须有先后顺序的,`<mvc:mapping>`必须在最前,其次是`<mvc:exclude-mapping>`,最后是拦截器`<bean>`。

仅在拦截范围之内的,才会触发拦截器执行(无论最终是拦截还是放行),如果某路径不在拦截范围之内(包含被添加到例外的),将根本就不触发拦截器的执行。

### 3. SpringMVC项目的乱码解决方案

整个SpringMVC框架默认使用的编码都是ISO-8859-1,是不支持中文的,所以,在`DispatcherServlet`接收到请求的那一刻起,数据的编码就已经是ISO-8859-1,为了修改编码,只能通过过滤器(Filter)来设置,在SpringMVC中也定义好了`CharacterEncodingFilter`,用于设置字符编码,所以,当使用SpringMVC时,应该在`web.xml`中配置该过滤器,并为这个过滤器类的`encoding`属性设置编码值:

  1. <filter>
  2. <filter-name>CharacterEncodingFilter</filter-name>
  3. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  4. <init-param>
  5. <param-name>encoding</param-name>
  6. <param-value>utf-8</param-value>
  7. </init-param>
  8. </filter>
  9.  
  10. <filter-mapping>
  11. <filter-name>CharacterEncodingFilter</filter-name>
  12. <url-pattern>/*</url-pattern>
  13. </filter-mapping>

### 4. SpringMVC处理异常

控制器是向客户端进行响应的组件,如果在控制器中的代码运行时出现异常,应该进行处理,如果不处理异常,则会按照默认的方式处理,有几处问题:

1. 对于没有计算机开发相关基础的用户而言,体验很差(界面上显示的错误完全看不懂);
2. 对于掌握了计算机开发相关技术的用户而言,可能从中获取当前项目的某些实现细节(异常的跟踪信息中会显示某些类、方法的名称等),导致项目的部分内容外泄;
3. 其它问题。

所以,在控制器中,应该对可能存在的异常进行处理!注意:此处的“处理”不包括使用`throw`抛出,而是通过`try...catch`类似的方式捕获并在`catch`代码块中进行处理,例如:

  1. @RequestMapping("null.do")
  2. public String showNull(
  3. String username, ModelMap modelMap) {
  4. try {
  5. username.length();
  6. } catch (NullPointerException e) {
  7. String message = "您的操作有误,未提交必要的参数,请<a href=input.do>重新提交</a>!";
  8. modelMap.addAttribute("msg", message);
  9. return "error";
  10. }
  11.  
  12. return null;
  13. }

由于异常出现的频率可能较高,或者,在多个不同的请求中都可能出现,那么,在每个方法中都进行处理,是不现实的,也不便于代码的管理!

在SpringMVC中,提供了2种统一处理异常的做法:

**1. 通过SimpleMappingExceptionResolver**

在Spring的配置文件中,对`SimpleMappingExceptionResolver`进行配置,确定异常与转发的页面的映射即可:

  1. <!-- 处理异常 -->
  2. <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  3. <property name="exceptionMappings">
  4. <props>
  5. <prop key="java.lang.NullPointerException">error</prop>
  6. <prop key="java.lang.StringIndexOutOfBoundsException">oob</prop>
  7. <prop key="java.lang.RuntimeException">runtime</prop>
  8. </props>
  9. </property>
  10. </bean>

使用这种做法时,如果出现异常,框架将自动转发到对应的页面,开发者难以对异常出现的原因作出针对性的处理!所以,这种做法只适合比较粗糙的、大概的处理异常!

同时,这种做法固定使用转发来显示错误提示页面,无法更改为其它方式的响应!

**2. 使用@ExceptionHandler**

在控制器类中,可以自定义处理异常的方法,并在方法之前添加`@ExceptionHandler`注解,该方法的设计规则与处理请求的方法大致相同,区别在于参数不可以随便写,必须包含1个异常类型的参数,

  1. @ExceptionHandler
  2. public String handleException(Exception e) {
  3. if (e instanceof NullPointerException) {
  4. return "error";
  5. } else if (e instanceof StringIndexOutOfBoundsException) {
  6. return "oob";
  7. }
  8. return "exception";
  9. }

> 使用`@ExceptionHandler`之前,必须保证在Spring配置文件中已经配置了注解驱动,即`<mvc:annotation-driven />`。

在使用`@ExceptionHandler`注解时,可以在注解中添加属性的配置,以确定所处理的异常的范围,例如:

@ExceptionHandler(IndexOutOfBoundsException.class)

经过以上配置,仅`IndexOutOfBoundsException`及其子孙类异常会被接下来的方法进行处理,而其它异常的出现,并不会导致对应的方法被执行!

在控制器中,允许同时存在多个处理异常的方法!

处理异常的方法仅能作用于当前控制器类中的请求!如果某个处理异常的方法的代码希望被通用,可以将这个处理异常的方法写在控制器类的基类中。

以上两种统一处理异常的方式是可以同时存在的!且第2种方式的优先级高于第1种方式。

**附:常见异常**

  1. Throwable
  2. Error
  3. OutOfMemoryError
  4. Exception
  5. SqlException
  6. IOException
  7. FileNotFoundException
  8. RuntimeException
  9. NullPointException
  10. ClassCastException
  11. ArithmeticException
  12. IndexOutOfBoundsException
  13. ArrayIndexOutOfBoundsException

### 【附】 拦截器和过滤器的区别

过滤器(Filter)是Java EE体系中的,而拦截器(Interceptor)是SpringMVC中的;

过滤器是在所有的Servlet之前执行的,而拦截器的初次执行是在DispatcherServlet之后、在Controller之前执行的;

过滤器的过滤范围只能在web.xml中通过<url-pattern>这1个节点来配置,而拦截器可以配置多个拦截路径,且可以添加例外,配置更加灵活;

所有的请求都可以被过滤器进行处理,却只有交由DispatcherServlet分发的请求才可能被拦截器处理!

### 【附】 字符编码问题 / 出错时的乱码问题

在不考虑某些编码不支持中文的情况下,使用了支持中文的编码,仍会出现乱码的原因只有1个:存和取的时候使用了不同的编码。

所以,解决方案就是:整个项目涉及的所有位置全部使用相同的编码!

通常,需要指定编码的位置有:
1. 项目的源代码,例如某个String类型数据的值;
2. 显示界面的组件所使用的编码,例如HTML/JSP使用的编码;
3. 数据存储位置使用的编码,例如数据库中的编码;
4. 数据传输过程中使用的编码,例如请求、响应,或数据库连接的URL。

SpringMVC中session使用&&拦截器&&乱码处理&&异常处理的更多相关文章

  1. SpringMVC中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  2. SpringMVC 中的Interceptor 拦截器

    1.配置拦截器 在springMVC.xml配置文件增加: <mvc:interceptors>  <!-- 日志拦截器 -->  <mvc:interceptor> ...

  3. SpringMVC中的Interceptor拦截器及与Filter区别

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  4. [转]SpringMVC中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  5. SpringMVC之七:SpringMVC中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那 ...

  6. SpringMVC中使用Interceptor拦截器顺序

    一.简介 SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验 证,或者是来判断用户是否登陆,或者是像1 ...

  7. SpringMVC配置session过期拦截器,返回登录页面

    spring-mvc.xml配置 <mvc:interceptors> <!-- session失效拦截器 --> <mvc:interceptor> <!- ...

  8. SpringMvc中的Interceptor拦截器的学习

    拦截器是SpringMvc框架中常用的一个东东,它跟Filter相似,但是也有区别,以前也没用过,今天看到就顺便学习了一下. SpirngMvc中的Interceptor主要是通过HandlerInt ...

  9. JavaEE开发之SpringMVC中的自定义拦截器及异常处理

    上篇博客我们聊了<JavaEE开发之SpringMVC中的路由配置及参数传递详解>,本篇博客我们就聊一下自定义拦截器的实现.以及使用ModelAndView对象将Controller的值加 ...

随机推荐

  1. spring集成JPA的三种方法配置

    JPA是Java EE5规范之一,是一个orm规范,由厂商来实现该规范.目前有hibernate,OpenJPA,TopLink和EclipseJPA等实现 spring提供三种方法集成JPA:1.L ...

  2. oracle之数据同步:Oracle Sql Loader使用说明(大批量快速插入数据库记录)

    1.准备表数据 select * from emp10; create sequence seq_eseq increment start maxvalue ; --得到序列的SQL语句 select ...

  3. jQuery之设置元素内容(移动和复制元素,使用append(),appendTo()方法)

    jQuery之设置元素内容(移动和复制元素,使用append(),appendTo()方法) ---------- 如果想把内容添加到现有内容末尾,可以利用append()命令.append()命令语 ...

  4. The nineteenth day

    Twinkle,twinkle,little start! 闪烁,闪烁,小星星 How I wonder what you are, 我想知道你是什么 Up above the world so hi ...

  5. Prime Numbers in a Grid素数网格

    &/@ Shorthand notation for Map If[PrimeQ[#], Framed@Style[#, Orange, Bold, 15], #] & /@ Rang ...

  6. Android 自定义ListView滚动条样式

    使用ListView FastScroller,默认滑块和自定义滑块图片的样子: 设置快速滚动属性很容易,只需在布局的xml文件里设置属性即可: <ListView android:id=&qu ...

  7. scope 作用域(bean 的生存范围)

    默认是 singleton ,单例模式,如下代码: @Test public void testAddUser() throws Exception { ApplicationContext ctx ...

  8. Django:Django的路由系统

    一,URLconf配置 1,基本格式 from django.conf.urls import url urlpatterns = [ url(正则表达式, views视图函数,参数,别名), ] 2 ...

  9. 【[APIO2012]派遣】

    题目 直接线段树合并就好了 之后在线段树上二分贪心选取金额较少的 如果是左偏树的话就开一个大根堆,根和子树顺次合并,合并之后堆内所有元素总和如果大于\(m\)就删除堆顶,由于每个元素只会被删除一次,所 ...

  10. CF449C Jzzhu and Apples

    嘟嘟嘟 这道题正解是怎么对的其实我也不清楚,总之靠感性理解吧. 首先当然要把1到n / 2的素数都筛出来,因为两两能配对的数一定都是这些素数的倍数.这也就说明对于(n / 2, n]的素数,他们一定不 ...