`

Spring Web 相关工具类

阅读更多

Web 相关工具类

您几乎总是使用 Spring 框架开发 Web 的应用,Spring 为 Web 应用提供了很多有用的工具类,这些工具类可以给您的程序开发带来很多便利。在这节里,我们将逐一介绍这些工具类的使用方法。

操作 Servlet API 的工具类

当您在控制器、JSP 页面中想直接访问 Spring 容器时,您必须事先获取 WebApplicationContext 对象。Spring 容器在启动时将 WebApplicationContext 保存在 ServletContext的属性列表中,通过 WebApplicationContextUtils 工具类可以方便地获取 WebApplicationContext 对象。

WebApplicationContextUtils

当 Web 应用集成 Spring 容器后,代表 Spring 容器的 WebApplicationContext 对象将以 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE 为键存放在 ServletContext 属性列表中。您当然可以直接通过以下语句获取 WebApplicationContext:

WebApplicationContext wac = (WebApplicationContext)servletContext.
getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

 

但通过位于 org.springframework.web.context.support 包中的 WebApplicationContextUtils 工具类获取 WebApplicationContext 更方便:

WebApplicationContext wac =WebApplicationContextUtils.
getWebApplicationContext(servletContext);

 

当 ServletContext 属性列表中不存在 WebApplicationContext 时,getWebApplicationContext() 方法不会抛出异常,它简单地返回 null。如果后续代码直接访问返回的结果将引发一个 NullPointerException 异常,而 WebApplicationContextUtils 另一个 getRequiredWebApplicationContext(ServletContext sc) 方法要求 ServletContext 属性列表中一定要包含一个有效的 WebApplicationContext 对象,否则马上抛出一个 IllegalStateException 异常。我们推荐使用后者,因为它能提前发现错误的时间,强制开发者搭建好必备的基础设施。

WebUtils

位于 org.springframework.web.util 包中的 WebUtils 是一个非常好用的工具类,它对很多 Servlet API 提供了易用的代理方法,降低了访问 Servlet API 的复杂度,可以将其看成是常用 Servlet API 方法的门面类。

下面这些方法为访问 HttpServletRequest 和 HttpSession 中的对象和属性带来了方便:

方法 说明
Cookie getCookie(HttpServletRequest request, String name) 获取 HttpServletRequest 中特定名字的 Cookie 对象。如果您需要创建 Cookie, Spring 也提供了一个方便的 CookieGenerator 工具类;
Object getSessionAttribute(HttpServletRequest request, String name) 获取 HttpSession 特定属性名的对象,否则您必须通过request.getHttpSession.getAttribute(name) 完成相同的操作;
Object getRequiredSessionAttribute(HttpServletRequest request, String name) 和上一个方法类似,只不过强制要求 HttpSession 中拥有指定的属性,否则抛出异常;
String getSessionId(HttpServletRequest request) 获取 Session ID 的值;
void exposeRequestAttributes(ServletRequest request, Map attributes) 将 Map 元素添加到 ServletRequest 的属性列表中,当请求被导向(forward)到下一个处理程序时,这些请求属性就可以被访问到了;

此外,WebUtils还提供了一些和ServletContext相关的方便方法:

方法 说明
String getRealPath(ServletContext servletContext, String path) 获取相对路径对应文件系统的真实文件路径;
File getTempDir(ServletContext servletContext) 获取 ServletContex 对应的临时文件地址,它以 File 对象的形式返回。

下面的片断演示了使用 WebUtils 从 HttpSession 中获取属性对象的操作:

protected Object formBackingObject(HttpServletRequest request) throws Exception {
    UserSession userSession = (UserSession) WebUtils.getSessionAttribute(request, 
        "userSession");
    if (userSession != null) {
        return new AccountForm(this.petStore.getAccount(
        userSession.getAccount().getUsername()));
    } else {
        return new AccountForm();
    }
}

 

Spring 所提供的过滤器和监听器

Spring 为 Web 应用提供了几个过滤器和监听器,在适合的时间使用它们,可以解决一些常见的 Web 应用问题。

延迟加载过滤器

Hibernate 允许对关联对象、属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Session 范围之内进行。如果 Service 层返回一个启用了延迟加载功能的领域对象给 Web 层,当 Web 层访问到那些需要延迟加载的数据时,由于加载领域对象的 Hibernate Session 已经关闭,这些导致延迟加载数据的访问异常。

Spring 为此专门提供了一个 OpenSessionInViewFilter 过滤器,它的主要功能是使每个请求过程绑定一个 Hibernate Session,即使最初的事务已经完成了,也可以在 Web 层进行延迟加载的操作。

OpenSessionInViewFilter 过滤器将 Hibernate Session 绑定到请求线程中,它将自动被 Spring 的事务管理器探测到。所以 OpenSessionInViewFilter 适用于 Service 层使用HibernateTransactionManager 或 JtaTransactionManager 进行事务管理的环境,也可以用于非事务只读的数据操作中。

要启用这个过滤器,必须在 web.xml 中对此进行配置:

…
<filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>*.html</url-pattern>
</filter-mapping>
…


上面的配置,我们假设使用 .html 的后缀作为 Web 框架的 URL 匹配模式,如果您使用 Struts 等 Web 框架,可以将其改为对应的“*.do”模型。

中文乱码过滤器

在您通过表单向服务器提交数据时,一个经典的问题就是中文乱码问题。虽然我们所有的 JSP 文件和页面编码格式都采用 UTF-8,但这个问题还是会出现。解决的办法很简单,我们只需要在 web.xml 中配置一个 Spring 的编码转换过滤器就可以了:

<web-app>
<!---listener的配置-->
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>
        org.springframework.web.filter.CharacterEncodingFilter ① Spring 编辑过滤器
    </filter-class>
    <init-param> ② 编码方式
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param> ③ 强制进行编码转换
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
    </filter>
    <filter-mapping> ② 过滤器的匹配 URL
        <filter-name>encodingFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>

<!---servlet的配置-->
</web-app>

 

这样所有以 .html 为后缀的 URL 请求的数据都会被转码为 UTF-8 编码格式,表单中文乱码的问题就可以解决了。

请求跟踪日志过滤器

除了以上两个常用的过滤器外,还有两个在程序调试时可能会用到的请求日志跟踪过滤器,它们会将请求的一些重要信息记录到日志中,方便程序的调试。这两个日志过滤器只有在日志级别为 DEBUG 时才会起作用:

方法 说明
org.springframework.web.filter.ServletContextRequestLoggingFilter 该过滤器将请求的 URI 记录到 Common 日志中(如通过 Log4J 指定的日志文件);
org.springframework.web.filter.ServletContextRequestLoggingFilter 该过滤器将请求的 URI 记录到 ServletContext 日志中。

以下是日志过滤器记录的请求跟踪日志的片断:

(JspServlet.java:224) -     JspEngine --> /htmlTest.jsp
(JspServlet.java:225) - 	     ServletPath: /htmlTest.jsp
(JspServlet.java:226) - 	        PathInfo: null
(JspServlet.java:227) - 	        RealPath: D:\masterSpring\chapter23\webapp\htmlTest.jsp
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|

|-------- XML error:  The previous line is longer than the max of 90 characters ---------|

(JspServlet.java:228) - 	      RequestURI: /baobaotao/htmlTest.jsp
…

 

通过这个请求跟踪日志,程度调试者可以详细地查看到有哪些请求被调用,请求的参数是什么,请求是否正确返回等信息。虽然这两个请求跟踪日志过滤器一 般在程序调试时使用,但是即使程序部署不将其从 web.xml 中移除也不会有大碍,因为只要将日志级别设置为 DEBUG 以上级别,它们就不会输出请求跟踪日志信息了。

转存 Web 应用根目录监听器和 Log4J 监听器

Spring 在 org.springframework.web.util 包中提供了几个特殊用途的 Servlet 监听器,正确地使用它们可以完成一些特定需求的功能。比如某些第三方工具支持通过 ${key} 的方式引用系统参数(即可以通过 System.getProperty() 获取的属性),WebAppRootListener 可以将 Web 应用根目录添加到系统参数中,对应的属性名可以通过名为“webAppRootKey”的 Servlet 上下文参数指定,默认为“webapp.root”。下面是该监听器的具体的配置:


清单 6. WebAppRootListener 监听器配置

…
<context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>baobaotao.root</param-value> ① Web 应用根目录以该属性名添加到系统参数中
</context-param>
…
② 负责将 Web 应用根目录以 webAppRootKey 上下文参数指定的属性名添加到系统参数中
<listener>
    <listener-class> 
    org.springframework.web.util.WebAppRootListener
    </listener-class>
</listener>
…

 

这样,您就可以在程序中通过 System.getProperty("baobaotao.root") 获取 Web 应用的根目录了。不过更常见的使用场景是在第三方工具的配置文件中通过${baobaotao.root} 引用 Web 应用的根目录。比如以下的 log4j.properties 配置文件就通过 ${baobaotao.root} 设置了日志文件的地址:

log4j.rootLogger=INFO,R
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=${baobaotao.root}/WEB-INF/logs/log4j.log ① 指定日志文件的地址
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout.ConversionPattern=%d %5p [%t] (%F:%L) - %m%n

 

另一个专门用于 Log4J 的监听器是 Log4jConfigListener。一般情况下,您必须将 Log4J 日志配置文件以 log4j.properties 为文件名并保存在类路径下。Log4jConfigListener 允许您通过 log4jConfigLocation Servlet 上下文参数显式指定 Log4J 配置文件的地址,如下所示:

① 指定 Log4J 配置文件的地址
<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
…
② 使用该监听器初始化 Log4J 日志引擎
<listener>
    <listener-class>
    org.springframework.web.util.Log4jConfigListener
    </listener-class>
</listener>
…

 

提示

一些Web应用服务器(如 Tomcat)不会为不同的Web应用使用独立的系统参数,也就是说,应用服务器上所有的 Web 应用都共享同一个系统参数对象。这时,您必须通过webAppRootKey 上下文参数为不同Web应用指定不同的属性名:如第一个 Web 应用使用 webapp1.root 而第二个 Web 应用使用 webapp2.root 等,这样才不会发生后者覆盖前者的问题。此外,WebAppRootListener 和 Log4jConfigListener 都只能应用在 Web 应用部署后 WAR 文件会解包的 Web 应用服务器上。一些 Web 应用服务器不会将Web 应用的 WAR 文件解包,整个 Web 应用以一个 WAR 包的方式存在(如 Weblogic),此时因为无法指定对应文件系统的 Web 应用根目录,使用这两个监听器将会发生问题。

Log4jConfigListener 监听器包括了 WebAppRootListener 的功能,也就是说,Log4jConfigListener 会自动完成将 Web 应用根目录以 webAppRootKey 上下文参数指定的属性名添加到系统参数中,所以当您使用 Log4jConfigListener 后,就没有必须再使用 WebAppRootListener了。

Introspector 缓存清除监听器

Spring 还提供了一个名为 org.springframework.web.util.IntrospectorCleanupListener 的监听器。它主要负责处理由 JavaBean Introspector 功能而引起的缓存泄露。IntrospectorCleanupListener 监听器在 Web 应用关闭的时会负责清除 JavaBean Introspector 的缓存,在 web.xml 中注册这个监听器可以保证在 Web 应用关闭的时候释放与其相关的 ClassLoader 的缓存和类引用。如果您使用了 JavaBean Introspector 分析应用中的类,Introspector 缓存会保留这些类的引用,结果在应用关闭的时候,这些类以及Web 应用相关的 ClassLoader 不能被垃圾回收。不幸的是,清除 Introspector 的唯一方式是刷新整个缓存,这是因为没法准确判断哪些是属于本 Web 应用的引用对象,哪些是属于其它 Web 应用的引用对象。所以删除被缓存的 Introspection 会导致将整个 JVM 所有应用的 Introspection 都删掉。需要注意的是,Spring 托管的 Bean 不需要使用这个监听器,因为 Spring 的 Introspection 所使用的缓存在分析完一个类之后会马上从 javaBean Introspector 缓存中清除掉,并将缓存保存在应用程序特定的 ClassLoader 中,所以它们一般不会导致内存资源泄露。但是一些类库和框架往往会产生这个问题。例如 Struts 和 Quartz 的 Introspector 的内存泄漏会导致整个的 Web 应用的 ClassLoader 不能进行垃圾回收。在 Web 应用关闭之后,您还会看到此应用的所有静态类引用,这个错误当然不是由这个类自身引起的。解决这个问题的方法很简单,您仅需在 web.xml 中配置 IntrospectorCleanupListener 监听器就可以了:

<listener>
    <listener-class>
    org.springframework.web.util.IntrospectorCleanupListener
    </listener-class>
</listener>

小结

本文介绍了一些常用的 Spring 工具类,其中大部分 Spring 工具类不但可以在基于 Spring 的应用中使用,还可以在其它的应用中使用。使用 JDK 的文件操作类在访问类路径相关、Web 上下文相关的文件资源时,往往显得拖泥带水、拐弯抹角,Spring 的 Resource 实现类使这些工作变得轻松了许多。

在 Web 应用中,有时你希望直接访问 Spring 容器,获取容器中的 Bean,这时使用 WebApplicationContextUtils 工具类从 ServletContext 中获取 WebApplicationContext 是非常方便的。WebUtils 为访问 Servlet API 提供了一套便捷的代理方法,您可以通过 WebUtils 更好的访问 HttpSession 或 ServletContext 的信息。

Spring 提供了几个 Servlet 过滤器和监听器,其中 ServletContextRequestLoggingFilter 和 ServletContextRequestLoggingFilter 可以记录请求访问的跟踪日志,你可以在程序调试时使用它们获取请求调用的详细信息。WebAppRootListener 可以将 Web 应用的根目录以特定属性名添加到系统参数中,以便第三方工具类通过 ${key} 的方式进行访问。Log4jConfigListener 允许你指定 Log4J 日志配置文件的地址,且可以在配置文件中通过 ${key} 的方式引用 Web 应用根目录,如果你需要在 Web 应用相关的目录创建日志文件,使用 Log4jConfigListener 可以很容易地达到这一目标。

Web 应用的内存泄漏是最让开发者头疼的问题,虽然不正确的程序编写可能是这一问题的根源,也有可能是一些第三方框架的 JavaBean Introspector 缓存得不到清除而导致的,Spring 专门为解决这一问题配备了 IntrospectorCleanupListener 监听器,它只要简单在 web.xml 中声明该监听器就可以了。

分享到:
评论

相关推荐

    Spring文件资源操作和Web相关工具类盘点

    除了文件资源操作,Spring 还提供了丰富的 Web 相关工具类,帮助开发者更高效地处理 HTTP 请求、响应以及会话管理等问题。以下是一些常用的 Web 工具类: 1. **HttpEntity** 和 **ResponseEntity**: 这两个类用于...

    Spring获取ApplicationContext对象工具类的实现方法

    本文将详细介绍Spring中获取ApplicationContext对象的工具类实现方法。 在Spring中,典型的获取ApplicationContext对象的方式是使用ApplicationContext接口的一个实现类,如ClassPathXmlApplicationContext。这是一...

    spring-web-5.3.6 jar包.rar

    这个jar文件包含Web应用开发时,用到Spring框架时所需的核心类, 包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。 spring的核心类,提供了核心HTTP...

    Spring的优秀工具类盘点,第1部分:文件资源操作和Web相关工具类

    Spring不但提供了一个...第1部分将介绍与文件资源操作和Web相关的工具类。在第2部分中将介绍特殊字符转义和方法入参检测工具类。文件资源操作文件资源的操作是应用程序中常见的功能,如当上传一个文件后将其保存在特

    Spring Web Services 框架入门研究--发布服务

    标题 "Spring Web Services 框架入门研究--发布服务" 提到的是关于使用Spring框架构建Web服务的内容。Spring Web Services是Spring生态体系中的一部分,它专注于创建基于SOAP(Simple Object Access Protocol)的互...

    Spring Webscripts Reference Documentation

    - **调试工具**:Spring Webscripts提供了丰富的日志和调试工具,帮助开发者排查问题。 总之,Spring Webscripts是Spring框架中的一个重要组件,它简化了Web应用的开发,提高了代码的可维护性和可扩展性。通过深入...

    spring-webmvc-5.0.9 jar包、源码和javadoc

    在Spring Web MVC中,Controller是实现业务逻辑的关键组件,通常由实现了Controller接口或使用@Controller注解的类组成。它们接收请求,调用服务层方法处理业务,然后将结果封装到Model对象中。Model对象包含了用于...

    spring-web和spring-webmvc_4.2.4

    3. **HTTP上传文件**:`spring-web`包含处理文件上传的工具类和接口,使得开发者能够轻松处理用户通过表单上传的文件。 4. **Spring Boot Actuator**:在Spring Boot中,`spring-web`模块提供了Actuator的基础支持...

    org.springframework.web.jar

    在Java的Web开发领域,Spring框架是不可或缺的重要工具,其中`org.springframework.web.jar`文件是Spring框架的核心组成部分,主要用于处理Web应用程序的相关功能。这个JAR(Java Archive)文件包含了Spring Web模块...

    spring-web-3.1.1.RELEASE.jar.zip

    总结,Spring Web 3.1.1.RELEASE为开发者提供了强大而灵活的工具,以构建高效、可扩展的Web应用程序。无论是简单的HTTP请求处理,还是复杂的异步任务和WebSocket通信,都可以在Spring Web的框架下轻松实现。理解并...

    spring.web.jar.zip

    总的来说,`spring.web.jar`是Spring Web框架的核心库,它为Java Web开发者提供了强大的工具和API,使得构建高效、可维护的Web应用成为可能。掌握Spring Web框架的使用,不仅能提升开发效率,还能更好地适应现代Web...

    springweb框架需要jar包大全

    4. guava-18.0.jar:Google的Guava库,提供了大量用于集合、缓存、并发、I/O等方面的实用工具类和函数式编程支持,能极大地提升开发效率。 5. druid-1.0.9.jar:Druid是一个功能强大的数据库连接池,它提供了监控、...

    spring-webflow2.3.0源码

    通过对流程、状态、转换的抽象,以及异常处理和恢复机制的设计,Spring Webflow为开发者提供了高效、灵活的工具,使得构建复杂交互流程变得更加容易。通过Eclipse导入源码,不仅可以学习到其设计理念,还能加深对...

    spring.jar spring-webmvc-struts.jar spring-webmvc.jar

    标题中的"spring.jar"、"spring-webmvc-struts.jar"和"spring-webmvc.jar"都是Spring框架相关的Java库文件,通常以.jar结尾的文件是Java的归档文件,包含了类、资源和元数据,用于Java应用程序的运行。这些文件在...

    快速搭建一个简易的spring web工程

    在IT行业中,Spring框架是Java开发领域中广泛使用的开源框架,尤其在构建Web应用程序时。本文将基于"快速搭建一个简易的Spring Web工程"的主题,详细介绍如何从零开始创建一个基本的Spring MVC项目,以便你可以快速...

    spring web项目

    【Spring Web项目】是基于Java开发的Web应用程序,它整合了Spring框架的多个模块,如Spring MVC、Spring Core以及Spring AOP,旨在提供一个高效、灵活的开发环境。Spring MVC作为Spring框架的一部分,负责处理HTTP...

    Spring的web整合包

    最后,Spring4.3.7的Web整合包还包含了一些辅助工具和类,如HandlerExceptionResolver用于处理控制器抛出的异常,HttpMessageConverter用于处理HTTP消息的序列化和反序列化,以及ViewResolver用于解析视图名。...

    SpringBoot之自带工具类常用示例

    在Spring Boot框架中,开发人员可以利用其内置的工具类来简化常见的编程任务,提高开发效率。这些工具类涵盖了许多方面,包括日期时间处理、文件操作、字符串操作等。本篇将详细介绍Spring Boot中的一些常用工具类...

Global site tag (gtag.js) - Google Analytics