下载地址:
http://pan.baidu.com/s/1qWDinyk
一 开发环境
1、动态web工程
2、部分依赖
hibernate-release-4.1.0.Final.zip
hibernate-validator-4.2.0.Final.jar
spring-framework-3.1.1.RELEASE-with-docs.zip
proxool-0.9.1.jar
log4j 1.2.16
slf4j -1.6.1
mysql-connector-java-5.1.10.jar
hamcrest 1.3.0RC2
ehcache 2.4.3
、为了方便学习,暂没有使用maven构建工程
二 工程主要包括内容
1、springMVC + spring3.1.1 + hibernate4.1.0集成
2、通用DAO层 和 Service层
3、二级缓存 Ehcache
3.1:缓存了数据库查询
3.2:实现了页面缓存
ehcache-core-2.5.2.jar ehcache-web-2.0.4.jar 主要针对页面缓存
4、REST风格的表现层
REST功能是Spring MVC 3.0新增的,它通过不带扩展名的URL来访问系统资源。(http://www.cnblogs.com/crazylqy/p/4323520.html)
5、通用分页(两个版本)
5.1、首页 上一页,下一页 尾页 跳转
5.2、上一页 1 2 3 4 5 下一页
6、数据库连接池采用proxool
7、spring集成测试
8、表现层的 java validator框架验证(采用hibernate-validator-4.2.0实现)
9、视图采用JSP,并进行组件化分离
10、xss过滤器
11、使用gzip优化web应用(filter实现)
aaarticlea/png;base64,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" alt="" />http://www.cnblogs.com/crazylqy/p/4326299.html
三 TODO LIST 将本项目做成脚手架方便以后新项目查询
1、Service层进行AOP缓存(缓存使用Memcached实现)
2、单元测试(把常见的桩测试、伪实现、模拟对象演示一遍 区别集成测试)
3、监控功能
后台查询hibernate二级缓存 hit/miss率功能
后台查询当前服务器状态功能(如 线程信息、服务器相关信息)
4、spring RPC功能
5、spring集成 quartz 进行任务调度
6、spring集成 java mail进行邮件发送
7、DAO层将各种常用框架集成进来(方便查询)
8、把工作中经常用的东西 融合进去,作为脚手架,方便以后查询
四 集成重点及常见问题
1、spring-config.xml 配置文件:
1.1、该配置文件只加载除表现层之外的所有bean,因此需要如下配置:
<context:component-scan base-package="cn.javass">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
通过exclude-filter 把所有 @Controller注解的表现层控制器组件排除
1.2、国际化消息文件配置
<!-- 国际化的消息资源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<!-- 在web环境中一定要定位到classpath 否则默认到当前web应用下找 -->
<value>classpath:messages</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds" value="60"/>
</bean>
此处basenames内一定是 classpath:messages ,如果你写出“messages”,将会到你的web应用的根下找 即你的messages.properties一定在 web应用/messages.propertis。
1.3、hibernate的sessionFactory配置 需要使用org.springframework.orm.hibernate4.LocalSessionFactoryBean,其他都是类似的,具体看源代码。
1.4、<aop:aspectj-autoproxy expose-proxy="true"/> 实现@AspectJ注解的,默认使用AnnotationAwareAspectJAutoProxyCreator进行AOP代理,它是 BeanPostProcessor的子类,在容器启动时Bean初始化开始和结束时调用进行AOP代理的创建,因此只对当容器启动时有效,使用时注意此 处。
1.5、声明式容器管理事务
建议使用声明式容器管理事务,而不建议使用注解容器管理事务(虽然简单),但太分布式了,采用声明式容器管理事务一般只对service层进行处理。
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="merge*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="put*" propagation="REQUIRED" />
<tx:method name="use*" propagation="REQUIRED"/>
<!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到-->
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="count*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="list*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config expose-proxy="true">
<!-- 只对业务逻辑层实施事务 -->
<aop:pointcut id="txPointcut" expression="execution(* cn.javass..service..*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
此处一定注意 使用 hibernate4,在不使用OpenSessionInView模式时,在使用getCurrentSession()时会有如下问题:
当有一个方法list 传播行为为Supports,当在另一个方法getPage()(无事务)调用list方法时会抛出 org.hibernate.HibernateException: No Session found for current thread 异常。
这是因为getCurrentSession()在没有session的情况下不会自动创建一个,不知道这是不是Spring3.1实现的bug,欢迎大家讨论下。
因此最好的解决方案是使用REQUIRED的传播行为。
二、spring-servlet.xml:
2.1、表现层配置文件,只应加装表现层Bean,否则可能引起问题。
<!-- 开启controller注解支持 -->
<!-- 注:如果base-package=cn.javass 则注解事务不起作用-->
<context:component-scan base-package="cn.javass.demo.web.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
此处只应该加载表现层组件,如果此处还加载dao层或service层的bean会将之前容器加载的替换掉,而且此处不会进行AOP织入,所以会造成AOP失效问题(如事务不起作用),再回头看我们的1.4讨论的。
2.2、<mvc:view-controller path="/" view-name="forward:/index"/> 表示当访问主页时自动转发到index控制器。
2.3、静态资源映射
<!-- 当在web.xml 中 DispatcherServlet使用 <url-pattern>/</url-pattern> 映射时,能映射静态资源 -->
<mvc:default-servlet-handler/>
<!-- 静态资源映射 -->
<mvc:resources mapping="/images/**" location="/WEB-INF/images/" />
<mvc:resources mapping="/css/**" location="/WEB-INF/css/" />
<mvc:resources mapping="/js/**" location="/WEB-INF/js/" />
以上是配置文件部分,接下来来看具体代码。
三、通用DAO层Hibernate4实现
为了减少各模块实现的代码量,实际工作时都会有通用DAO层实现,以下是部分核心代码:
public abstract class BaseHibernateDao<M extends java.io.Serializable, PK extends java.io.Serializable> implements IBaseDao<M, PK> { protected static final Logger LOGGER = LoggerFactory.getLogger(BaseHibernateDao.class); private final Class<M> entityClass;
private final String HQL_LIST_ALL;
private final String HQL_COUNT_ALL;
private final String HQL_OPTIMIZE_PRE_LIST_ALL;
private final String HQL_OPTIMIZE_NEXT_LIST_ALL;
private String pkName = null; @SuppressWarnings("unchecked")
public BaseHibernateDao() {
this.entityClass = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Field[] fields = this.entityClass.getDeclaredFields();
for(Field f : fields) {
if(f.isAnnotationPresent(Id.class)) {
this.pkName = f.getName();
}
} Assert.notNull(pkName);
//TODO @Entity name not null
HQL_LIST_ALL = "from " + this.entityClass.getSimpleName() + " order by " + pkName + " desc";
HQL_OPTIMIZE_PRE_LIST_ALL = "from " + this.entityClass.getSimpleName() + " where " + pkName + " > ? order by " + pkName + " asc";
HQL_OPTIMIZE_NEXT_LIST_ALL = "from " + this.entityClass.getSimpleName() + " where " + pkName + " < ? order by " + pkName + " desc";
HQL_COUNT_ALL = " select count(*) from " + this.entityClass.getSimpleName();
} @Autowired
@Qualifier("sessionFactory")
private SessionFactory sessionFactory; public Session getSession() {
//事务必须是开启的,否则获取不到
return sessionFactory.getCurrentSession();
}
……
}
Spring3.1集成Hibernate4不再需要HibernateDaoSupport和HibernateTemplate了,直接使用原生API即可。
四、通用Service层代码 此处省略,看源代码,有了通用代码后CURD就不用再写了。
@Service("UserService")
public class UserServiceImpl extends BaseService<UserModel, Integer> implements UserService { private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); private UserDao userDao; @Autowired
@Qualifier("UserDao")
@Override
public void setBaseDao(IBaseDao<UserModel, Integer> userDao) {
this.baseDao = userDao;
this.userDao = (UserDao) userDao;
} @Override
public Page<UserModel> query(int pn, int pageSize, UserQueryModel command) {
return PageUtil.getPage(userDao.countQuery(command) ,pn, userDao.query(pn, pageSize, command), pageSize);
}
}
五、表现层 Controller实现
采用SpringMVC支持的REST风格实现,具体看代码,此处我们使用了java Validator框架 来进行 表现层数据验证
在Model实现上加验证注解
@Pattern(regexp = "[A-Za-z0-9]{5,20}", message = "{username.illegal}") //java validator验证(用户名字母数字组成,长度为5-10)
private String username; @NotEmpty(message = "{email.illegal}")
@Email(message = "{email.illegal}") //错误消息会自动到MessageSource中查找
private String email; @Pattern(regexp = "[A-Za-z0-9]{5,20}", message = "{password.illegal}")
private String password; @DateFormat( message="{register.date.error}")//自定义的验证器
private Date registerDate;
在Controller中相应方法的需要验证的参数上加@Valid即可
@RequestMapping(value = "/user/add", method = {RequestMethod.POST})
public String add(Model model, @ModelAttribute("command") @Valid UserModel command, BindingResult result)
六、Spring集成测试
使用Spring集成测试能很方便的进行Bean的测试,而且使用 @TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)能自动回滚事务,清理测试前后状态。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-config.xml"})
@Transactional
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
public class UserServiceTest { AtomicInteger counter = new AtomicInteger(); @Autowired
private UserService userService;
……
}
七、ehcache缓存
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="javass"> <diskStore path="d://ehcache"/> <!-- maxElementsInMemory :cache 中最多可以存放的元素的数量。如果放入cache中的元素超过这个数值,有两种情况:
1、若overflowToDisk的属性值为true,会将cache中多出的元素放入磁盘文件中。
2、若overflowToDisk的属性值为false,会根据memoryStoreEvictionPolicy的策略替换cache中原有的元素。 -->
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false">
</defaultCache> <cache name="cn.javass.demo.model.UserModel"
maxElementsInMemory="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false">
</cache> <!-- 设置默认的查询缓存区域 -->
<!-- 该配置应该写,否则会出现警告,若不写等于没有用查询缓存 -->
<cache
name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="5000"
eternal="false"
timeToLiveSeconds="3600"
overflowToDisk="false"/> <!-- 设置时间戳缓存区域 -->
<!-- 该配置应该写,否则会出现警告,若不写等于没有用查询缓存 -->
<cache
name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="true"/> <cache name="SimplePageCachingFilter"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="900"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LFU" /> </ehcache>
spring-config.xml配置
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
<prop key="net.sf.ehcache.configurationResourceName">${net.sf.ehcache.configurationResourceName}</prop>
<prop key="hibernate.cache.use_structured_entries">${hibernate.cache.use_structured_entries}</prop>
1.数据库缓存
1.1
<cache name="cn.javass.demo.model.UserModel"
maxElementsInMemory="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600"
overflowToDisk="false">
</cache> <!-- 设置默认的查询缓存区域 -->
<!-- 该配置应该写,否则会出现警告,若不写等于没有用查询缓存 -->
<cache
name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="5000"
eternal="false"
timeToLiveSeconds="3600"
overflowToDisk="false"/> <!-- 设置时间戳缓存区域 -->
<!-- 该配置应该写,否则会出现警告,若不写等于没有用查询缓存 -->
<cache
name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="true"/>
1.2
aaarticlea/png;base64,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" alt="" />
1.3
aaarticlea/png;base64,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" alt="" />
2.页面缓存
2.1
<cache name="SimplePageCachingFilter"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="900"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LFU" />
2.2
package cn.javass.common.web.filter; import java.util.Enumeration;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.constructs.blocking.LockTimeoutException;
import net.sf.ehcache.constructs.web.AlreadyCommittedException;
import net.sf.ehcache.constructs.web.AlreadyGzippedException;
import net.sf.ehcache.constructs.web.filter.FilterNonReentrantException;
import net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; public class PageEhCacheFilter extends SimplePageCachingFilter { private final static Logger log = Logger.getLogger(PageEhCacheFilter.class);
private final static String FILTER_URL_PATTERNS = "patterns";
private static String[] cacheURLs;
private void init() throws CacheException {
String patterns = filterConfig.getInitParameter(FILTER_URL_PATTERNS);
cacheURLs = StringUtils.split(patterns, ",");
} @Override
protected void doFilter(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain chain)
throws AlreadyGzippedException, AlreadyCommittedException,
FilterNonReentrantException, LockTimeoutException, Exception {
if (cacheURLs == null) {
init();
}
String url = request.getRequestURI();
boolean flag = false;
if (cacheURLs != null && cacheURLs.length > 0) {
for (String cacheURL : cacheURLs) {
if (url.contains(cacheURL.trim())) {
flag = true;
break;
}
}
} // 如果包含我们要缓存的url 就缓存该页面,否则执行正常的页面转向 if (flag) {
String query = request.getQueryString();
if (query != null) {
query = "?" + query;
}
log.info("当前请求被缓存:" + url + query);
super.doFilter(request, response, chain);
} else {
chain.doFilter(request, response);
}
} @SuppressWarnings("unchecked")
private boolean headerContains(final HttpServletRequest request,
final String header, final String value) {
logRequestHeaders(request);
final Enumeration accepted = request.getHeaders(header);
while (accepted.hasMoreElements()) {
final String headerValue = (String) accepted.nextElement();
if (headerValue.indexOf(value) != -1) {
return true;
}
}
return false;
} /**
*
* @see net.sf.ehcache.constructs.web.filter.Filter#acceptsGzipEncoding(javax.servlet.http.HttpServletRequest)
*
* <b>function:</b> 兼容ie6/7 gzip压缩
*
* @author hoojo
*
* @createDate 2012-7-4 上午11:07:11
*/ @Override
protected boolean acceptsGzipEncoding(HttpServletRequest request) {
boolean ie6 = headerContains(request, "User-Agent", "MSIE 6.0");
boolean ie7 = headerContains(request, "User-Agent", "MSIE 7.0");
return acceptsEncoding(request, "gzip") || ie6 || ie7; } }
2.3 web.xml
<!-- 缓存、使用页面缓存,gzip压缩核心过滤器 -->
<filter>
<filter-name>PageEhCacheFilter</filter-name>
<filter-class>cn.javass.common.web.filter.PageEhCacheFilter</filter-class>
<init-param>
<param-name>patterns</param-name>
<!-- 配置你需要缓存的url -->
<param-value>/pageCache.jsp,/pageCache </param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>PageEhCacheFilter</filter-name>
<url-pattern>/pageCache</url-pattern>
</filter-mapping>
2.4测试
package cn.javass.demo.web.controller; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; /**
* @author Zhangkaitao
* @version 1.0
*/
@Controller
public class pageCacheController { @RequestMapping(value = "/pageCache")
public String index(HttpServletRequest request){
return "pageCache";
} }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@page import="java.util.Date"%>
<%@ include file="inc/header.jsp"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>欢迎</title>
</head>
<body>
<p>使用new Date()来检测该页面是否被缓存</p>
<%=new Date()%>
</body>
</html>
访问两次该页面,检测时间没有发生变化,说明该url被缓存了
八、xss过滤器
使用XssRequestWrapper装饰器模式
页面缓存可参考:http://www.cnblogs.com/crazylqy/p/4325363.html
其他部分请直接看源码