闲来无事,收集了各种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" onclick="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包很多,有不需要的自己删除。
war文件
工程ZIP文件