Spring 3 版本内容拾遗

WEB 配置

web.xml

<servlet>
        <servlet-name>viewDispatcher_1</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
                    <!--
                        不定义contextConfigLocation属性值,缺省为${servlet-name}-servlet.xml。
                        -->
            <param-value>/WEB-INF/config/webmvc-servlet.xml</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
</servlet>    
<servlet>
        <servlet-name>viewDispatcher_2</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/config/freemarker-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
        <servlet-name> viewDispatcher_1<serrvlet-name>
        <url-pattern>*.view1</url-pattern>
</servlet-mapping>
<servlet-mapping>
   <servlet-name> viewDispatcher_2<servlet-name>
    <url-pattern>*.view2</url-pattern>
</servlet-mapping>

 

补充:配置Web应用程序,让满足Mapping的请求使用定义的Servlet处理,可以配置多个DispathcerServlet来使用不同的配置文件,满足不同要求的处要求(比如当同时使用不兼容的视图<JSP and Freemarker>时)。

Spring配置:国际化配置

在配置文件中,添加内容:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
                p:basenames="WEB-INF/i18n/messages,WEB-INF/i18n/application"
                p:fallbackToSystemLocale="false" />
<!—或者-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
	<property name="basename" value="messages"/>
</bean>

在JSP视图中可以使用<spring:message code="message_name_key"/> 控制器、请求映射、返回

使用@Controller注解将bean定义为控制器,

使用@RequestMapping为bean或者方法定义请求的映射处理关系。

使用@PathVariable定义映射URI解析参数,

使用@ModelAttribute定义模型属性。

@Controller
@RequestMapping("/freemarker")
public class FreemarkerViewController {
@ModelAttribute
public 
	/*view name: prefix+return value+suffix*/
        @RequestMapping("/spftest/{id}")
        public String spftest(@PathVariable String id,Model model) {
                model.addAttribute("_id", id);
                return "spftest";
        }
	/*view name: prefix+@RequestMappinge+suffix*/
        @RequestMapping("/hello/{id}")
        public void hello(@PathVariable String id,Model model) {
                model.addAttribute("_id", id);
        }
	/*merge model and view return, view name:prefix+viewname+suffix*/
	@RequestMapping("view/{id}")
        public ModelAndView view(@PathVariable String id, Model model) {
                model.addAttribute("_id", id);
                ModelAndView mav = new ModelAndView();
                mav.setViewName("view");
                return mav;
        }
	/*return http response body,use with json formatter.*/
	@RequestMapping("/ajax/{name}/{age}")
	@ResponseBody
        public FormInfo ajax(@PathVariable("name") String name,
                        @PathVariable("age") Integer age,
                        @ModelAttribute("type") FormInfo info, Model model) {
                logger.info("@ajax:{},{},{}", new Object[] { info.getName(), info.getAge(),
                                info.getBirthday() });
                info.setName(name);
                info.setAge(age);
                return info;
        }
}

当@RequestMapping修饰的函数返回值为String字符串并且使用其他返回注解修饰,则生成的视图名规则:前缀+返回值+后缀。

当使用ModelAndView作为返回值类型时,生成的视图规则与String相同。

当@RequestMapping修饰的函数返回值为空时,则生成的视图名规则: 前缀+@RquestMappingvalue值+后缀。

当使用@ResponseBody修饰返回内容时,返回的内容一般使用Json格式转换,这样客户端可以是用JavaScript脚本直接处理。JSON的转换需要在mvc-servlet.xml文件中增加配置:

<bean id="mappingJacksonHttpMessageConverter" 
	class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
		<list>
                        <ref bean="mappingJacksonHttpMessageConverter" />
		</list>
        </property>
</bean>

定制数据属性编辑

最常见的是在将视图中表单提交的String类型值与Date类型值进行装换,在@Controller中用@InitBinder注解方法:

@InitBinder
public void initBinder(WebDataBinder binder) {
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	dateFormat.setLenient(false);
	binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}

 

视图
JSP&Tiles

如果需要使用Tiles 2装饰JSP作为Spring MVC视图,配置Spring MVC Configuration文件,增加内容:

<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
        id="tilesConfigurer">
        <property name="definitions">
                <list>
                        <value>/WEB-INF/layouts/layouts.xml</value>
                        <!-- Scan views directory for Tiles configurations -->
                        <value>/WEB-INF/views/**/views.xml</value>
                </list>
        </property>
</bean>
<bean id="tiewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
                value="org.springframework.web.servlet.view.tiles2.TilesView" />
</bean>


Tiles 2 的配置文件layoutx.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
        <definition name="public" template="/WEB-INF/layouts/default.jspx">
                <put-attribute name="header" value="/WEB-INF/views/jsp/common/header.jspx" />
                <put-attribute name="footer" value="/WEB-INF/views/jsp/common/footer.jspx" />
        </definition>
</tiles-definitions>


JSP文件default.jspx

<html xmlns:jsp="http://java.sun.com/JSP/Page"
        xmlns:c="http://java.sun.com/jsp/jstl/core"
        xmlns:tiles="http://tiles.apache.org/tags-tiles"
        xmlns:spring="http://www.springframework.org/tags">
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<jsp:directive.page pageEncoding="UTF-8" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body class="tundra spring">
        <div id="wrapper">
                <tiles:insertAttribute name="header" ignore="true" />
                <tiles:insertAttribute name="menu" ignore="true" />
                <div id="main">
                        <tiles:insertAttribute name="body" />
                        <tiles:insertAttribute name="footer" ignore="true" />
                </div>
        </div>
</body>
</html>


Freemarker

修改Spring MVC Configuration文件,增加以下内容:

<!-- Freemarker Configuration-->
<bean id="freemarkerConfig"
        class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/WEB-INF/views/ftl" />
        <property name="defaultEncoding" value="UTF-8"/><!—解决中文乱码@1-->
        <property name="freemarkerSettings">
                <props>                         
                        <prop key="number_format">#</prop><!-- 数字格式化-->
                </props>
        </property>
</bean>
<bean id="freeMarkerViewResolver"
        class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="cache" value="true" />
        <property name="prefix" value="" />
        <property name="suffix" value=".ftl" />
        <!—解决中文乱码@2-->
        <property name="contentType" value="text/html;charset=UTF-8" />         
</bean>


Spring提供了在freemarker模板文件中的标签支持,将spring-webmvc-xxx.jar文件的spring.ftl文件复制到freemarker configuration中定义的templateLoaderPath目录或子目录下。

在需要使用标签的文件中添加: <#import "/path/spring.ftl" as sp>

使用sitemesh模板技术,需要在WEB-INF/web.xml文件中配置:

<filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
</filter>
<filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>/*</url-pattern>
</filter-mapping>


缺省在sitemesh的装饰配置文件decorators.xml支持JSP模板定义,如果要使用freemarker定义模板,需要在WEB-INF/web.xml中添加配置:

<servlet>
        <servlet-name>FreemarkerDecorator</servlet-name>
        <servlet-class>com.opensymphony.module.sitemesh.freemarker.FreemarkerDecoratorServlet</servlet-class>
        <init-param>
                <param-name>TemplatePath</param-name>
                <param-value>/</param-value>
        </init-param>
        <init-param>
                <param-name>default_encoding</param-name>
                <param-value>UTF-8</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
        <servlet-name>FreemarkerDecorator</servlet-name>
        <url-pattern>*.ftl</url-pattern>
</servlet-mapping>


然后在decorators.xml文件定义:

<decorators defaultdir="/WEB-INF/_decorators/ftl">
    <decorator name="main" page="main.ftl">
          <pattern>/freemarker/*.view</pattern>
    </decorator>
</decorators>


就可以使用freemarker编写的模板文件main.ftl:

<html>
    <head>
    ${title}
    ${head}
    </head>
    <body>
    <#include "/WEB-INF/_decorators/ftl/header.ftl">    
        <div>
        ${base}|${title}<p/>   
        ${body}
        </div>  
        <#include "/WEB-INF/_decorators/ftl/footer.ftl">
        </body>
</html>


避免表单重复提交 使用redirect:前缀。 如表单的Action对应的方法:

@RequestMapping("/index/form")
public String form(@ModelAttribute("type") @Valid FormInfo info,
                BindingResult result) {
        if (result.hasErrors()) {
                return "index";
        } else {
                return "redirect:/tiles/form.view";
        }
}


多视图配置

1. 使用ResourceBundleViewResolver配置内容:

< bean id="r" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
	<property name="basename" value="views"/>
	<property name="order" value="0"/>
</bean>

<!-- 对于FreeMarker等还需要有额外的配置-->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer" 
          id="freemarkerConfig" p:templateLoaderPath="/WEB-INF/ftl/"/>

在views.properties中配置属性:[视图名].class、[视图名].url

helloj.class=org.springframework.web.servlet.view.JstlView
helloj.url=WEB-INF/jsp/helloj.jsp

hellof.class=org.springframework.web.servlet.view.freemarker.FreeMarkerView
hellof.contentType=text/html;charset=UTF-8
hellof.url=hellof.ftl


2. 视图链配置 当一个配置文件中定义多个ViewResolver的时候,使用

<property name="order" value="1">
</property>


value的数值越小,优先级越高。

正常情况下每个Controller的执行方法都应该返回一个ModelAndView,正如名称所显示的,ModelAndView是用来封装视图和显示数据集合的一个结果类。ViewResolver透过对ModelAndView的分析渲染视图,并动态填充视图中的数据内容。

注意:一般有特定要求的视图使用ResourceBundleViewResolver在属性文件中定义class和url。大部分其他视图使用视图链顺序配置解析,其中InternalResourceViewResolver、FreeMarkerViewResolver、VelocityViewResolver等无法返回null的ViewResolver,因为调用了RequestDispatcher方法,只能调用一次而且不能预先知道视图是否能成功渲染,必须放在视图链的最末端,否则其后的ViewResolver无法生效。

验证

可以使用实现JSR 303规范的的Hiberate Validator 4+版本与Spring集成使用,在需要约束的Bean中对属性添加约束注解@NotEmpty、@Size、@Length等。

public class FormInfo {
        @NotEmpty
        private String name;
        @Length(min = 2, max = 20)
        private String address;
        @Min(10)
        @Max(200)
        private Integer age;
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private Date birthday;
        //sets and gets
}


如果需要自定义validation messages,classpath目录中建立新的ValidationMessageslocal.properties,然后你将hibernate-validator-xxx.jar中的ValidationMessages.properties中的内容复制到这文件中修改。 在Spring MVC中的Controller中可以使用@Vaild注解对bean进行验证。

@InitBinder
public void initBinder(WebDataBinder binder) {
        binder.setValidator(validator);
}       
@RequestMapping("/form")
public String form(@ModelAttribute("type") @Valid FormInfo info){
        //do something
}


注解配置

需要使用XSD定义

<?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:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">   
</beans>


注解注入配置

<!-- 声明式事务管理,处理Hibernate、JPA、Ibatis DAO模型 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 注释配置 -->
<context:annotation-config />
<!-- 配置组件扫描的路径(包名) -->
<context:component-scan base-package="scan.package.name" />


Spring扩展注解

主要使用的注解 @Service @Compenent 注册为Context中的Bean,可以指定注入的名称。 @Autowired 自动注入依赖,一JNDI,二Type-match类型匹配。 @Qualfier 自动注入依赖的名称过滤

JSR-250注解 @Resource 注解被用来激活一个命名资源的依赖注入,在JavaEE应用程序中,该注解被典型地转换为绑定于JNDI context中的一个对象。 Spring支持使用@Resource通过JNDI lookup来解析对象,默认地,拥有与@Resource注解所提供名字相匹配的“bean name(bean名字)”的Spring管理对象会被注入。与spring扩展中的@Autowired、@Qualfier功能类似。 @PostConstruct 、@PreDestroy 注解分别用来触发Spring的初始化和销毁回调。 参考程序包:test.annotation.config

AOP配置:

注解定义

1. 编辑Spring配置文件,加入以下内容:

<!-- AOP配置 --> 
<aspectj-autoproxy/>

2. 定义Aop切面的方法。

3. 在需要使用Aop切面方法的类中定义注解。 参考程序包:test.annotation.aop

 

配置属性:

注解定义

1. 自定义Annotation满足注解注入的Bean可以使用属性文件中的配置内容。

<!-- 属性文件读取 -->
<bean id="loader"
        class="org.koala.spring.AnnotationBeanPostProcessor">
        <property name="locations">
                <list>
                        <value>classpath:jdbc.properties</value>
                </list>
        </property>
</bean>


其中jdbc.properties为提供的属性文件

2. 在配置文件中代替PropertyPlaceholderConfiguter就可以在类中使用如:

@Service  
public class PropertiesLoader implements Serializable {   
  
    @Properties(name="pic.address" )   
    private String picAddress;   
  
    @Properties(name="pic.url" )   
    private String picUrl;   
   
}


使用Annotation配置Spring MVC @Controller

作用于Class,定义Controller的名称,为Spring Bean的id值。

@RequestMapping

作用于Class和Method,定义URL映射的匹配的执行方法,可定义的属性值有

value,params,method。

@ResponeBody

返回响应内容体

@RequestParam

作用于执行方法的参数,用户提取请求中的参数值。

@ModelAttribute

作用与方法和参数,当作用于方法时为View提供的应用数据,与ModelAndView中的Map对应。当作用于参数时用于映射一个模型属性到特定注解的方法参数,这是控制器获得持有表单数据的对象引用的方法,在使用绑定这个参数的模型必须先绑定它,

@SessionAttibute 作用于Class,通常会列出模型属性的名称,这些属性被透明的保存在会话或者对话存储中,用于在后续的请求之间作为表单支持。

DemoContorller.java

@Controller("democontroller")
public class DemoContorller {
    @RequestMapping("/helloj.action")
    public ModelAndView helloj(@RequestParam(required = false, value = "id") String id) {
        ModelAndView mav = new ModelAndView("helloj");
        Map map = new HashMap();
        map.put("message", String.format("This is demo message!The id is [%s]", id));
        mav.addAllObjects(map);
        return mav;
    }
}


applcationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 

<context:annotation-config />    
<context:component-scan base-package="demo.scan.controller"/>
***
</beans>


表单、验证

依赖注入DI(控制反转) name id区别 bean定义中id为XML推荐的标识必须为有效字符,一个类型多个bean定义id,则其他id可以认为是别名。另外如果定义多个标识符,或者不符合XML合法id有效字符作为标识符可以使用name属性处理,name属性值可以用逗号、冒号、空格分割多个标识符。

延迟加载 <beans default-lazy-init="true" …>可以指定缺省延迟加载规则,也可以用<bean lazy-init="false" …>来指定单独bean的延迟加载策略。

自动装载 可以在使用default-autowire在beans指定全局的缺省自动加载的策略。也可以使用autowire对bean指定特定的加载策略。autowire会减少配置文件内容;autowire会自动与java源程序同步;autowire可能导致类型冲突;autowire对文档依赖生成是个难题。

作用域

<scoped-proxy proxy-target-class="false">
</scoped-proxy>

定义在session、request或者自定义的作用域内,当bean被注入到其他bean时,可以透过代理动态的获得真正的目标对象。当proxy-target-class="false"时使用JDK动态代理必须提供bean的接口定义,否则必须要引入CGLB包。

容器扩展 可以通过扩展BeanPostProcessor对bean提供自定义(或默认地来覆盖容器)的实例化逻辑、依赖解析逻辑,完成bean的实例化、配置和其它的初始化后执行一些自定义逻辑。

AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {
		"applicationContext-common.xml", "applicationContext-jdbc.xml" });
ctx.getBeanFactory().addBeanPostProcessor(new BeanPostProcessor() {
	public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
		System.out.printf("[-------after------][%s,%s]", o.toString(), s);
		return o;
	}

	public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
		System.out.printf("[-------before------][%s,%s]", o.toString(), s);
		return o;
	}
});


 

BeanFactoryPostProcessor可以对bean的定义(配置元数据)进行处理。允许其在容器实际实例化任何其它的bean之前读取配置元数据并可以修改它。

XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
// bring in some property values from a Properties file
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
// now actually do the replacement
cfg.postProcessBeanFactory(factory);


方法注入

一般当bean要引用另一个bean时,只要将被引用的bean定义为property就可以了,但是有一些情况是有区别的,比如两个bean的生命周期不同,构建实例规则不同。比如一个singleton bean引用prototype bean,则singleton bean只会在初始化的时候创建一个prototype bean并一直使用他,而prototype bean的多实例规则将失效。 这个时候有两种办法处理,一是放弃依赖注入,使用提供BeanFactoryAware实现的办法提供prototype bean的创建。

public class CommandManager implements BeanFactoryAware{
private BeanFactory beanFactory;
//覆盖方法
public void setBeanFactory(BeanFactory beanFactory){
    this.beanFactory=beanFactory;
}
//业务处理
public Object process(){
    T t=createT();
    return t.action();
}
//创建对象
public T createT(){
    return (T)this.beanFactory.getBean("t");
}
}


第二种方法:使用lookup方法注入bean。在被注入的bean中定义创建注入bean的抽象方法。

public abstract class CommandManager{
    //声明创建注入bean的抽象方法,容器会创建实现此方法的动态子类
public abstract T createT();
//业务处理
public Object process(){
    T t=createT();
    return t.action();
}
}
<bean id="t" class="x.xx.T" scope="prototype"/>
<bean id="commandManager" class="x.xx.CommandManager" scope="singleton">
        <lookup-method name="createT" bean="t"/>
</bean>


内建PropertyEditor的实现 Spring中提供了大量的内建PropertyEditor提供Object与String之间的转化。自定义PropertyEditor也非常容易。 定义bean类型; 继承PropertyEditorSurport定义bean类型的PropertyEditor; 注册PropertyEditor; 参考:test.propertyedit.、applicaitonContext-property.xml


                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值