web.xml
配置contextConfigLocation
在web.xml
中定义contextConfigLocation
参数,Spring
会使用这个参数去加载所有逗号分隔的xml
文件,如果没有这个参数,Spring
默认加载web-inf/applicationContext.xml
文件。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:conf/spring/applicationContext_core*.xml,
classpath*:conf/spring/applicationContext_dict*.xml,
classpath*:conf/spring/applicationContext_hibernate.xml,
</param-value>
</context-param>
也可以使用通配符来进行配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:conf/spring/applicationContext*.xml</param-value>
</context-param>
通配符 | 说明 |
---|---|
? | 匹配单个字符 |
* | 匹配除"/ "外任意字符 |
** | 匹配任意多个目录 |
举例如下:
classpath:app-Beans.xml
说明:无通配符,必须完全匹配。
classpath:App?-Beans.xml
说明:匹配一个字符,例如 App1-Beans.xml
、 App2-Beans.xml
。
classpath:user/*/Base-Beans.xml
说明:匹配零个或多个字符串(只针对名称,不匹配目录分隔符等),例如:user/a/Base-Beans.xml
、 user/b/Base-Beans.xml
,但是不匹配 user/Base-Beans.xml
。
classpath:user/**/Base-Beans.xml
说明:匹配路径中的零个或多个目录,例如:user/a/ab/abc/Base-Beans.xml
,同时也能匹配 user/Base-Beans.xml
。
classpath:**/*-Beans.xml
说明:表示在所有的类路径中查找和加载文件名以“-Beans.xml
”结尾的配置文件,但重复的文件名只加载其中一个,视加载顺序决定。
classpath*:user/**/*-Beans.xml
classpath*:**/*-Beans.xml
说明:“classpath*:
”表示加载多个资源文件,即使重名也会被加载,比如app1.jar
中有一个config-Beans.xml
,app2.jar
中也有一个config-Beans.xml
,这个时候,两个都会加载。classpath*:
可以用来从多个jar
文件中加载相同的文件,且可以用来加载其它(非当前)ClassLoader
的路径里文件。
注意Spring
中路径分割符为“/
”,而不能用“\\
” 。
配置编码过滤器
Spring
中的CharacterEncodingFilter
继承GenericFilterBean
和OncePerRequestFilter
,也就是说,这个过滤器就是针对于每次浏览器请求进行过滤的,然后再其之上添加了父类没有的功能即处理字符编码。
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<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>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
encoding
用来设置编码格式。forceEncoding
用来设置是否理会request.getCharacterEncoding()
方法,设置为true
则强制覆盖之前的编码格式。<url-pattern>
配置为“/*
”表示拦截客户端浏览器所有的请求。
当Servlet
容器启动的时候,会读取web.xml
中对于过滤器的配置信息, 读取到<init-param>
中的子标签<param-name>
encoding
和forceEncoding
所对应的<param-value>
的值,再通过调用该类setEncoding(String encoding)
和setForceEncoding(boolean forceEncoding)
将值注入到这两个字段中。
添加代理过滤器
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
所有的请求都会经过DelegatingFilterProxy
,从而实现权限的控制。
applicationContext.xml
引入参数配置文件
Spring 3
为我们提供了一种方案可以方便我们在一个阶段内不需要频繁写一个参数的值,而在不同阶段间又可以方便的切换参数的配置信息,就是 <content:property-placeholder>
元素 。
只需要在Spring
配置文件中添加一句:
<context:property-placeholder location="classpath:jdbc.properties"/>
这里的location
值为参数配置文件的位置,配置文件通常放到src
目录下。
参数配置文件
参数配置文件的格式即键值对的形式:
#jdbc配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root
行内“#
”号后面部分为注释。
配置数据源
这样一来就可以为Spring
配置的bean
的属性设置值了,比如Spring
有一个数据源的类:
<bean id="dataSource" class="org.springframework,jdbc,datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
配置事务管理器
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 配置DataSourceTransactionManager时需要依注入DataSource的引用 -->
<property name="dataSource" ref="dataSource"/>
</bean>
事务代理机制
使用 Annotation
方式:
<tx:annotation-driven transaction-manager="transactionManager"/>
可以在类级别或方法上使用 @Transaction
注入;
加注 @Transaction
的类或方法,本身并没有事务行为,能被识别为事务的,其实是 tx:annotation-driven
的配置开启了事务。
创建SqlSession
SqlSessionFactoryBean
有一个必须属性dataSource
,另外其还有一个通用属性configLocation
(用来指定mybatis
的xml
配置文件路径)。
<!-- 创建SqlSessionFactory,同时指定数据源-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 指定sqlMapConfig总配置文件,定制的environment在spring容器中不在生效-->
<property name="configLocation" value="classpath:sqlMapConfig.xml"/>
</bean>
注入SqlSessionTemplate
SqlSessionTemplate
是 MyBatis-Spring
的核心。 这个类负责管理 MyBatis
的 SqlSession
, 调用 MyBatis
的 SQL
方法, 翻译异常。
<!-- 在会话工厂中取出SqlSessionTemplate这个对象 -->
<bean id="sqlsessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
将数据映射接口转为Spring Bean
<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="basePackage" value="dao"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
MapperScannerConfigurer
将扫描basePackage
所指定的包下的所有接口类(包括子类),如果它们在SQL
映射文件中定义过,则将它们动态定义为一个Spring Bean
,这样,我们在Service
中就可以直接注入映射接口的bean
。
自动扫描
配置完这个标签后,Spring
就会去自动扫描base-package
对应的路径或者该路径的子包下面的java
文件,如果扫描到文件中带有@Service
,@Component
,@Repository
,@Controller
等这些注解的类,则把这些类注册为bean
。
<context:component-scan base-package="**.*.service"/>
<context:component-scan base-package="**.*.components"/>
配置AOP
<aop:config>
<!-- 表示在所有切入点加注事务管理 -->
<aop:pointcut expression="execution(* springlibs.service.*.*(..))" id="puintCutid" /> <!-- 需要配置 component-scan -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="puintCutid" />
</aop:config>
pointcut
表示的是一些连接点的集合,使用expression
来表达这种集合。advisor
这里就当做连接pointcut
切入点 与advice
通知 的作用。
expression
表达式 : execution(* springlibs.service.*.*(..))
:
- 第一个
*
: 表示所有的返回值类型 - 第二个
*
: 表示所有的类 - 第三个
*
: 表示所有的方法
切入点表达式例子:
execution(* springlibs.service.*.*(..))
表示springlibs.service
下所有的类跟所有的方法execution(* springlibs.service.*.save*(..))
表示springlibs.service
下所有的以save
开头的方法execution(public * springlibs.service.*.*(..))
表示springlibs.service
下所有的公共方法
线程池ThreadPoolTaskExecutor配置
<!-- spring thread pool executor -->
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<!-- 线程池维护线程的最少数量 -->
<property name="corePoolSize" value="5" />
<!-- 允许的空闲时间 -->
<property name="keepAliveSeconds" value="200" />
<!-- 线程池维护线程的最大数量 -->
<property name="maxPoolSize" value="10" />
<!-- 缓存队列 -->
<property name="queueCapacity" value="20" />
<!-- 对拒绝task的处理策略 -->
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
execute(Runable)
方法执行过程:
- 如果此时线程池中的数量小于
corePoolSize
,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。 - 如果此时线程池中的数量等于
corePoolSize
,但是缓冲队列workQueue
未满,那么任务被放入缓冲队列。 - 如果此时线程池中的数量大于
corePoolSize
,缓冲队列workQueue
满,并且线程池中的数量小于maxPoolSize
,建新的线程来处理被添加的任务。 - 如果此时线程池中的数量大于
corePoolSize
,缓冲队列workQueue
满,并且线程池中的数量等于maxPoolSize
,那么通过handler
所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize
、任务队列workQueue
、最大线程maximumPoolSize
,如果三者都满了,使用handler
处理被拒绝的任务。 - 当线程池中的线程数量大于
corePoolSize
时,如果某线程空闲时间超过keepAliveTime
,线程将被终止。这样,线程池可以动态的调整池中的线程数。
通过配置织入@Aspectj切面
通过aop
命名空间的<aop:aspectj-autoproxy />
声明自动为Spring
容器中那些配置@aspectJ
切面的bean
创建代理。
<aop:aspectj-autoproxy />
有一个proxy-target-class
属性,默认为false
,表示使用jdk
动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>
时,表示使用CGLib
动态代理技术织入增强。不过即使proxy-target-class
设置为false
,如果目标类没有声明接口,则Spring
将自动使用CGLib
动态代理。
servlet-Context.xml
将方法返回值注入为bean
通过MethodInvokingFactoryBean
类,可注入方法返回值。 MethodInvokingFactoryBean
用来获得某个方法的返回值,该方法既可以是静态方法,也可以是实例方法。该方法的返回值可以注入bean
实例属性,也可以直接定义成bean
实例。
<!--调用静态方法的返回值作为bean-->
<bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="java.lang.System"/>
<property name="targetMethod" value="getProperties"/>
</bean>
<!--调用实例方法的返回值作为bean-->
<bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="sysProps"/>
<property name="targetMethod" value="getProperty"/>
<property name="arguments" value="java.version"/>
</bean>
配置注解驱动
<mvc:annotation-driven />
会自动注册RequestMappingHandlerMapping
、RequestMappingHandlerAdapter
与ExceptionHandlerExceptionResolver
三个bean。
还将提供以下支持:
- 支持使用
ConversionService
实例对表单参数进行类型转换 - 支持使用
@NumberFormat
、@DateTimeFormat
- 注解完成数据类型的格式化
- 支持使用
@Valid
注解对JavaBean
实例进行JSR 303
验证 - 支持使用
@RequestBody
和@ResponseBody
注解
<mvc:annotation-driven message-codes-resolver ="bean ref" validator="" conversion-service="">
<mvc:return-value-handlers>
<bean></bean>
</mvc:return-value-handlers>
<mvc:argument-resolvers>
</mvc:argument-resolvers>
<mvc:message-converters>
</mvc:message-converters>[/color]
</mvc:annotation-driven>
- 当使用
<mvc:view-controller>
标签时一定要加入<mvc:annotation-driven />
,不然会使requestMapping
失效。 - 当为了处理静态资源问题而加入
<mvc:default-servlet-handler>
时,也一定要加入<mvc:annotation-driven />
,不然requestMapping
同样会失效。 - 当使用自定义类型转换器的时候需要加上
<mvc:annotation-driven />
标签。
静态资源访问
在进行Spring MVC
的配置时,通常我们会配置一个dispatcher servlet
用于处理对应的URL
。配置如下:
<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>/</url-pattern>
</servlet-mapping>
只拦截.do
请求配置如下:
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
这表示名字为 Spring MVC
的servlet
会处理一切的url
对应的请求,那么我们怎么让servlet
来处理项目中的静态资源呢?
采用Spring
自带<mvc:resources>
方法。
<mvc:annotation-driven />
<mvc:resources location="/img/" mapping="/img/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/css/" mapping="/css/**"/>
location
元素表示webapp
目录下的img
包下的所有文件mapping
元素表示以/img
开头的所有请求路径,如/img/a
或者/img/a/b
该配置的作用是:DispatcherServlet
不会拦截以/img
开头的所有请求路径,并当作静态资源交由Servlet
处理。
将访问url和视图进行映射
在Spring MVC
中使用<mvc:view-controller>
标签直接将访问url
和视图进行映射,而无需要通过控制器。
<!-- 如果当前路径是/testMvcViewController,则交给相应的视图解析器直接解析为视图 -->
<mvc:view-controller path="/testMvcViewController" view-name="success" />
<!-- 重定向,如果当前路径是/,则重定向到/index -->
<mvc:view-controller path="/" view-name="redirect:/index" />
如果没有<mvc:annotation-driven/>
,那么所有的@Controller
注解可能就没有解析,所以当有请求时候都没有匹配的处理请求类,就都去<mvc:default-servlet-handler/>
即default servlet
处理了,就会导致访问其他的页面失败。
整合freemarker
<!-- freemarker的配置 -->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl/" />
<property name="defaultEncoding" value="utf-8" />
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">10</prop>
<prop key="locale">zh_CN</prop>
<prop key="datetime_format">yyyy-MM-dd</prop><!-- 时间格式化 -->
<prop key="date_format">yyyy-MM-dd</prop>
<prop key="number_format">#.##</prop>
</props>
</property>
</bean>
<!-- 配置freeMarker视图解析器 -->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true" />
<property name="prefix" value="" /><!-- 上面已经配了,这里就不用配啦 -->
<property name="suffix" value=".ftl" />
<property name="contentType" value="text/html;charset=UTF-8" />
<property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
<property name="allowSessionOverride" value="true" />
<property name="allowRequestOverride" value="true" />
<property name="exposeSpringMacroHelpers" value="false" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="requestContextAttribute" value="request" />
</bean>
配置拦截器
<mvc:interceptors>
<!-- 日志拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/static/**" />
<bean class="拦截器java代码路径" />
</mvc:interceptor>
</mvc:interceptors>
mvc:mapping
:拦截器路径配置mvc:exclude-mapping
:拦截器不需要拦截的路径
通过配置织入@Aspectj切面
通过aop
命名空间的<aop:aspectj-autoproxy />
声明自动为Spring
容器中那些配置@aspectJ
切面的bean
创建代理。
<aop:aspectj-autoproxy />
有一个proxy-target-class
属性,默认为false
,表示使用jdk
动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>
时,表示使用CGLib
动态代理技术织入增强。不过即使proxy-target-class
设置为false
,如果目标类没有声明接口,则Spring
将自动使用CGLib
动态代理。
引入其他配置文件
<import resource="classpath*:/spring/job-timer.xml" />