13.5 实现Web层 13.5.1 控制器的处理顺序

13.5 实现Web层

前面部分已经实现了本应用的所有中间层,系统的所有业务逻辑组件也都部署在Spring容器中了。接下来应该为应用实现Web层了。通常而言,系统的控制器和JSP在起设计。因为当JSP页面发出请求后,该请求被控制器接收,然后控制器负责调用业务逻辑组件来处理请求。从这个意义上来说,控制器是JSP页面和业务逻辑组件之间的纽带。

13.5.1 控制器的处理顺序

对于使用Spring MVC的应用而言,控制器实际上由两个部分组成:系统的核心控制器DispatcherServlet和业务控制器Controller:

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID"
version="3.1">
<!-- 配置spring核心监听器,默认会以 /WEB-INF/applicationContext.xml作为配置文件 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- contextConfigLocation参数用来指定Spring的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<!-- 定义Spring MVC的前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 让Spring MVC的前端控制器拦截所有请求 -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 编码过滤器 -->
<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>
<!-- jsp的配置 -->
<jsp-config>
<jsp-property-group>
<!-- 配置拦截所有的jsp页面 -->
<url-pattern>*.jsp</url-pattern>
<!-- 可以使用el表达式 -->
<el-ignored>false</el-ignored>
<!-- 不能在页面使用java脚本 -->
<scripting-invalid>true</scripting-invalid>
<!-- 给所有的jsp页面导入要依赖的库,tablib.jsp就是一个全局的标签库文件 -->
<include-prelude>/WEB-INF/jsp/taglib.jsp</include-prelude>
</jsp-property-group>
</jsp-config>
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

springmvc-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 自动扫描该包,SpringMVC会将包下用了@controller注解的类注册为Spring的controller -->
<context:component-scan
base-package="org.fkit.hrm.controller" />

<!-- 设置默认配置方案 -->
<mvc:annotation-driven />

<!-- 使用默认的Servlet来响应静态文件 -->
<mvc:default-servlet-handler />

<!-- 定义Spring MVC的拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截所有请求 -->
<mvc:mapping path="/*" />
<!-- 自定义判断用户权限的拦截类 -->
<bean class="org.fkit.hrm.interceptor.AuthorizedInterceptor" />
</mvc:interceptor>
</mvc:interceptors>

<!-- 视图解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />

<!-- 文件上传下载 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件大小上限,单位为字节(10MB) -->
<property name="maxUploadSize">
<value>10485760</value>
</property>
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
</bean>
</beans>

springmvc-config.xml文件中配置了一个拦截器,用于判断用户是否登录,如果其没有登录,则用户不能访问网站,跳回登录页面重新登录。

AuthorizedInterceptor.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package org.fkit.hrm.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.fkit.hrm.domain.User;
import org.fkit.hrm.util.common.HrmConstants;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
* 判断用户权限的Spring MVC的拦截器
*/
public class AuthorizedInterceptor implements HandlerInterceptor
{
/** 定义不需要拦截的请求 */
private static final String[] IGNORE_URI ={"/loginForm", "/login", "/404.html"};

/**
* 该方法需要preHandle方法的返回值为true时才会执行。 该方法将在整个请求完成之后执行,主要作用是用于清理资源。
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception exception)
throws Exception
{

}

/**
* 这个方法在preHandle方法返回值为true的时候才会执行。 执行时间是在处理器进行处理之
* 后,也就是在Controller的方法调用之后执行。
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler, ModelAndView mv)
throws Exception
{

}

/**
* preHandle方法是进行处理器拦截用的,该方法将在Controller处理之前进行调用,
* 当preHandle的返回值为false的时候整个请求就结束了。
* 如果preHandle的返回值为true,则会继续执行postHandle和afterCompletion。
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception
{
/** 默认用户没有登录 */
boolean flag = false;
/** 获得请求的ServletPath */
String servletPath = request.getServletPath();
/** 判断请求是否需要拦截 */
for (String s : IGNORE_URI)
{
if (servletPath.contains(s))
{
flag = true;
break;
}
}
/** 拦截请求 */
if (!flag)
{
/** 1.获取session中的用户 */
User user = (User) request.getSession()
.getAttribute(HrmConstants.USER_SESSION);
/** 2.判断用户是否已经登录 */
if (user == null)
{
/** 如果用户没有登录,跳转到登录页面 */
request.setAttribute("message", "请先登录再访问网站!");
request.getRequestDispatcher(HrmConstants.LOGIN)
.forward(request, response);
return flag;
} else
{
flag = true;
}
}
return flag;
}
}

下面通过用例来介绍控制层的实现。