闲来无事,收集了各种SSI整合资料之后,比葫芦画瓢终于画出来一个。备份于此,以免遗忘。
一,准备工作
数据库建立
/*
SQLyog Enterprise - MySQL GUI
Host - 5.5.21
*********************************************************************
Server version : 5.5.21
*/
/*!40101 SET NAMES utf8 */;
CREATE TABLE `afl_user` (
`id` tinyint(4) NOT NULL AUTO_INCREMENT,
`username` char(20) NOT NULL,
`password` char(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
JAR包请自行下载需要的。
二,整体环境
JDK:1.6
struts:2.2.3
spring:3.0.5
ibatis:2.3.4
Tomcat:7.0
Eclipse Java EE IDE for Web Developers.
Version: Indigo Service Release 1
Build id: 20110916-0149
源码目录结构
三,实现细节
1,ACTION代码
BaseDTO.java 目前为空,方便以后
package com.afl.system.struts2.action.dto;
public class BaseDTO {
}
BaseAction.java
/**
* 所有Action的基类,
* 继承自BaseAction的action都可以直接使用HttpServletRequest,HttpServletResponse和Session
*/
package com.afl.system.struts2.action;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.util.ServletContextAware;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.afl.system.struts2.action.dto.BaseDTO;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
* @author
*
*/
public class BaseAction<DTO extends BaseDTO> extends ActionSupport implements SessionAware,
ServletRequestAware, ServletResponseAware, ServletContextAware, ModelDriven<DTO> {
private static final long serialVersionUID = 1L;
protected Map<String, Object> session;
protected HttpServletRequest request;
protected HttpServletResponse response;
protected ServletContext context;
protected DTO dto;
/*
* (non-Javadoc)
*
* @see org.apache.struts2.util.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context) {
this.context = context;
}
/*
* (non-Javadoc)
*
* @see org.apache.struts2.interceptor.ServletResponseAware#setServletResponse(javax.servlet.http.HttpServletResponse)
*/
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
/*
* (non-Javadoc)
*
* @see org.apache.struts2.interceptor.ServletRequestAware#setServletRequest(javax.servlet.http.HttpServletRequest)
*/
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
/*
* (non-Javadoc)
*
* @see org.apache.struts2.interceptor.SessionAware#setSession(java.util.Map)
*/
public void setSession(Map<String, Object> session) {
this.session = session;
}
@Override
public DTO getModel() {
return dto;
}
//<!-- 这个就是获得设备上下文的方法,和struts1一样吧^-^ -->
public ApplicationContext getApplicationContext() {
return WebApplicationContextUtils.getWebApplicationContext(context);
}
//<!-- 作了个处理,以后需要调用spring的bean,直接调用此方法就可以了 -->
public Object getObject(String beanName) {
return getApplicationContext().getBean(beanName);
}
}
UserDTO.java
package com.afl.register.action.dto;
import com.afl.system.struts2.action.dto.BaseDTO;
public class UserDTO extends BaseDTO {
private String username;
private String password;
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;
}
}
RegisterAction.java
package com.afl.register.action;
import com.afl.register.action.dto.UserDTO;
import com.afl.register.service.IRegisterService;
import com.afl.system.struts2.action.BaseAction;
public class RegisterAction extends BaseAction<UserDTO> {
private static final long serialVersionUID = 1L;
private IRegisterService registerService;
public RegisterAction(){
dto = new UserDTO();
}
public String addUser(){
registerService.addUser(dto.getUsername(), dto.getPassword());
return "success";
}
public IRegisterService getRegisterService() {
return registerService;
}
public void setRegisterService(IRegisterService registerService) {
this.registerService = registerService;
}
}
2,service代码
IRegisterService.java
package com.afl.register.service;
public interface IRegisterService {
public void addUser(String username, String password);
}
RegisterServiceImpl.java
package com.afl.register.service.impl;
import com.afl.register.service.IRegisterService;
import com.afl.register.service.dao.IRegisterDAO;
import com.afl.system.entity.User;
public class RegisterServiceImpl implements IRegisterService {
private IRegisterDAO registerDAO;
@Override
public void addUser(String username, String password) {
User user = new User(username, password);
registerDAO.addUser(user);
}
public IRegisterDAO getRegisterDAO() {
return registerDAO;
}
public void setRegisterDAO(IRegisterDAO registerDAO) {
this.registerDAO = registerDAO;
}
}
IRegisterDAO.java
package com.afl.register.service.dao;
import com.afl.system.entity.User;
public interface IRegisterDAO {
public void addUser(User user);
}
RegisterDAOImpl.java
package com.afl.register.service.dao.impl;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import com.afl.register.service.dao.IRegisterDAO;
import com.afl.system.entity.User;
public class RegisterDAOImpl extends SqlMapClientDaoSupport implements IRegisterDAO {
@Override
public void addUser(User user) {
getSqlMapClientTemplate().insert("insertUser", user);
}
}
3,entity及配置文件
User.java
package com.afl.system.entity;
public class User {
// 主键 id
private Long id;
// 用户名
private String username;
// 密码
private String password;
public User(){
}
public User(String username, String password){
this.username = username;
this.password = password;
}
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
User.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>
<typeAlias alias="User" type="com.afl.system.entity.User" />
<!-- 保存注册信息 -->
<insert id="insertUser" parameterClass="User">
insert into
AFL_User(username,password)values(#username#,#password#)
</insert>
</sqlMap>
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- 这是一个重要的地方,很多人在使用<s:include>子页面后,发现子页面乱码,怎么改都不行,原因就在次,struts2的默认编码为UTF-8,乱码的同志请看看你的jsp页面上的编码是不是和这个不一致呢。只要把这里和jsp编码改一致就行了 -->
<constant name="struts.i18n.encoding" value="UTF-8" />
<!-- 告诉struts2,我要用spring装配工厂,其实默认就是这个了-_-!!! -->
<constant name="struts.objectFactory" value="spring" />
<!-- struts2的扩展名,比如struts1的时候,用的.do,struts2默认为.action,可以改成其它的,比如.dxd -->
<constant name="struts.action.extension" value="action" />
<!-- 资源文件 -->
<constant name="struts.custom.i18n.resources"
value="messageResource">
</constant>
<!-- 用户注册类 -->
<!-- abstract属性就说明了该action继承自自己定义的基础action,而class采用的registerAction是由spring产生的 -->
<package name="register" extends="struts-default" abstract="baseAction">
<action name="addUser" class="registerAction" method="addUser">
<!-- 注册成功 -->
<result name="success">/register/register_success.jsp</result>
<!-- 注册失败 -->
<result name="input">/register/register.jsp</result>
</action>
</package>
</struts>
jdbc.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ibatis
jdbc.user=root
jdbc.password=root
jdbc.minPoolSize=5
jdbc.maxPoolSize=20
jdbc.maxIdleTime=1800
jdbc.acquireIncrement=5
jdbc.maxStatements=50
jdbc.initialPoolSize=10
jdbc.idleConnectionTestPeriod=1800
jdbc.acquireRetryAttempts=30
SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<!-- 用户信息表 -->
<sqlMap resource="com/afl/system/entity/User.xml" />
</sqlMapConfig>
applicationContext-action.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- struts2's Action Mapping -->
<!-- 基础Action -->
<bean name="baseAction"
class="com.afl.system.struts2.action.BaseAction" scope="prototype">
</bean>
<!-- 用户注册action -->
<bean name="registerAction"
class="com.afl.register.action.RegisterAction" scope="prototype">
<property name="registerService" ref="registerService" />
</bean>
</beans>
applicationContext-iBatis.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- 配置数据源,连接池采用的是c3p0,具体各参数代表意义参看c3p0自带的doc,非常详细。 -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<property name="minPoolSize" value="${jdbc.minPoolSize}" />
<property name="maxPoolSize" value="${jdbc.maxPoolSize}" />
<property name="maxIdleTime" value="${jdbc.maxIdleTime}" />
<property name="acquireIncrement"
value="${jdbc.acquireIncrement}" />
<property name="maxStatements" value="${jdbc.maxStatements}" />
<property name="initialPoolSize"
value="${jdbc.initialPoolSize}" />
<property name="idleConnectionTestPeriod"
value="${jdbc.idleConnectionTestPeriod}" />
<property name="acquireRetryAttempts"
value="${jdbc.acquireRetryAttempts}" />
</bean>
<!-- 配置iBatis的sqlMapClient,这里当然是交给了spring去处理,其中,将SqlMapConfig文件放到了WEB-INF的iBatis目录下,也是便于管理 -->
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>/WEB-INF/iBatis/SqlMapConfig.xml</value>
</property>
<!-- 这里使用的数据源就是上面配置的数据源 -->
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 上面的数据源的value值用的是表达式,原因就在这里,这将配置文件放到了iBatis目录下,也就是jdbc.properties,设置了c3p0的各项参数 -->
<bean id="propertyConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/iBatis/jdbc.properties</value>
</property>
</bean>
<!-- 这个就是spring的事务管理了,采用的DataSource事务管理,要管理的DataSource当然也是上面配置的DataSource -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 事务管理的代理类,将其抽象化abstruct=true,以后需要进行事务管理直接继承此类就行了,非常方便 -->
<bean id="transactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<!-- 这个就是刚才配置的事务管理器 -->
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<!-- 下面是spring事务管理的策略,可以看到,凡是涉及数据库插入、修改的操作都应当以add、insert、edit、update、delete开头,这样才能由spring进行事务管理 -->
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="add*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="edit*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="delete*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 这是项目中注册类,使用的sqlMapClient由spring去注入 -->
<bean id="registerDAO"
class="com.afl.register.service.dao.impl.RegisterDAOImpl">
<property name="sqlMapClient">
<ref bean="sqlMapClient" />
</property>
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 项目中,我将事务管理放到了service层上,因为dao只负责与数据库基本交互,在此项目中一般只操作一个表,无需事务。而service层上根据业务需要处理多表,因此将事务放在了service层上,其中的parent就是上面配置并abstract的代理 -->
<bean id="registerService" parent="transactionProxy">
<property name="target">
<bean class="com.afl.register.service.impl.RegisterServiceImpl">
<property name="registerDAO">
<ref bean="registerDAO"/>
</property>
</bean>
</property>
</bean>
</beans>
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">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- struts2模块 -->
<filter>
<filter-name>struts2</filter-name>
<!-- 这个就是struts2的核心过滤器 -->
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 项目中的字符编码处理,与整合无关 -->
<!-- <filter>
<filter-name>CharacterFilter</filter-name>
<filter-class>
com.afl.system.filter.CharacterFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> -->
<!-- spring listener -->
<listener>
<!-- 这个就是今后用到的WebApplicationUtilContent -->
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- springframework config files -->
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- 把spring的配置文件放到了/WEB-INF/下的springframework包里,方便统一管理,命名规则是以applicationContent-开头的xml文件,初始化时会自动搜索所有符合规则的配置文件 -->
<param-value>
/WEB-INF/springframework/applicationContext-*.xml
</param-value>
</context-param>
<!-- config servlet -->
<!-- 这个是dwr的配置文件,与整合无关 -->
<servlet>
<servlet-name>dwr</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
4,JSP代码
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<%-- <a href="register/register.jsp">register</a> --%>
<jsp:forward page="register/register.jsp" />
</body>
</html>
register.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Register</title>
<script type="text/javascript">
function register(){
document.forms[0].action = 'register/addUser.action';
document.forms[0].submit();
}
</script>
</head>
<body >
<form>
<table style ="width:100%">
<tr>
<td>user name:</td>
<td><input type="text" name="username" id="username" maxlength="10"/></td>
</tr>
<tr>
<td>password:</td>
<td><input type="password" name="password" id="password" maxlength="15"/></td>
</tr>
<tr>
<td></td>
<td><input type="button" value="Register" οnclick="register();"></td>
</tr>
</table>
</form>
</body>
</html>
register_success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello</title>
</head>
<body>
Register successfully!
</body>
</html>
四,打包下载
说明;lib包很多,有不需要的自己删除。