web.xml 配置解析及引入 Spring 特性

WEB 容器加载应用时,首先是从 web.xml 开始解析项目结构。那么当然,如果我们要为项目加入 spring 特性,就首先需要在 web.xml 中加入 spring 的设定。Spring MVC 和 Spring 本身只是类库,和 jdk 环境一样,我们将这些类库添加到项目中后,只需要让项目知道怎么去用这些类库就可以了。
下面我们结合加入 Spring 功能的 WEB 应用,看一下 web.xml 中相关配置的作用。

  1. 环境参数
    节点定义一些环境参数全局变量。应用启动或运行时,可调用读取环境参数的方法试图取得所需的全局变量。例如 Spring 需要一个名字为 contextConfigLocation 的环境参数,我们在 web.xml 中设定其值。
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring-context.xml,classpath:spring-mybatis.xml</param-value>
 </context-param>

当然,也可以为自定义的类提供环境参数。
上面例子中 classpath 具体指的是 WEB-INF/classes 这个路径,一般地所有的配置文件都会放在这个路径下面。
2. 监听器 (Listener)
Listener 需实现 javax.servlet.ServletContextListener 接口。一些Listener 监听 WEB 服务器的动作,例如服务器启动 WEB 应用,application、session 与 request 的建立或销毁等,并做一些初始化工作;还有一些 Listener 可以监听 Session、context 和 request 的属性变化,包括 HttpSessionAttributeListener 等。Spring 需要监听应用的启动及关闭,当应用启动时根据配置文件加载 Bean;当应用关闭时则销毁 Bean。而这些 Bean 正是 Spring 工作的基础。

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

WEB 容器启动时会创建该监听器,该监听器使用前述全局变量 contextConfigLocation 来完成它的初始化工作。不过事实上,Spring 提供了 contextConfigLocation 默认值。如果没有配置 contextConfigLocation 的话,ContextLoaderListener 会自动读取 WEB-INF/classes/applicationContext.xml (如果存在)这个文件作为 spring 的默认配置文件进行初始化。如果相应文件不存在并且没有配置 contextConfigLocation 参数,WEB 容器就不能正常加载 spring,项目也不能使用 Spring 的功能。
Listener 还常常用来实现以下几个功能。
- 统计在线人数
- 防止单用户重复登录。用一个 map 保存已经登录了的用户的 ID 和登录信息,并将 map 保存在 WEB 应用的内置对象 application 中。用一个实现了 HttpSessionListener 的监听器来监听用户登录和退出,登录时首先检查 map 中是否已经有已登录的相同用户;退出时将相应用户的登录信息从 map 中移除。Spring Security 中通过监听器org.springframework.security.web.session.HttpSessionEventPublisher 提供了防止用户重复登录的功能。
3. 过滤器 (Filter)
Filter 需实现 javax.servlet.Filter 接口。WEB 容器在加载 Listener 之后加载 Filter。一般地,用户通过浏览器向服务器发送一个 HTTP 或者 HTTPS 请求,在 java web 应用的服务器端,会有一个 Servlet 程序对其进行响应,并返回内容。Filter 不用于处理客户端的请求,但它会按照设定的过滤范围,过滤出一些请求,并对其进行一些处理,然后再交由 Servlet 进行处理或返回给客户端。一个Filter 可负责过滤多个请求或响应;一个请求或响应也可被多个过滤器处理 (Filter Chain)。
Filter 可以执行的操作类型如下。
- 在 HttpServletRequest 到达 Servlet 之前,拦截客户的HttpServletRequest。根据需要检查 HttpServletRequest,也可以修改HttpServletRequest头和数据。
- 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。根据需要检查 HttpServletResponse,也可以修改 HttpServletResponse 头和数据。
以 Spring 编码客户端请求为例,配置一个 Filter 应当在 web.xml 中加入类似的内容。

<filter>
    <filter-name>encodingFilter</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>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

这个过滤器在请求到达 Servlet 前,使用 Spring 提供的 CharacterEncodingFilter 将 request 按照制定的方式进行编码,以防止客户端和服务器采用不同的编码格式导致 request 出现乱码。
除了字符编码,Filter 还常常实现以下功能。
- 用户权限验证,例如检查用户登录状态(session),检查用户权限等
- 日志记录
- 异常捕捉,在 Filter 进行 chain.doFilter(request, reponse) 请求中继过程中,加上 try…catch 语句块,就能捕捉到 Servlet 抛出的可预料或不可预料的异常,并进行处理
- 内容更改,例如敏感词过滤与替换,或者需要为每个 response 加上一个个人标签等
4. Servlet
Servlet 最终负责接收用户的 request,处理用户请求后又将 response 返回给用户。Servlet 实质上是运行在 WEB 容器里的 java 程序,当然 WEB 容器需要 jdk 的支持来运行 Java 程序。
开发人员可以直接编写 java 文件,也可以编写 jsp 文件作为 Servlet 响应用户请求,后者将由 WEB 容器负责将其转换为 java 文件并编译。当客户端需要将 html 格式代码给客户端时,直接在 java 里使用 response.getWriter() 得到输出流,然后在 reponse 中写入 html 代码,这样非常不方便,使用 jsp 则可以避免这种困难。
实际上,现在的 WEB 框架一般采用 MVC (Model, View, Controller) 三层结构管理 WEB 应用的 Servlet。Controller 由原生 java 实现,Model 对应 JavaBean,View 由 jsp 实现。Controller 匹配接收客户端请求,并调用后续的 Model 层操作(当然可能需要把请求参数转发给 Model),例如从数据库获取数据等。Model 层操作完成后,将数据交由 View 层,以便更新 View,完成后把最终视图呈现给用户。
使用 SpringMVC 需要在 web.xml 中引入如下的配置。

<servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>SpringMVC</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

可以看出,SpringMVC 实质上是一个 DispatcherServlet,它负责接收所有匹配 *.do 的客户端请求或转发请求。DispatcherServlet 接收到请求后,将转发给响应的 Controller 并按照既定的 MVC 处理逻辑进行处理。
Spring MVC 提供了拦截器 (Interceptor) 的功能。拦截器借助于 JAVA 反射机制实现,是面向切面编程 (AOP) 编程思想的一种体现。拦截器在 Spring 自身的文件里配置,和 Filter 类似,它拦截用户请求,并可以实现大部分 Filter 可以实现的功能。常见的用途有结合 Token 防止表单重复提交、权限检查、电子签名检查等。

通过以上配置,就在项目结构层面为 WEB 项目引入了 Spring Ioc 容器和 Spring MVC 功能(当然需要为项目引入相关 Spring 包)。但要使用 Spring 的功能,Spring 还需要一些配置文件(例如上文提到的 applicationContext.xml 和 spring-mvc.xml)来初始化它自身。关于 Spring 的配置文件,将在下一篇文章中继续研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值