环境:jdk1.7 spring3.2.2 struts2.3.15 hibernate3.3.2 druid1.0.9.jar
上一篇我们讲解了ssh的整合。这一篇继续深入ssh整合之采用注解方式。
=====================StudentPageAction=====================
上一篇我们讲解了ssh的整合。这一篇继续深入ssh整合之采用注解方式。
下面来看工程的建立及相关代码
导入包
工程结构
========================web.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">
<error-page>
<error-code>404</error-code>
<location>/Err404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/Err500.html</location>
</error-page>
<!-- 解决延迟加载的问题start -->
<filter>
<filter-name>OpenSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInView</filter-name>
<url-pattern>*.php</url-pattern>
</filter-mapping>
<!-- 解决延迟加载的问题end -->
<!--struts2 config start -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>config</param-name>
<param-value>struts-default.xml,struts-plugin.xml,configs/struts.xml</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--struts2 config end -->
<!-- druid pool -->
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
<init-param>
<param-name>exclusions</param-name>
<param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
<!--http://localhost:8080/SSHFinal/druid/index.html -->
<!--spring config start -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:configs/context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- spring config end -->
<!-- 加载日志start -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:configs/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<!-- 加载日志end -->
<welcome-file-list>
<welcome-file>Login.jsp</welcome-file>
</welcome-file-list>
</web-app>
================druid连接池配置druid.properties==================
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/studentdb
username=root
password=sasa
#配置监控统计拦截的filters,去掉后监控界面sql无法统计
filters=stat
#配置初始化大小
initialSize=6
#配置初始化最大连接数
maxActive=20
#配置初始化最小连接数
minIdle=3
#配置获取连接等待超时的时间,1分钟
maxWait=60000
#检测连接是否有效的SQL
validationQuery=SELECT 'x'
#空闲的连接是否进行有效性检查
testWhileIdle=true
#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testOnBorrow=false
#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testOnReturn=false
#启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true
maxPoolPreparedStatementPerConnectionSize=20
#对于长时间不使用的连接强制关闭
removeAbandoned=true
#超过60秒的空闲连接就可以被关闭了,单位是秒
removeAbandonedTimeout=60
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis=10000
#配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis=30000
===============hibernate核心配置文件hibernate.cfg.xml========================
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="cache.provider_configuration_file_resource_path">
configs/ehcache.xml
</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>
</session-factory>
</hibernate-configuration>
===============spring核心配置文件context.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: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-3.0.xsd">
<!-- 启动注解的扫描支持 -->
<context:component-scan base-package="com.obtk.dao,com.obtk.biz">
</context:component-scan>
<!-- durid连接池配置start -->
<bean id="duridConfig" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:configs/druid.properties</value>
</list>
</property>
</bean>
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName" value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<property name="filters" value="${filters}" />
<property name="initialSize" value="${initialSize}" />
<property name="maxActive" value="${maxActive}" />
<property name="minIdle" value="${minIdle}" />
<property name="maxWait" value="${maxWait}" />
<property name="validationQuery" value="${validationQuery}" />
<property name="testWhileIdle" value="${testWhileIdle}" />
<property name="testOnBorrow" value="${testOnBorrow}" />
<property name="testOnReturn" value="${testOnReturn}" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="${maxPoolPreparedStatementPerConnectionSize}" />
<property name="removeAbandoned" value="${removeAbandoned}" />
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
<property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
<property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
</bean>
<!-- durid连接池配置end -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="druidDataSource"></property>
<property name="configLocation">
<value>classpath:configs/hibernate.cfg.xml</value>
</property>
<property name="mappingLocations">
<list>
<value>classpath:configs/mappers/*.hbm.xml</value>
</list>
</property>
</bean>
<!-- 事务配置start -->
<bean id="txManger" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:advice id="txAdvise" transaction-manager="txManger">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
<tx:method name="load*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="do*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="mycut" expression="execution(* com.obtk.biz.*.*(..))"/>
<aop:advisor advice-ref="txAdvise" pointcut-ref="mycut"/>
</aop:config>
<!-- 事务配置end -->
</beans>
====================struts核心配置文件struts.xml=====================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"struts-2.3.dtd">
<struts>
<constant name="struts.action.extension" value="php"></constant>
<constant name="struts.multipart.saveDir" value="C:\tmp"></constant>
<!-- 最大只能传1m上来 -->
<constant name="struts.multipart.maxSize" value="1048576"></constant>
<include file="configs/struts/struts-*.xml"></include>
</struts>
==============用户模块的struts配置struts-user.xml======================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"struts-2.3.dtd">
<struts>
<package name="user" extends="struts-default">
<action name="Login" class="com.obtk.actions.LoginAction">
<result name="success">index.jsp</result>
<result name="input">Login.jsp</result>
</action>
<action name="CheckUser" class="com.obtk.actions.CheckUserAction">
<result name="success" type="stream">
<param name="contentType">text/html</param>
<param name="inputName">bis</param>
</result>
</action>
<action name="Register" class="com.obtk.actions.RegisterAction">
<result name="success">Login.jsp</result>
<result name="input">Register.jsp</result>
</action>
</package>
</struts>
关键代码示例
因为继承HibernateDaoSupport无法应用注解自动装配,所有单独编写一个MyDaoSupport
package com.obtk.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class MyDaoSupport extends HibernateDaoSupport{
@Autowired
public void setMyFactory(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}
}
==================StudentDaoImpl==================
package com.obtk.dao;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import com.obtk.entitys.PageEntity;
import com.obtk.entitys.StudentEntity;
@Repository("stuDao")
public class StudentDaoImpl extends MyDaoSupport implements IStudentDao{
//继承了MyDaoSupport里面的自动装配
public StudentEntity loadOne(Integer stuId) {
HibernateTemplate template = this.getHibernateTemplate();
template.setCacheQueries(true);
StudentEntity stu = template.load(StudentEntity.class,stuId);
return stu;
}
@SuppressWarnings("unchecked")
public List<StudentEntity> queryByPage(final PageEntity thePage) {
List<StudentEntity> stuList=null;
HibernateTemplate template = this.getHibernateTemplate();
template.setCacheQueries(true);
String hql="from StudentEntity s inner join fetch s.dept d where 1=1";
final StringBuffer hqlBuffer=new StringBuffer(hql);
if(thePage.getStuName()!=null){
hqlBuffer.append(" and s.stuName like '%'"+thePage.getStuName()+"'%'");
}
if(thePage.getGender()!=null){
hqlBuffer.append(" and s.gender='"+thePage.getGender()+"'");
}
if(thePage.getDeptName()!=null){
hqlBuffer.append(" and d.deptName='"+thePage.getDeptName()+"'");
}
hqlBuffer.append(" order by s.age desc");
stuList=this.getHibernateTemplate().executeFind(
new HibernateCallback<Object>() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query qy=session.createQuery(hqlBuffer.toString());
//设置每页显示多少条
qy.setMaxResults(thePage.getPageSize());
//设置从那一条开始
qy.setFirstResult((thePage.getPageNo()-1)*thePage.getPageSize());
return qy.list();
}
}
);
return stuList;
}
public Integer countCnt(PageEntity thePage) {
Integer result=null;
HibernateTemplate template = this.getHibernateTemplate();
template.setCacheQueries(true);
String hql="select count(*) from StudentEntity s inner join s.dept d where 1=1";
final StringBuffer hqlBuffer=new StringBuffer(hql);
if(thePage.getStuName()!=null){
hqlBuffer.append(" and s.stuName like '%'"+thePage.getStuName()+"'%'");
}
if(thePage.getGender()!=null){
hqlBuffer.append(" and s.gender='"+thePage.getGender()+"'");
}
if(thePage.getDeptName()!=null){
hqlBuffer.append(" and d.deptName='"+thePage.getDeptName()+"'");
}
List theList=template.find(hqlBuffer.toString());
if(theList.size()!=0){
result=Integer.parseInt(theList.get(0)+"");
}
System.out.println("总条数:"+result);
return result;
}
}
===========================StudentBiz.java==========================
package com.obtk.biz;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import com.obtk.dao.IStudentDao;
import com.obtk.entitys.PageEntity;
import com.obtk.entitys.StudentEntity;
@Service("stuBiz")
public class StudentBiz {
private IStudentDao stuDao;
@Autowired
@Qualifier("stuDao") //表示根据名称自动装配
public void setStuDao(IStudentDao stuDao) {
this.stuDao = stuDao;
}
public StudentEntity loadOne(Integer stuId) {
return stuDao.loadOne(stuId);
}
public List<StudentEntity> queryByPage(final PageEntity thePage) {
return stuDao.queryByPage(thePage);
}
public Integer countCnt(PageEntity thePage) {
return stuDao.countCnt(thePage);
}
}
=====================StudentPageAction=====================
package com.obtk.actions;
import java.util.List;
import java.util.Map;
import com.obtk.biz.StudentBiz;
import com.obtk.entitys.PageEntity;
import com.obtk.entitys.StudentEntity;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class StudentPageAction extends ActionSupport{
private String stuName;
private String gender;
private String deptName;
private String pageNo;
private String pageSize;
private StudentBiz stuBiz;
public void setStuBiz(StudentBiz stuBiz) {
this.stuBiz = stuBiz;
}
public String execute() throws Exception {
PageEntity thePage=new PageEntity();
if(pageNo!=null){
int mYPageNo=Integer.parseInt(pageNo);
thePage.setPageNo(mYPageNo);
}
if(pageSize!=null){
int myPageSize=Integer.parseInt(pageSize);
thePage.setPageSize(myPageSize);
}
if(stuName!=null){
stuName=new String(stuName.getBytes("iso-8859-1"),"utf-8");
thePage.setStuName(stuName);
}
if(gender!=null){
gender=new String(gender.getBytes("iso-8859-1"),"utf-8");
thePage.setGender(gender);
}
if(deptName!=null){
deptName=new String(deptName.getBytes("iso-8859-1"),"utf-8");
thePage.setDeptName(deptName);
}
//第一次进来就是第一页数据
List<StudentEntity> stuList=stuBiz.queryByPage(thePage);
//总条数
int rows=stuBiz.countCnt(thePage);
int totalPages=0;
if(rows%thePage.getPageSize()==0){
totalPages=rows/thePage.getPageSize();
}else{
totalPages=rows/thePage.getPageSize()+1;
}
//因为要在页面上展示
thePage.setTotalPages(totalPages);
ActionContext ac=ActionContext.getContext();
Map request=(Map)ac.get("request");
if(stuList!=null){
//分页实体对象
request.put("thePage",thePage);
//尽量用request对象保存数据
request.put("stuList",stuList);
return this.SUCCESS;
}else{
return this.ERROR;
}
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getPageNo() {
return pageNo;
}
public void setPageNo(String pageNo) {
this.pageNo = pageNo;
}
public String getPageSize() {
return pageSize;
}
public void setPageSize(String pageSize) {
this.pageSize = pageSize;
}
}
============分页的页面ShowStudents.jsp===============================
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="com.obtk.entitys.*"%>
<c:set var="path" value="${pageContext.request.contextPath}"></c:set>
<c:set var="scheme" value="${pageContext.request.scheme}"></c:set>
<c:set var="serverName" value="${pageContext.request.serverName}"></c:set>
<c:set var="serverPort" value="${pageContext.request.serverPort}"></c:set>
<c:set var="basePath" value="${scheme}://${serverName}:${serverPort}${path}/"></c:set>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<!-- 设定参考路径 -->
<base href="${basePath }">
<title>第一个页面</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<script type="text/javascript">
function changePage(){
var sizeStrTag=document.getElementsByName("theSize")[0];
var sizeStr=sizeStrTag.value;
window.location="QueryStuPage.php?pageNo=1&pageSize="+sizeStr;
}
</script>
</head>
<body>
<h2>欢迎您:${sessionScope.userName} <a href="Quit.php">退出</a></h2>
<h2>显示学生的数据 </h2>
<form action="QueryStuPage.php" method="get">
<p><input type="text" name="stuName" value="${thePage.stuName}"/>
<input type="submit" value="搜索"/>
</p>
</form>
<c:if test="${not empty stuList}">
<table border="1px">
<tr><td>编号</td><td>名称</td><td>性别</td><td>年龄</td><td>地址</td><td>操作</td></tr>
<c:forEach items="${stuList}" var="stu">
<tr><td>${stu.stuId}</td><td>${stu.stuName}</td>
<td>${stu.gender}</td>
<td>${stu.age}</td><td>${stu.address}</td>
<td><a href="DeleteStu.php?stuId=${stu.stuId}">删除</a>
<a href="QueryOne.php?stuId=${stu.stuId}">修改</a></td></tr>
</c:forEach>
</table>
<!-- 如果当前不是第一页,就有上一页 -->
<c:set var="pre" value="1"></c:set>
<c:if test="${thePage.pageNo ne 1}">
<c:set var="pre" value="${thePage.pageNo*1 -1}"></c:set>
</c:if>
<!-- 如果当前不是最后一页,就有下一页 -->
<c:set var="next" value="${thePage.totalPages}"></c:set>
<c:if test="${thePage.pageNo ne thePage.totalPages}">
<c:set var="next" value="${thePage.pageNo*1+1}"></c:set>
</c:if>
<p>当前页码:${thePage.pageNo}/${thePage.totalPages}
<a href="QueryStuPage.php?pageNo=1&pageSize=${thePage.pageSize}&keyStr=${thePage.stuName}">首页</a>
<a href="QueryStuPage.php?pageNo=${thePage.totalPages}&pageSize=${thePage.pageSize}&keyStr=${thePage.stuName}">尾页</a>
<a href="QueryStuPage.php?pageNo=${pre}&pageSize=${thePage.pageSize}&keyStr=${thePage.stuName}">上一页</a>
<a href="QueryStuPage.php?pageNo=${next}&pageSize=${thePage.pageSize}&keyStr=${thePage.stuName}">下一页</a>
每页显示多少条<select name="theSize" οnchange="changePage();">
<option value="3"
<c:if test="${thePage.pageSize eq 3}">selected="selected"</c:if>
>3</option>
<option value="5"
<c:if test="${thePage.pageSize eq 5}">
selected="selected"
</c:if>
>5</option>
<option value="8"
<c:if test="${thePage.pageSize eq 8}">
selected="selected"
</c:if>
>8</option>
</select>
</p>
</c:if>
</body>
</html>