说明:本次采用SpringMVC、Spring、Hibernate、Log4j、ehcache、C3P0、jackjson、mysql数据库
一、配置Spring
1.配置Spring容器组件扫描
2.配置数据源,使用C3P0
3.为hibernate配置SessionFactory
4.配置声明式事务
5.配置ehcache缓存
applicationContext.xml
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:cache="http://www.springframework.org/schema/cache"
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/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/cache
http://www.springframework.org/schema/cache/spring-cache-3.0.xsd">
<!-- Spring容器组件扫描 -->
<context:component-scan base-package="com.zxj.ssh">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- 引入外部资源文件 -->
<context:property-placeholder location="classpath:mysql.properties"
ignore-unresolvable="true" />
<!-- 数据源,来自于:com.mchange.v2.c3p0.ComboPooledDataSource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driverClassName}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${username}"></property>
<property name="password" value="${password}"></property>
<!-- 初始化连接数 -->
<property name="initialPoolSize" value="15"></property>
<!-- 设置连接池中最小与最大连接数 -->
<property name="minPoolSize" value="1"></property>
<property name="maxPoolSize" value="50"></property>
<!-- 当连接不够时,需要重新获取得连接数 -->
<property name="acquireIncrement" value="5"></property>
<!-- 连接池中允许存在最大的预编译对象 -->
<property name="maxStatements" value="200"></property>
<property name="maxIdleTime" value="200"></property><!-- 超时时间,单位:毫秒 -->
<property name="checkoutTimeout" value="2000"></property><!-- 多长时间回收一次超时连接 -->
<!-- 验证连接是否正常成功 -->
<property name="preferredTestQuery" value="SELECT COUNT(id) FROM t_tmp"></property>
</bean>
<!-- 为hibernate配置SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">
true
</prop>
<prop key="hibernate.format_sql">
true
</prop>
</props>
</property>
<!-- 扫描JAVABEAN组件的ORM映射关系 -->
<property name="packagesToScan">
<list>
<value>com.zxj.ssh.deptmag.beans</value>
<value>com.zxj.ssh.rolemag.beans</value>
<value>com.zxj.ssh.usermag.beans</value>
</list>
</property>
</bean>
<bean id="txManage"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 声明式事务管理:将事务管理声明在配置文件中,事务管理交由容器采用AOP面向切面编程的思想去管理我们的事务 -->
<!-- 定义通知 -->
<tx:advice id="txAdvice" transaction-manager="txManage">
<tx:attributes>
<!-- 定义一个全局的方法事务控制 -->
<tx:method name="*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="true" />
<!-- 新增方法 -->
<tx:method name="save*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="false" />
<tx:method name="add*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="false" />
<tx:method name="insert*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="false" />
<!-- 更新方法 -->
<tx:method name="update*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="false" />
<tx:method name="change*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="false" />
<tx:method name="modify*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="false" />
<!-- 删除方法 -->
<tx:method name="delete*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="false" />
<tx:method name="remove*" propagation="REQUIRED" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="false" />
<!-- 查询方法 -->
<tx:method name="find*" propagation="SUPPORTS" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="true" />
<tx:method name="query*" propagation="SUPPORTS" isolation="REPEATABLE_READ"
rollback-for="java.lang.Exception" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.zxj.ssh.*mag.service.impl.*.*(..))"
id="serviceMethods" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" />
</aop:config>
<!-- 配置ehCache缓存 -->
<cache:annotation-driven cache-manager="cacheManager" />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"></property>
</bean>
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"></property>
</bean>
</beans>
二、配置SpringMVC
springmvc-servlet.xml,放置于WebRoot/WEB-INF下
<?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:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- 开启MVC注解 -->
<mvc:annotation-driven conversion-service="tc" />
<!-- 指定静态资源包 -->
<mvc:resources location="/resource/" mapping="/resource/**" />
<!-- 制定扫描规则 -->
<!-- 开启自动扫描,并且只扫描WEB层的组件 -->
<context:component-scan base-package="com.zxj.ssh">
<!-- spring框架所提供的两大过滤器 -->
<!-- 除了有annotation,还有这么几个过滤器assignable(类名),regex,aspectj -->
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Service" />
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Repository" />
</context:component-scan>
<!-- 向spring容器注册,注册转换器 -->
<bean id="tc"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.zxj.ssh.converter.GlobalDateConverter"></bean>
</set>
</property>
</bean>
<!-- 如果需要使用jackjson,那么需要配置以下的数据转换器 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="converter" />
</list>
</property>
</bean>
<!-- 该转换器的作用:将HTTP消息体中信息向JSON转换 -->
<bean id="converter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
<!-- 视图解析器(ViewResolver) -->
<bean id="urlBasedViewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<!-- 如果你的页面中使用到了JSTL技术的话,那么需要指定JstlView这个类来解析 -->
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/"></property> <!-- //usermag/userlist.jsp -->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
三、配置Log4j
log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
<!-- 系统启动日志 -->
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<!-- %c发生在哪个类,%d发生的时间,%p日志的级别,%m输出的信息,%n换行 -->
<param name="ConversionPattern" value="%c %d{yyyy-MM-dd HH:mm:ss} --%p --%m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="STDOUT" />
<param name="levelMax" value="STDOUT" />
</filter>
</appender>
<appender name="DEBUG" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${ssh.root}/logs/ssh-debug.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="10240KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<!-- %c发生在哪个类,%d发生的时间,%p日志的级别,%m输出的信息,%n换行 -->
<param name="ConversionPattern" value="%c %d{yyyy-MM-dd HH:mm:ss} --%p --%m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="DEBUG" />
<param name="levelMax" value="DEBUG" />
</filter>
</appender>
<appender name="INFO" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${ssh.root}/logs/ssh-info.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="10240KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<!-- %c发生在哪个类,%d发生的时间,%p日志的级别,%m输出的信息,%n换行 -->
<param name="ConversionPattern" value="%c %d{yyyy-MM-dd HH:mm:ss} --%p --%m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="INFO" />
<param name="levelMax" value="INFO" />
</filter>
</appender>
<appender name="WARN" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${ssh.root}/logs/ssh-warn.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="10240KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<!-- %c发生在哪个类,%d发生的时间,%p日志的级别,%m输出的信息,%n换行 -->
<param name="ConversionPattern" value="%c %d{yyyy-MM-dd HH:mm:ss} --%p --%m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="WARN" />
<param name="levelMax" value="WARN" />
</filter>
</appender>
<appender name="ERROR" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="${ssh.root}/logs/ssh-error.log" />
<param name="Append" value="true" />
<param name="MaxFileSize" value="10240KB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<!-- %c发生在哪个类,%d发生的时间,%p日志的级别,%m输出的信息,%n换行 -->
<param name="ConversionPattern" value="%c %d{yyyy-MM-dd HH:mm:ss} --%p --%m%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="levelMin" value="ERROR" />
<param name="levelMax" value="ERROR" />
</filter>
</appender>
<root>
<priority value="INFO"></priority>
<appender-ref ref="STDOUT" />
<appender-ref ref="DEBUG" />
<appender-ref ref="INFO" />
<appender-ref ref="WARN" />
<appender-ref ref="ERROR" />
</root>
</log4j:configuration>
四、配置ehCache
ehcache.xml
<ehcache>
<!-- java.io.tmpdir 表示内存,可以更换为磁盘空间 -->
<diskStore path="d:/cache" /><!--如果内存中已经缓存不够时, 我们还可以指定磁盘缓存空间 path="d:/cache" -->
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="180" overflowToDisk="true"
memoryStoreEvictionPolicy="LFU" />
<!-- maxElementsInMemory="10000" 缓存中可放置的最大对象容量 -->
<!-- eternal="false" 设置缓存是否永久有效,默认:false -->
<!-- timeToIdleSeconds="120" 设置从来没有被使用过的缓存对象,在缓存空间中所能生存的时间,单位:秒 -->
<!-- timeToLiveSeconds="180" 设置被使用过的缓存对象,在缓存空间中所能生存的时间,单位:秒 -->
<!-- overflowToDisk="true" 当内存空间不足时,是否将数据写入到磁盘中 -->
<!-- memoryStoreEvictionPolicy="LFU" 当缓存空间不够用时,缓存清理内存有以下几个方式: FIFO first
in first out 先进先出 LFU less frequently Used 一直以来最少使用 LRU less recently Used
最近最少使用 -->
<cache name="users" maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="10" timeToLiveSeconds="25" overflowToDisk="true"
memoryStoreEvictionPolicy="LFU" />
</ehcache>
五、配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>ssh</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>ssh.root</param-value>
</context-param>
<!-- 启动spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 启动logj日志记录 -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.xml</param-value>
</context-param>
<!-- 日志刷新时间,单位是:毫秒 -->
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!-- 字符过滤器 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.zxj.ssh.filter.EncodingFilter</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>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- OpenSessionInViewFilter 主要是解决延迟加载中no session的问题 -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 安全过滤器:防止SQL注入 -->
<!-- 敏感字符过滤器 -->
<!-- 特殊字符过滤器 -->
<!-- 启动springmvc容器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
六、hibernate注解示例
package com.zxj.ssh.usermag.beans;
import java.io.Serializable;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name="t_user")
@Cacheable(value=true)
public class UserBean implements Serializable{
private static final long serialVersionUID = -9091157722228084808L;
@Id
@Column(name="id")
@GenericGenerator(name="iden",strategy="identity")
@GeneratedValue(generator="iden")
private Long id;
@Column(name="user_name",length=20)
private String userName;
@Column(name="login_name",length=20)
private String loginName;
@Column(name="pwd",length=32)
private String password;
@Column(name="sex")
private Integer sex;
public UserBean() {
super();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
@Override
public String toString() {
return "UserBean [id=" + id + ", userName=" + userName + ", loginName="
+ loginName + ", password=" + password + ", sex=" + sex + "]";
}
}
七、ehcache注解示例
package com.zxj.ssh.usermag.service.impl;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.zxj.ssh.usermag.beans.UserBean;
import com.zxj.ssh.usermag.dao.IUserDao;
import com.zxj.ssh.usermag.service.IUserService;
@Service
public class UserServiceImpl implements IUserService {
@Resource
private IUserDao userDaoImpl;
@CachePut(value = "users", key = "#loginName") // 二级缓存的对象设置用法
@Override
public UserBean queryUserByLoginName(String loginName) {
return userDaoImpl.queryUserByLoginName(loginName);
}
@Cacheable(value = "users", key = "0") // 查询缓存的用法,键默认写成key="0"
@Override
public List<UserBean> findUserListByUserName(String userName) {
return userDaoImpl.findUserListByUserName(userName);
}
@CacheEvict(value = "users", allEntries = true, beforeInvocation = true) // 二级缓存的对象清空用法
@Override
public void saveUserInfo(UserBean user) throws Exception {
userDaoImpl.saveUserInfo(user);
}
}