Struts+Spring+ibatis基础实现

现在公司中做的新项目使用Struts+Spring+ibatis作为大致框架,我之前没有用过,趁着边学边做之际把一些流程记录一下,同时也整理一下流程,以便以后自己如果要构架软件结构的话可以用上。

一。构建struts框架

我使用的是myeclipse。新建一个web project,导入一下jar包:commons-logging-1.0.4.jar、freemarker-2.3.8.jar、ognl-2.6.11.jar、struts2-core-2.0.11.jar、xwork-2.0.4.jar

配置web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 id="WebApp_ID" version="2.5">
 

 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>
   org.apache.struts2.dispatcher.FilterDispatcher
  </filter-class>
 </filter>

 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>*.action</url-pattern>
 </filter-mapping>

 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>default.html</welcome-file>
  <welcome-file>default.htm</welcome-file>
  <welcome-file>default.jsp</welcome-file>
 </welcome-file-list>
</web-app>

写第一个Action:HelloWorldAction.java :

package cn.hxex.struts.helloworld.action;

import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class HelloWorldAction extends ActionSupport {
 public static final String MESSAGE = "Struts 2 Hello World Tutorial!";

 public String execute() throws Exception {
  setMessage(MESSAGE);
  return SUCCESS;
 }

 private String message;

 public void setMessage(String message) {
  this.message = message;
 }

 public String getMessage() {
  return message;
 }

 public String getCurrentTime() {
  return new Date().toString();
 }

}

对应的页面:helloworld.jsp:

<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
 <head>
  <title>Struts 2 Hello World Application!</title>
 </head>
 <body>
  <h2><s:property value="message" /></h2>
  <p>Current date and time is: <b><s:property value="currentTime" /></b>
 </body>
</html>

对应的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>

 <constant name="struts.devMode" value="true" />

 <package name="helloworld" namespace="/helloworld"
  extends="struts-default">

  <action name="HelloWorld"
   class="cn.hxex.struts.helloworld.action.HelloWorldAction">
   <result>/pages/HelloWorld.jsp</result>
  </action>

  <!-- Add actions here -->
 </package>
 
 </struts>

这样,访问http://localhost:8088/strutsdemo/helloworld/HelloWorld.action

大致可以运行一个简单的action了

二.Spring配置

首先,在web.xml里配置里加入spring的初始化配置

在lib文件夹加入asm.jar、cglib-2.1.3.jar

<listener>
  <listener-class>cn.hxex.struts.helloworld.listener.ContextLoaderListener</listener-class>
 </listener>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:applicationContext-beans.xml</param-value>
 </context-param>

对应的applicationContext-beans.xml:

<beans>
 <import resource="applicationContext-property.xml"/>
 <import resource="applicationContext-database.xml"/>
 <import resource="applicationContext-dao.xml"/>
 <import resource="applicationContext-service.xml"/>
</beans>

applicationContext-property.xml:

定义了引入的property文件

<beans>
  <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
   <list>
    <value>classpath:jdbc.properties</value>
   </list>
  </property>
 </bean>
</beans>

jdbc.properties:

定义了数据库的连接方式

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.maxActive=10
jdbc.maxIdle=1
jdbc.maxWait=10000
jdbc.initSize=1
jdbc.username=root
jdbc.password=111111
jdbc.readolnypassword=111111

jdbc.write.url=jdbc\:mysql\://localhost\:3306/test?user\=root&password\=111111&useUnicode\=true&characterEncoding\=utf8
jdbc.readonly.url=jdbc\:mysql\://localhost\:3306/test?user\=root&password\=111111&useUnicode\=true&characterEncoding\=utf8

applicationContext-database.xml:

使用spring定义了一下ibatis中需要的配置,ibatis的特点是读写分开,因此有writeDataSource和readDataSource。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

 <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
   <list>
    <value>classpath:jdbc.properties</value>
   </list>
  </property>
 </bean>
 
 <bean id="writeDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
  <property name="url"><value>${jdbc.write.url}</value></property>
  <property name="username"><value>${jdbc.username}</value></property>
  <property name="password"><value>${jdbc.password}</value></property>
  <property name="maxActive"><value>${jdbc.maxActive}</value></property>
  <property name="maxWait"><value>${jdbc.maxWait}</value></property>
  <property name="maxIdle"><value>${jdbc.maxIdle}</value></property>
  <property name="initialSize"><value>${jdbc.initSize}</value></property>
  <property name="removeAbandoned"><value>true</value></property>
 </bean>

 <bean id="readDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
  <property name="url"><value>${jdbc.readonly.url}</value></property>
  <property name="username"><value>${jdbc.username}</value></property>
  <property name="password"><value>${jdbc.password}</value></property>
  <property name="maxActive"><value>${jdbc.maxActive}</value></property>
  <property name="maxWait"><value>${jdbc.maxWait}</value></property>
  <property name="maxIdle"><value>${jdbc.maxIdle}</value></property>
  <property name="initialSize"><value>${jdbc.initSize}</value></property>
  <property name="removeAbandoned"><value>true</value></property>
 </bean>
 
 <!-- SqlMap setup for iBATIS Database Layer -->
    <bean id="sqlMapClient4Write" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation">
            <value>classpath:/cn/hxex/struts/helloworld/dao/impl/maps/sql-write-map-config.xml</value>
        </property>
        <property name="dataSource">
         <ref bean="writeDataSource"/>
        </property>
    </bean>
    
    <bean id="sqlMapClient4Read" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation">
            <value>classpath:/cn/hxex/struts/helloworld/dao/impl/maps/sql-read-map-config.xml</value>
        </property>
        <property name="dataSource">
         <ref bean="readDataSource"/>
        </property>
    </bean>
 
 <!-- Transaction manager for a single JDBC DataSource -->
    <bean id="writeTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource">
            <ref local="writeDataSource"/>
        </property>
    </bean>
 
 <bean id="readTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource">
            <ref local="readDataSource"/>
        </property>
    </bean>
 
 <bean id="writeTxInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager">
   <ref bean="writeTxManager"/>
  </property>
  <property name="transactionAttributes">
   <props>
    <prop key="*">PROPAGATION_REQUIRED,-Exception</prop>
   </props>
  </property>
 </bean>
 
 <bean id="readTxInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager">
   <ref bean="readTxManager"/>
  </property>
  <property name="transactionAttributes">
   <props>
    <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
   </props>
  </property>
 </bean>
 
 <bean id="txBeanNameProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  <property name="interceptorNames">
   <list>
    <value>writeTxInterceptor</value>
    <value>readTxInterceptor</value>
   </list>
  </property>
  <property name="beanNames">
   <list>
    <value>*Service</value>
   </list>
  </property>
 </bean>
</beans>

applicationContext-dao.xml:

DAO的定义

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC
    "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans default-autowire="no" default-lazy-init="false"
 default-dependency-check="none">

 <bean id="userReadDao" class="cn.hxex.struts.helloworld.dao.read.impl.UserReadDaoImpl">
  <property name="ibatisSqlMapClient">
   <ref bean="sqlMapClient4Read" />
  </property>
  <property name="myDataSource">
   <ref bean="readDataSource" />
  </property>
 </bean>

</beans>

applicationContext-service.xml:

业务逻辑service,里面需要调用数据库操作

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC
    "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans
  default-autowire="no"
  default-lazy-init="false"
  default-dependency-check="none"
>

  <bean id="userService" class="cn.hxex.struts.helloworld.service.UserService">
    <property name="userReadDao">
      <ref bean="userReadDao"/>
    </property>
  </bean>
  
 

  <!--
     To include additional bean definitions for Spring in the generated
     application context file, add a file to your XDoclet merge directory
     called spring-beans.xml that contains the <bean></bean> markup.
  -->

</beans>

sql-read-map-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

 <settings enhancementEnabled="true" maxTransactions="40"
  maxRequests="32" maxSessions="10" lazyLoadingEnabled="false" />

 <sqlMap resource="cn/hxex/struts/helloworld/dao/impl/maps/User.xml" />
</sqlMapConfig>

 

sql-write-map-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
    "http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

 <settings enhancementEnabled="true" maxTransactions="40"
  maxRequests="32" maxSessions="10" lazyLoadingEnabled="false" />

  <sqlMap resource="cn/hxex/struts/helloworld/dao/impl/maps/User.xml" />
</sqlMapConfig>

使用ibatis访问数据库的基类:

cn.hxex.struts.helloworld.dao.read.impl.BaseIbatisReadDaoImpl:

package cn.hxex.struts.helloworld.dao.read.impl;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

import com.ibatis.sqlmap.client.SqlMapClient;

/**
 * Ibatis型读dao基类
 *
 */
public class BaseIbatisReadDaoImpl extends SqlMapClientDaoSupport {

 protected final Log log = LogFactory.getLog(getClass());

 /**
  * @spring.property ref="sqlMapClient4Read"
  * @param sqlMapClient
  *            SqlMapClient
  */
 public void setIbatisSqlMapClient(SqlMapClient sqlMapClient) {
  super.setSqlMapClient(sqlMapClient);
 }

 /**
  * @spring.property ref="readDataSource"
  * @param dataSource
  *            DataSource
  */
 public void setMyDataSource(DataSource dataSource) {
  super.setDataSource(dataSource);
 }

 /**
  * 
  * @param ob
  * @return
  */
 public int getInt(Object ob) {
  if (ob != null)
   return Integer.parseInt(ob.toString());
  else
   return 0;
 }
}

做自己需要的dao时只要扩展这个基类就可以了:

package cn.hxex.struts.helloworld.dao.read.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hxex.struts.helloworld.dao.read.intf.IUserReadDao;
import cn.hxex.struts.helloworld.po.User;


/**
 * 
 */
public class UserReadDaoImpl extends BaseIbatisReadDaoImpl implements IUserReadDao
  {

 /**
  * 查询所有的用户
  * 
  * @return List
  */
 public List<User> getAllUser() {
  Map param = new HashMap();

  // 分页用
  // param.put("start", );
  // param.put("maxResult", );
  return (List<User>) super.getSqlMapClientTemplate().queryForList("getAllUsers", param);
 }

}

通过spring输入service:(applicationContext-service.xml中曾配置过)

package cn.hxex.struts.helloworld.service;

import java.util.List;

import cn.hxex.struts.helloworld.dao.read.intf.IUserReadDao;
import cn.hxex.struts.helloworld.po.User;

public class UserService {
 IUserReadDao userReadDao;
 public List<User> getAllUser(){
  return userReadDao.getAllUser();
 }
 public void setUserReadDao(IUserReadDao userReadDao) {
  this.userReadDao = userReadDao;
 }
}

在需要的Action中使用还需配置struts.xml:

加入拦截器:

<package name="front-default" extends="struts-default">
  <interceptors>
   <interceptor-stack name="defaultWebStack">
    <interceptor-ref name="autowiring" />
    <interceptor-ref name="staticParams" />
    <interceptor-ref name="params" />
   </interceptor-stack>
  </interceptors>
 </package>

之后继承自这个package

<package name="user" namespace="/user" extends="front-default">

或者直接配置在需要的action里

<package name="user" namespace="/user" extends="front-default">

  <action name="userQuery_*"
   class="cn.hxex.struts.helloworld.action.UserQueryAction"
   method="{1}">
   <result name="success">/pages/queryuser.jsp</result>
   <result name="edit" type="redirect">/helloworld/HelloWorld.action</result>
   <interceptor-ref name="defaultWebStack"/>
  </action>
  <!-- Add actions here -->
 </package>

具体拦截器的作用可以参见Struts2内建拦截器的简要介绍

之后就可以在需要的Action中自动注入所需服务了.

public class UserQueryAction extends ActionSupport {

 UserService userService;
 public String execute() throws Exception {
  List<User> result = userService.getAllUser();
  this.setUsers(result);
  return SUCCESS;
 }

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦