这里通过一个小的登录注册系统练习使用整套的S2SH框架,虽然整体架构不大,但也基本可以说明整个S2SH框架的组成部分和工作流程。
这里我会首先摆出整个系统的组成部分以及源码,然后大致浏览一下这个框架各个组成部分的工作流程,最后说一下我所遇到过的坑!
S2SH就是Struts2、Spring以及Hibernate三大框架的整合,具体的各个框架的工作原理自行搜索,这里只是一个简单的说明。
先看一下整个框架整合的源码的结构:
这是源码中使用到的action、model、service、dao的部分:
下面是用到的几个页面:
在整合使用S2SH框架时,必须使用到许多的jar包,jar包是非常重要的,在很多情况下都会出现jar的依赖不足的情况,所以,我先贴出maven中pom.xml的内容,方便jar包的下载。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!--aspect包的导入-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.5</version>
</dependency>
<!--spring包的导入 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!--hibernate包的导入-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.5.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.3.8.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--struts包的引入-->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.20.1</version>
</dependency>
<!--struts-spring包的引入-->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.16.3</version>
</dependency>
<!--struts2中的json插件-->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.3.16.3</version>
</dependency>
<!--struts2测试插件的引入-->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>2.3.20</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
接着,我们看一下数据库,这个数据库很简单,数据库名为test,就一张USERS表,表中的字段如下:
创建数据库表的SQL如下:
CREATE TABLE `USERS` (
`id` varchar(36) NOT NULL,
`user_name` varchar(50) NOT NULL,
`u_password` varchar(32) NOT NULL,
`u_email` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
然后,我们创建跟数据库对应的实体类,这里就为Hibernate做准备了,实体类Users如下:
package model;
import java.io.Serializable;
/**
* Created by zhuxinquan on 16-12-1.
*/
public class Users implements Serializable{
private static final long serialVersionUID = -4414249636229253339L;
private String id;
private String name;
private String password;
private String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Users{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
然后创建Hibernate映射文件User.hbm.xml如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.Users" table="USERS" >
<comment></comment>
<id name="id" type="string">
<column name="id" length="36" />
<generator class="assigned" />
</id>
<property name="name" type="string">
<column name="user_name" length="50" not-null="true">
<comment></comment>
</column>
</property>
<property name="password" type="string">
<column name="u_password" length="32">
<comment></comment>
</column>
</property>
<property name="email" type="string">
<column name="u_email" length="100">
<comment></comment>
</column>
</property>
</class>
</hibernate-mapping>
映射文件实现了持久化类和数据库表之间的映射,即对象和关系数据库之间的映射,方便了对数据库的操作。
接下来,是dao层和service层。
dao层的接口IUserDao如下:
package dao;
import model.Users;
import java.util.List;
/**
* Created by zhuxinquan on 16-12-1.
*/
public interface IUserDao {
void save(Users user) throws Exception;
List<Users> findAll() throws Exception;
Users getByName(String userName) throws Exception;
Users getByNameAndPwd(String userName, String userPwd) throws Exception;
}
dao层的实现UserDaoImpl如下:
package dao.impl;
import dao.IUserDao;
import model.Users;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;
import java.util.List;
import java.util.UUID;
public class UserDaoImpl extends HibernateDaoSupport implements IUserDao {
public void save(Users user) throws Exception {
System.out.println("UserDao Save()");
String uId = UUID.randomUUID().toString();
user.setId(uId);
System.out.println(user);
Session session = getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
session.save(user);
transaction.commit();
if(session.isOpen()){
session.close();
}
// HibernateTemplate hibernateTemplate = this.getHibernateTemplate();
// hibernateTemplate.save(user);
// hibernateTemplate.flush();
System.out.println("Save OK");
}
public List<Users> findAll() throws Exception {
String hql = "FROM Users";
// Session session = null;
// Users user = null;
// try {
// session = getSessionFactory().openSession();
// Transaction transaction = session.beginTransaction();
// user = session.find(hql);
// transaction.commit();
// } finally {
// session.close();
// }
System.out.println("UserDao findAll()");
///////////////////
List<Users> userList = null;
try{
userList = (List<Users>) this.getHibernateTemplate().find(hql);
}catch (Exception e){
e.printStackTrace();
}
// List<Users> userList = getHibernateTemplate().find(hql);
System.out.println(userList);
return userList;
}
public Users getByName(String userName) throws Exception {
String hql = "FROM Users WHERE name=?";
Session session = null;
Users user = null;
try {
session = getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
//数据库暂时为设置主键,存在多个用户名相同的情况,此处仅仅判断是否已被占用,返回一个即可证明已经占用
//user = (Users)session.createQuery(hql).setParameter(0, userName).list().get(0);
user = (Users)session.createQuery(hql).setParameter(0, userName).uniqueResult();
transaction.commit();
}catch (Exception e){
e.printStackTrace();
}finally {
session.close();
}
System.out.println("Check return User: " + user);
return user;
}
public Users getByNameAndPwd(String userName, String userPwd) throws Exception {
String hql = "FROM Users WHERE name=? AND password=?";
Session session = null;
Users user = null;
try {
session = getSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
user = (Users)session.createQuery(hql)
.setParameter(0, userName)
.setParameter(1, userPwd)
.uniqueResult();
transaction.commit();
System.out.println("getByNameAndPwd" + user);
} finally {
session.close();
}
return user;
}
}
上面的代码可以看到有好多注释的地方和打印输出的地方,注释的部分有的是由于Hibernate操作数据库的方式不同,需要非常注意的地方是Hibernate的版本问题,由于版本的不同会导致很多不可思议的错误,这里我使用的都是hibernate4.
下面是service层的一些操作,首先是service的接口IUserService:
package service;
import model.Users;
import java.util.List;
public interface IUserService {
void addUser(Users user) throws Exception;
Users getUserByNameAndPassword(String userName, String userPassword) throws Exception;
boolean isNameValid(String userName) throws Exception;
List<Users> findAll() throws Exception;
}
下面是IUserService接口的实现类UserServiceImpl:
package service.impl;
import dao.IUserDao;
import model.Users;
import service.IUserService;
import java.util.List;
public class UserServiceImpl implements IUserService {
private IUserDao userDao;
public void addUser(Users user) throws Exception {
if(user == null || user.getName() == null || user.getName().equals("")
|| user.getPassword() == null || user.getPassword().equals("")) {
return;
}
userDao.save(user);
}
public List<Users> findAll() throws Exception {
return userDao.findAll();
}
public Users getUserByNameAndPassword(String userName, String userPassword) throws Exception {
Users user = null;
if(userName == null || userName.trim().equals("")
|| userPassword == null || userPassword.trim().equals("")) {
return null;
}
user = userDao.getByNameAndPwd(userName, userPassword);
System.out.println("UserServiceImpl" + user);
return user;
}
public boolean isNameValid(String userName) throws Exception {
Users user = userDao.getByName(userName);
if(user == null) {
return true;
} else {
return false;
}
}
public void setUserDao(IUserDao userDao) {
this.userDao = userDao;
}
}
后面是我们需要进行请求处理的action的部分,这里使用到了注册、登录、用户列表、检查用户名是否可用以及错误跳转的请求源码如下:
CheckUser.java
package action;
import com.opensymphony.xwork2.ActionSupport;
import model.Users;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ServletRequestAware;
import service.IUserService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by zhuxinquan on 16-12-2.
*/
public class CheckUser extends ActionSupport implements ServletRequestAware {
Logger logger = Logger.getLogger(UserAction.class);
private IUserService userService;
protected HttpServletRequest servletRequest = null;
private String userName;
private String password;
private String email;
private Users user;
public Logger getLogger() {
return logger;
}
public String checkUser() throws Exception {
String userName = servletRequest.getParameter("userName");
boolean isNameValid = userService.isNameValid(userName);
HttpServletResponse response = ServletActionContext.getResponse();
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("text/html");
response.getWriter().write("{\"isNameValid\":" + isNameValid + "}");
return null;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
public IUserService getUserService() {
return userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Users getUser() {
return user;
}
public void setUser(Users user) {
this.user = user;
}
public void setServletRequest(HttpServletRequest httpServletRequest) {
}
}
InputAction.java
package action;
import com.opensymphony.xwork2.ActionSupport;
/**
* Created by zhuxinquan on 16-12-2.
*/
public class InputAction extends ActionSupport {
public String input() {
return INPUT;
}
}
ListAction.java
package action;
import com.opensymphony.xwork2.ActionSupport;
import model.Users;
import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import service.IUserService;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* Created by zhuxinquan on 16-12-2.
*/
public class ListAction extends ActionSupport implements ServletRequestAware {
Logger logger = Logger.getLogger(UserAction.class);
private IUserService userService;
protected HttpServletRequest servletRequest = null;
private String userName;
private String password;
private String email;
private Users user;
public Logger getLogger() {
return logger;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
public IUserService getUserService() {
return userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Users getUser() {
return user;
}
public void setUser(Users user) {
this.user = user;
}
public void setServletRequest(HttpServletRequest request) {
this.servletRequest = request;
}
public String list() throws Exception {
List<Users> userList = null;
try {
userList = userService.findAll();
} catch (RuntimeException e) {
logger.error(e);
}
servletRequest.setAttribute("userList", userList);
return "userlist";
}
}
LoginAction.java
package action;
import com.opensymphony.xwork2.ActionSupport;
import model.Users;
import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import service.IUserService;
import javax.servlet.http.HttpServletRequest;
/**
* Created by zhuxinquan on 16-12-2.
*/
public class LoginAction extends ActionSupport implements ServletRequestAware {
Logger logger = Logger.getLogger(UserAction.class);
private IUserService userService;
protected HttpServletRequest servletRequest = null;
private String userName;
private String password;
private String email;
private Users user;
public void setServletRequest(HttpServletRequest httpServletRequest) {
this.servletRequest=httpServletRequest;
}
public void addError(String errorKey) {
addActionError(getText(errorKey));
}
public String login() throws Exception {
Users user = null;
System.out.println("LoginAction:login");
user = userService.getUserByNameAndPassword(userName, password);
System.out.println("login" + user);
if(user == null) {
addError("errors.userNameOrPassword");
return INPUT;
}
setUser(user);
return SUCCESS;
}
public IUserService getUserService() {
return userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Users getUser() {
return user;
}
public void setUser(Users user) {
this.user = user;
}
}
RegisterAction.java
package action;
import com.opensymphony.xwork2.ActionSupport;
import model.Users;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ServletRequestAware;
import service.IUserService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by zhuxinquan on 16-12-2.
*/
public class RegistAction extends ActionSupport implements ServletRequestAware {
private String userName;
private String password;
private String email;
private Users user;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Users getUser() {
return user;
}
public void setUser(Users user) {
this.user = user;
}
private IUserService userService;
public IUserService getUserService() {
return userService;
}
public void setUserService(IUserService userService) {
this.userService = userService;
}
public String input() {
System.out.println("Registe Action Input:");
return INPUT;
}
public String checkUser() throws Exception {
System.out.println("checkUser()");
String userName = servletRequest.getParameter("userName");
boolean isNameValid = userService.isNameValid(userName);
HttpServletResponse response = ServletActionContext.getResponse();
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("text/html");
response.getWriter().write("{\"isNameValid\":" + isNameValid + "}");
System.out.println(isNameValid);
return null;
}
public String regist() throws Exception {
System.out.println("in register() action");
Users user = new Users();
user.setName(userName);
user.setPassword(password);
user.setEmail(email);
try {
userService.addUser(user);
} catch (RuntimeException e) {
servletRequest.setAttribute("fail", "failure, please re-regist!");
return INPUT;
}
setUser(user);
System.out.println("register action:" + user);
return SUCCESS;
}
protected HttpServletRequest servletRequest = null;
public void setServletRequest(HttpServletRequest httpServletRequest) {
this.servletRequest = httpServletRequest;
}
}
接下来是比较关键的配置文件的部分了,spring通过依赖注入的方式自动生成并注入Bean的实例。下面是web.xml的内容:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>S2SH Demo</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
在web.xml文件中定义了过滤器、监听器以及一些初始化的参数,接着就是applicationContext.xml的内容,这个是Spring最关键的内容了:
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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
default-autowire="byName" default-lazy-init="true">
<bean id="userDao" class="dao.impl.UserDaoImpl" />
<bean id="userService" class="service.impl.UserServiceImpl" />
<!--<bean id="userService" class="service.impl.UserServiceImpl" >-->
<!--<property name="userDao" ref="userDao"></property>-->
<!--</bean>-->
<!--<bean id="loginAction" class="action.UserAction" scope="prototype" >-->
<!--<property name="userService" ref="userService"></property>-->
<!--</bean>-->
<!--<bean id="userAction" class="action.UserAction" scope="prototype" >-->
<!--<property name="userService" ref="userService"></property>-->
<!--</bean>-->
<!--<bean id="registAction" class="action.UserAction" scope="prototype" >-->
<!--<property name="userService" ref="userService"></property>-->
<!--</bean>-->
<!--<bean id="loginAction" class="action.LoginAction" scope="prototype" />-->
<!--<bean id="userAction" class="action.UserAction" scope="prototype" />-->
<!--<bean id="registAction" class="action.RegistAction" scope="prototype" />-->
<!--数据源定义,使用DBCP连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="${datasource.maxActive}" />
<property name="maxIdle" value="${datasource.maxIdle}" />
<property name="maxWait" value="${datasource.maxWait}" />
<!--<property name="defaultAutoCommit" value="true" />-->
<!--<property name="removeAbandoned" value="true" />-->
<!--<property name="removeAbandonedTimeout" value="60" />-->
<!--<property name="validationQuery" value="select 1 " />-->
<!--<property name="testOnBorrow" value="true" />-->
</bean>
<!--Hibernate SessionFatory-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingDirectoryLocations">
<list>
<value>classpath:hbm</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</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="hibernate.cache.provider_class">
${hibernate.cache.provider_class}
</prop>
<prop key="hibernate.connection.release_mode">
${hibernate.connection.release_mode}
</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 属性文件读入 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:jdbc.properties</value>
<value>classpath*:hibernate.properties</value>
</list>
</property>
</bean>
<!-- 事务配置 -->
<aop:config proxy-target-class="true">
<aop:advisor
pointcut="execution(* service..*ServiceImpl.*(..))"
advice-ref="txAdvice-demo" />
</aop:config>
<tx:advice id="txAdvice-demo">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="is*" read-only="true" />
<!--<tx:method name="search*" read-only="true" />-->
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
最后是struts.xml的内容,在struts.xml文件中定义了如下的内容:
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.custom.i18n.resources" value="MessageResources"></constant>
<package name="demo" extends="struts-default" namespace="/">
<interceptors>
<interceptor-stack name="tokenStack">
<interceptor-ref name="token">
<param name="excludeMethods">input</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<!-- results made available to all actions -->
<global-results>
<result name="success">/pages/welcome.jsp</result>
</global-results>
<action name="input" method="input" class="action.InputAction">
<result name="input">/login.jsp</result>
</action>
<!--<action name="user" method="{1}" class="userAction">-->
<!--<result name="userlist">/pages/users.jsp</result>-->
<!--</action>-->
<action name="login" method="login" class="action.LoginAction">
<result name="input">/login.jsp</result>
<result name="userlist">/pages/users.jsp</result>
</action>
<action name="user!*" method="{1}" class="action.ListAction">
<result name="userlist">/pages/users.jsp</result>
</action>
<action name="regist!*" method="{1}" class="action.RegistAction">
<!--<interceptor-ref name="tokenStack"></interceptor-ref>-->
<!--<result name="invalid.token">/pages/regist.jsp</result>-->
<result name="input">/pages/regist.jsp</result>
</action>
</package>
</struts>
最后就是一些资源文件,包括hibernate.cfg.xml:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">××××××××××</property>
<property name="show_sql">true</property>
<mapping resource="hbm/Users.hbm.xml"/>
<!-- DB schema will be updated if needed -->
<!-- <property name="hbm2ddl.auto">update</property> -->
</session-factory>
</hibernate-configuration>
hibernate.properties:
############## mysql #######################
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.cache.use_query_cache=true
#hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.cache.provider_class=net.sf.ehcache.hibernate.EhCacheProvider
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate.connection.release_mode=on_close
############## ORACLE #######################
#hibernate.dialect=org.hibernate.dialect.OracleDialect
#hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
#hibernate.dialect=org.hibernate.dialect.OracleDialect
#hibernate.show_sql=true
#hibernate.cache.use_query_cache=true
#hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
#hibernate.connection.release_mode=on_close
jdbc.properties
########## DataSource MaxActive ##########
front.datasource.maxActive=200
datasource.maxActive=8
datasource.maxIdle=4
datasource.maxWait=1000
########### MYSQL ############
#jdbc.driverClassName=com.mysql.jdbc.ReplicationDriver
#jdbc.url=jdbc:mysql://172.20.88.207:3306,172.20.88.222:3306/?autoReconnect=true
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=**********
###### ORACLE #######
#jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
#jdbc.url=jdbc:oracle:thin:@localhost:1521:chinasei
#jdbc.username=scott
#jdbc.password=tiger
MessageResources.properties
#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net)
errors.email.format = Email is an invalid e-mail address
errors.email.required = Email is required
errors.password.required = Password is required
errors.userNameOrPassword = user name or password is error.
errors.username.required = Username is required
lable.text.email = email
lable.text.login = login
lable.text.ordinal = ordinal
lable.text.password = password
lable.text.regist = regist
lable.text.userName = user name
lable.text.userlist = all users
struts.messages.invalid.token = you are not allowed submit twice.
welcome.info = login success, welcome!
最后就是使用到的页面文件了:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<a href='<s:url value="/login.jsp"/>'>登录</a>
<a href='<s:url action="regist" method="input"/>'>注册</a>
<%--<a href='<s:url action="/regist" var="input"/>'>注册</a> --%>
<a href='<s:url action="user" method="list"/>'>用户列表</a>
主页定义了3个链接,分别是登录、注册以及用户列表
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>login</title>
</head>
<body>
<s:actionerror/>
<s:form method="POST" action="login">
<s:textfield name="userName" key="lable.text.userName"></s:textfield><br />
<s:password name="password" key="lable.text.password"></s:password><br />
<s:submit type="input" action="login" method="login" key="lable.text.login"/>
</s:form>
</body>
</html>
regist.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><s:text name="lable.text.regist"/></title>
<script type="text/javascript" src='<c:url value="/scripts/common/jquery.js" />' type="text/javascript"></script>
<script type="text/javascript">
function checkUserName() {
var userNameInput = document.getElementById("userName");
var userName = userNameInput.value;
if(jQuery.trim(userName) == "") {
document.getElementById("userNameSpan").innerHTML = "";
return false;
}
var isNameValid = true;
jQuery.ajax({
type: "POST",
url: '<s:url action="regist" method="checkUser" />',
data: "userName=" + userName,
dataType: "json",
cache: false,
async: false,
success: function (data, textStatus) {
isNameValid = data['isNameValid'];
if(isNameValid) {
document.getElementById("userNameSpan").innerHTML = "该用户名可以使用";
} else {
document.getElementById("userNameSpan").innerHTML = "该用户名已经被占用";
userNameInput.focus();
}
}
});
return isNameValid;
}
</script>
</head>
<body>
<s:actionerror/>
<s:form name="registForm" method="POST" action="regist!regist" validate="true">
<s:token />
<s:textfield name="userName" id="userName" key="lable.text.userName" onblur="checkUserName()"></s:textfield><span id="userNameSpan"></span><br />
<s:password name="password" key="lable.text.password"></s:password><br />
<s:textfield name="email" key="lable.text.email"></s:textfield>
<s:submit type="input" key="lable.text.regist"></s:submit>
</s:form>
</body>
</html>
users.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><s:text name="lable.text.userlist"></s:text></title>
</head>
<body>
<table border="1">
<tr>
<td><s:text name="lable.text.ordinal"/></td>
<td><s:text name="lable.text.userName"/></td>
<td><s:text name="lable.text.email"/></td>
</tr>
<s:iterator value="#request.userList" status="status">
<tr>
<td width="40"><s:property value="#status.index+1"></s:property></td>
<td width="80"><s:property value="name"></s:property></td>
<td width="150"><s:property value="email"></s:property></td>
</tr>
</s:iterator>
</table>
</body>
</html>
welcome.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><s:text name="welcome.info"/></title>
</head>
<body>
<h3><s:property value="user.name"></s:property><s:text name="welcome.info"/></h3>
<p><s:if test="user.email==null || user.email==''">您未注册邮箱。</s:if>
<s:else>您注册的邮箱是:<s:property value="user.email"></s:property></s:else></p>
</body>
</html>
所有的源码部分都完了,具体的可以在这里查看。
然后来说一下我所遇到的Bug!
1.jar包版本的问题
jar包的版本不同会导致遇到文件找不到的问题
2.IDEA jar包的导入方式
这个问题比较尴尬,如果通过maven的方式导入是不会出现这个问题的,如果是手动添加现有的jar包文件一定要直接导入,不要讲jar文件再次添加到其它的jar中,如下图:
就是左边的 + 号,而不是右边的 + 号
3.struts中请求处理的action使用的method,可能会如下填写:
<action name="user!*" method="{1}" class="action.ListAction">
<result name="userlist">/pages/users.jsp</result>
</action>
这样就可以根据不同的请求去调用不同的方法执行请求,写法如上,method={1},这里(【struts2】中method={1}详解)解释了这种写法。
所以在jsp文件中也必须如下填写action了(regist!regist):
<s:form name="registForm" method="POST" action="regist!regist" validate="true">
<s:token />
<s:textfield name="userName" id="userName" key="lable.text.userName" onblur="checkUserName()"></s:textfield><span id="userNameSpan"></span><br />
<s:password name="password" key="lable.text.password"></s:password><br />
<s:textfield name="email" key="lable.text.email"></s:textfield>
<s:submit type="input" key="lable.text.regist"></s:submit>
</s:form>
好了,来大致理一下工作流程,当容器启动加载的时候,Spring加载各个配置文件,注入依赖的Bean,当请求到来首先通过web.xml文件中配置的过滤器接受请求,转发交给struts进行处理,strust框架寻求合适的action进行响应,处理响应时,通过hibernate进行数据的操作,完成具体的操作,然后进行页面的响应显示。
大致就是这样,3个框架的整合,需要注意到很多的细节,这里没有过多的描述,具体的代码理解和框架分开使用差异不算太大,重要的是一定要有耐心,理清各个部分的思路~~~