SpringMVC中session使用&&拦截器&&乱码处理&&异常处理

### 1. 使用Sessionjava

一般,会在Session中存放:web

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

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

### 2. 拦截器:Interceptor浏览器

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

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

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

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

关于拦截器的配置大体以下:url

<!-- 拦截器链 -->
    <mvc:interceptors>
        <!-- 第1个拦截器 -->
        <mvc:interceptor>
            <!-- 拦截路径 -->
            <mvc:mapping path="/user/index.do"/>
            <!-- 拦截器类 -->
            <bean class="cn.tedu.spring.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
        <!-- 第2个拦截器 -->
        <!-- 第3个拦截器 -->
        <!-- 第N个拦截器 -->
    </mvc:interceptors>

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

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

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

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

<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>`节点,以配置例外,例如:

<!-- 拦截路径 -->
    <mvc:mapping path="/user/*"/>
    <!-- 添加例外 -->
    <mvc:exclude-mapping path="/user/reg.do"/>
    <mvc:exclude-mapping path="/user/login.do"/>
    <mvc:exclude-mapping path="/user/handle_reg.do"/>
    <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`属性设置编码值:

<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>

### 4. SpringMVC处理异常

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

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

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

@RequestMapping("null.do") public String showNull( String username, ModelMap modelMap) { try { username.length(); } catch (NullPointerException e) { String message = "您的操做有误,未提交必要的参数,请<a href=input.do>从新提交</a>!"; modelMap.addAttribute("msg", message); return "error"; } return null; }

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

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

**1. 经过SimpleMappingExceptionResolver**

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

<!-- 处理异常 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.NullPointerException">error</prop>
                <prop key="java.lang.StringIndexOutOfBoundsException">oob</prop>
                <prop key="java.lang.RuntimeException">runtime</prop>
            </props>
        </property>
    </bean>


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

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

**2. 使用@ExceptionHandler**

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

 @ExceptionHandler public String handleException(Exception e) { if (e instanceof NullPointerException) { return "error"; } else if (e instanceof StringIndexOutOfBoundsException) { return "oob"; } return "exception"; }

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

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

@ExceptionHandler(IndexOutOfBoundsException.class)

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

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

处理异常的方法仅能做用于当前控制器类中的请求!若是某个处理异常的方法的代码但愿被通用,能够将这个处理异常的方法写在控制器类的基类中。

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

**附:常见异常**

 Throwable Error OutOfMemoryError Exception SqlException IOException FileNotFoundException RuntimeException NullPointException ClassCastException ArithmeticException IndexOutOfBoundsException ArrayIndexOutOfBoundsException


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

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

过滤器是在全部的Servlet以前执行的,而拦截器的初次执行是在DispatcherServlet以后、在Controller以前执行的;

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

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

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

在不考虑某些编码不支持中文的状况下,使用了支持中文的编码,仍会出现乱码的缘由只有1个:存和取的时候使用了不一样的编码。

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

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

相关文章
相关标签/搜索