spring in action 4 7.0 7 Advanced Spring MVC spring mvc高级应用

本章内容

This chapter covers
 Alternate Spring MVC configuration options
 Handling file uploads
 Handling exceptions in controllers
 Working with flash attributes

spring mvc的基本配置,如下示,在第5章第1节即5.1中

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class<?>[] { RootConfig.class };
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[] { WebConfig.class };
	}

}

需求:

You may need servlets and filters in addition to DispatcherServlet.
Maybe you need to do some additional configuration on DispatcherServlet itself.
For pre-Servlet 3.0 container, you may need to configure DispatcherServlet 
in a traditional web.xml file.

7.1.1 Customizing DispatcherServlet configuration

7.1.1 自定义DispatcherServlet配置

代码5.1(原文说的是代码7.1,那是错的.)中的三个方法,如下示,是在必须重写的三个抽象方法.

getServletMappings
getRootConfigClasses
getServletConfigClasses

除此之外还有其它可选的重写方法.如

customizeRegistration()

对象AbstractAnnotationConfigDispatcherServletInitializer在将DispatcherServlet注册到servlet容器之后(在此过程中还生成了ServletRegistration.Dynamic对象),会调用customizeRegistration()方法,把对象ServletRegistration.Dynamic传递给该方法.

对象ServletRegistration.Dynamic是AbstractAnnotationConfigDispatcherServletInitializer在将DispatcherServlet注册到servlet容器时生成的.通过重写customizeRegistration()方法可以将自定义的配置应用到DispatcherServlet中.

举例说明,如果要启用DispatcherServlet的multipart requests(类似上传文件这样的请求,可以参考http://blog.csdn.net/five3/article/details/7181521),那么需要重写customizeRegistration方法并在方法内设置MultipartConfigElement对象,如下示

@Override
protected void customizeRegistration(Dynamic registration) {
    registration.setMultipartConfig(
    new MultipartConfigElement("/tmp/spittr/uploads"));
}

这样放到5.1里就是这样的,注意引入的包别引错了.

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class<?>[] { RootConfig.class };
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[] { WebConfig.class };
	}

	@Override
	protected void customizeRegistration(Dynamic registration) {
	    registration.setMultipartConfig(
	    new MultipartConfigElement("/tmp/spittr/uploads"));
	}
}

在把ServletRegistration.Dynamic对象当参数传递给方法customizeRegistration()之后(其实就是重写customizeRegistration这个方法之后),就可以实现下面几个功能了

1. set the load-on-startup priority by calling setLoadOnStartup()

2. set an initialization parameter by calling setInitParameter()

3. call setMultipartConfig() to configure Servlet 3.0 multipart support

7.1.2 Adding additional servlets and filters

7.1.2 配置servlet和过滤器

实现对象AbstractAnnotationConfigDispatcherServletInitializer的时候就创建了DispatcherServlet和ContextLoaderListener.但是如果要注册别的servlets, filters, or listeners,如何操作?

使用java配置的一个好处就是定义的初始化类的数量可以如你所愿.因此,当需要注册组件时,只需要创建一个初始化类即可.最简单的方式 就是实现spring的WebApplicationInitializer接口.

下面的代码显示了如何通过实现WebApplicationInitializer接口来注册一个servlet

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.WebApplicationInitializer;

public class MyServletInitializer implements WebApplicationInitializer {
	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		Dynamic myServlet = servletContext.addServlet("myServlet", MyServlet.class);
		myServlet.addMapping("/custom/**");
	}
}

上面的代码是一个相对比较简单的servlet注册初始化类.该类注册了一个servlet然后将其与单个路径映射.其实DispatcherServlet也可以通过这样的方式来手动注册,但是真的没有必要,因为AbstractAnnotationConfigDispatcherServletInitializer已经替我们做了很多工作.

类似地,也可以通过创建一个WebApplicationInitializer实现来注册监听器或者过滤器,下面的代码显示了如何注册一个过滤器

@Override
public void onStartup(ServletContext servletContext)
throws ServletException {
javax.servlet.FilterRegistration.Dynamic filter =
servletContext.addFilter("myFilter", MyFilter.class);
filter.addMappingForUrlPatterns(null, false, "/custom/*");
}

在servlet3.0容器中,WebApplicationInitializer是一个通用的注册servlets, filters, and listeners的方式.但是如果只想要将注册的过滤器与DispatcherServlet建立映射,在AbstractAnnotationConfigDispatcherServletInitializer中有快捷方式.

要注册一个或者多个注册器,并将其与DispatchServlet映射起来,只需要重写getServletFilters() 方法即可.

@Override
protected Filter[] getServletFilters() {
return new Filter[] { new MyFilter() };
}

getServletFilters()这个方法在AbstractDispatcherServletInitializer中,而AbstractAnnotationConfigDispatcherServletInitializer又继承自AbstractDispatcherServletInitializer,所以就在实现AbstractAnnotationConfigDispatcherServletInitializer时候重写该方法即可.

import javax.servlet.Filter;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class<?>[] { RootConfig.class };
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return new Class<?>[] { WebConfig.class };
	}

	@Override
	protected void customizeRegistration(Dynamic registration) {
		registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads"));
	}

	@Override
	protected Filter[] getServletFilters() {
		return new Filter[] { new MyFilter() };
	}
}

观察方法Filter[] getServletFilters(),可见该方法返回的是一个javax.servlet.Filter数组,上面的示例中,只返回了一个过滤器,但实际上可以返回的过滤器数量如您所愿.这里没有必要明确声明将过滤器与DispatchServlet建立映射,由容器自动完成.

7.1.3 Declaring DispatcherServlet in web.xml

典型的创建DispatchServlet和ContextLoaderListener的xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

DispatchServlet和ContextLoaderListener会分别指定对应的应用上下文,上面的配置中,ContextLoaderListener指定了应用上下文,但是DispatchServlet没有,这样的话,默认使用的是应用名后接-context.xml的文件名的方式,该文件默认放在WEB-INF目录下.

下面指定了DispatchServlet应用上下文

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	<listener>
		<listener-class>
			org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
				/WEB-INF/spring/appServlet/servlet-context.xml
			</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
</web-app>

下面的配置表示DispatcherServlet和ContextLoaderListener使用AnnotationConfigWebApplicationContext,该对象实现了WebApplicationContext,它会加载java配置类而不会加载xml文件.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<context-param>
	<param-name>contextClass</param-name>
	<param-value>
		org.springframework.web.context.support.AnnotationConfigWebApplicationContext
	</param-value>
</context-param>
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>com.habuma.spitter.config.RootConfig</param-value>
</context-param>
<listener>
	<listener-class>
		org.springframework.web.context.ContextLoaderListener
	</listener-class>
</listener>
<servlet>
	<servlet-name>appServlet</servlet-name>
	<servlet-class>
		org.springframework.web.servlet.DispatcherServlet
	</servlet-class>
	<init-param>
		<param-name>contextClass</param-name>
		<param-value>
			org.springframework.web.context.support.AnnotationConfigWebApplicationContext
		</param-value>
	</init-param>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			com.habuma.spitter.config.WebConfigConfig
		</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>appServlet</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
时间: 2025-01-24 12:43:12

spring in action 4 7.0 7 Advanced Spring MVC spring mvc高级应用的相关文章

【Spring】【笔记】《Spring In Action》第4章 面向切面的Spring

前导: 在软件开发中,分布于应用中多处的功能称为:横切关注点(cross-cutting concerns). 横切关注点从概念上是与应用的业务逻辑相分离的,将横切关注点与业务逻辑相分离是面向切面编程AOP要解决的. 4.1 什么是面向切面编程 横切关注点可以被模块化为特殊的类,这些类被称为切面. 4.1.1 AOP术语 通知 Advice 切面的工作 被称为通知. 通知定义了切面是什么.何时使用. Spring切面可以应用5种类型的通知: Before:在方法被调用之前调用通知 After:在

spring in action 学习笔记十三:SpEL语言(Spring Expression Language)

SpEl语言的目的之一是防止注入外部属性的代码硬代码化.如@Value("#{student.name}")这个注解的意思是把Student类的name的属性值注入进去.其中student指向Student,是Student的id. SpEl的作用是: 1.The ability to reference beans by their IDs; 2.Invoking methods and accessing propeerties on objects 3.Mathmatical,r

Spring实战-Spring in Action, 4th Edition-2015年第4版本

In Action系列中最畅销的Spring图书,近十万读者学习Spring的共同选择!In Action系列中最畅销的Spring图书,有近10万读者选择本书来学习Spring! Spring框架已经成为Java开发人员的必备知识,而且Spring 3引入了强大的新特性,例如SpEL.Spring表达式语言.IoC容器的新注解以及用户急需的对REST的支持.无论你是刚刚接触Spring还是被Spring 3.0的新特性所吸引,本书都是掌握Spring的最佳选择. 下载地址: Spring in

spring in action 4 6.3使用Apache Tiles

配置Tiles视图解析器 需要一个TilesConfigurer bean,该bean用于定位和加载tile定义,还需要一个TilesViewResolver用于将逻辑视图名与tile定义映射起来.在WebConfig.java中 @Configuration @EnableWebMvc @ComponentScan(basePackageClasses={AutoScan.class}) public class WebConfig extends WebMvcConfigurerAdapte

spring in action 学习十一:property placeholder Xml方式实现避免注入外部属性硬代码化

这里用到了placeholder特有的一个语言或者将表达形式:${},spring in action 描述如下: In spring wiring ,placeholder values are property names wrapped with ${...},as an exampl,you can resolve the constructor arguments for a BlankDisc in xml like this : <bean id="sgtPeppers&qu

spring in action学习笔记一:DI(Dependency Injection)依赖注入之CI(Constructor Injection)构造器注入

一:这里先说一下DI(Dependency Injection)依赖注入有种表现形式:一种是CI(Constructor Injection)构造方法注入,另一种是SI(Set Injection) set 注入.这篇随笔讲的是第一种构造方法注入(Constructor Injection). 其实DI(Dependency Injection)依赖注入你不妨反过来读:注入依赖也就是把"依赖"注入到一个对象中去.那么何为"依赖"呢?依赖就是讲一个对象初始化或者将实例

spring in action学习笔记十五:配置DispatcherServlet和ContextLoaderListener的几种方式。

在spring in action中论述了:DispatcherServlet和ContextLoaderListener的关系,简言之就是DispatcherServlet是用于加载web层的组件的上下文.ContextLoadListener是加载 其他组件的上下文. 第一种方式:纯注解的方式: 在spring4.0版本以上,倾向用注解的方式配置DispatcherServlet和ContextLoaderListener.配置方式如下: 思路:一个类只要继承AbstractAnnotati

code From Spring In Action

1.典型的Spring配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sp

Spring In Action 4 学习笔记(一)Spring概览

Spring的核心概念就是DI和AOP,是Spring实现所有复杂华丽框架的基石. 相对于EJB等重型框架,Spring更加轻量化,可以强化普通的POJO对象. 1.简化JAVA开发 为了尽可能简化Java的开发,Spring遵循如下4个策略: Lightweight and minimally invasive development with POJOs 使用POJO类进行轻量化低侵入式的开发 Loose coupling through DI and interface orientati