准备

导包

Struts2

导入 Struts2 zip 包解压目录下 'apps/struts-blank.war' 中所有 jar 包,如下:

asm-3.3.jar
asm-commons-3.3.jar
asm-tree-3.3.jar
commons-fileupload-1.4.jar
commons-io-2.2.jar
commons-lang3-3.2.jar
freemarker-2.3.28.jar
javassist-3.11.0.GA.jar
log4j-api-2.3.jar # 可选
log4j-core-2.3.jar # 可选
ognl-3.0.21.jar
struts2-core-2.3.37.jar
xwork-core-2.3.37.jar

另外导入 lib 下如下包:

struts2-convention-plugin-2.3.37.jar # Struts2 注解开发包
struts2-json-plugin-2.3.37.jar # Struts2 内置 Json 序列化支持包
struts2-spring-plugin-2.3.37.jar # Struts2 整合 Spring 包

Hibernate

首先是 Hibernate 开发的必须包,即 Hibernate zip 包 解压目录下 'lib/required' 下所有的包,如下:

antlr-2.7.7.jar
dom4j-1.6.1.jar
geronimo-jta_1.1_spec-1.1.1.jar
hibernate-commons-annotations-5.0.1.Final.jar
hibernate-core-5.0.7.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar
jandex-2.0.0.Final.jar
javassist-3.18.1-GA.jar
jboss-logging-3.3.0.Final.jar

Strut2 和 Hibernate 都引入了一个相同的 jar 包 javassisit,整合时必须只保留一个。

还需导入日志记录包

log4j-1.2.16.jar
slf4j-api-1.6.1.jar
slf4j-log4j12-1.7.2.jar

如果使用这里的日志记录包,那么 Struts2 包中两个可选日志记录包就不需要引入。

如果 Hibernate 要使用 C3P0 连接池,还需引入 'lib\optional\c3p0' 下所有包,如下:

c3p0-0.9.2.1.jar
hibernate-c3p0-5.0.7.Final.jar
mchange-commons-java-0.2.3.4.jar

当然,使用 Hibernate 还需要数据库驱动包,这里我使用 MySQL 驱动包

mysql-connector-java-5.1.7-bin.jar

Spring

使用 IoC 需引入的包:

com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.log4j-1.2.15.jar
spring-beans-4.2.4.RELEASE.jar
spring-context-4.2.4.RELEASE.jar
spring-core-4.2.4.RELEASE.jar
spring-expression-4.2.4.RELEASE.jar

使用 AOP 需引入的包:

com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.2.4.RELEASE.jar
spring-aspects-4.2.4.RELEASE.jar

使用 JDBC 模板需引入的包:

spring-jdbc-4.2.4.RELEASE.jar
spring-tx-4.2.4.RELEASE.jar

使用事务管理需引入的包:

spring-tx-4.2.4.RELEASE.jar

整合 web 项目需引入的包:

spring-web-4.2.4.RELEASE.jar

整合单元测试测试需引入的包:

spring-test-4.2.4.RELEASE.jar

整合 ORM 框架 Hibernate 需引入的包:

spring-orm-4.2.4.RELEASE.jar

上述完整 jar 包下载

配置

Struts2

配置 Struts2 的核心过滤器:

<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-INF/web.xml

引入 Struts2 核心配置文件:

<?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>
    <package name="test" extends="struts-default" namespace="/">

    </package>
</struts>

struts.xml

Hibernate

引入核心配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 连接数据库的基本参数 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///test</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <!-- 配置Hibernate的方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 可选配置================ -->

        <!-- 打印SQL -->
        <property name="hibernate.show_sql">true</property>
        <!-- 格式化SQL -->
        <property name="hibernate.format_sql">true</property>
        <!-- 自动创建表 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- 配置C3P0连接池 -->
        <property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
        <!--在连接池中可用的数据库连接的最少数目 -->
        <property name="c3p0.min_size">5</property>
        <!--在连接池中所有数据库连接的最大数目  -->
        <property name="c3p0.max_size">20</property>
        <!--设定数据库连接的过期时间,以秒为单位,
        如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
        <property name="c3p0.timeout">120</property>
        <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
        <property name="c3p0.idle_test_period">3000</property>
    </session-factory>
</hibernate-configuration>

hibernate.cfg.xml

Spring

配置 Spring 的核心监听器:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--默认情况下 Spring 会查找路径为 WEB-INF/applicationContext.xml 的配置文件,通过如下配置,让 Spring 在 classpath 下查找-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>

WEB-INF/web.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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- Spring整合Hibernate -->
    <!-- 引入Hibernate的配置的信息=============== -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- 引入hibernate的配置文件 -->
        <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
    </bean>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 开启注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

applicationContext.xml

Log4j 配置:

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###
# error warn info debug trace
log4j.rootLogger= info, stdout

log4j.properties

代码

java框架之Spring(4)-Spring整合Hibernate和Struts2-LMLPHP

package com.zze.domain;

public class User {
    private Integer id;
    private String name;
    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

com.zze.domain.User

package com.zze.dao;

import com.zze.domain.User;

public interface UserDao {
    void save(User user);
}

com.zze.dao.UserDao

package com.zze.dao.impl;

import com.zze.dao.UserDao;
import com.zze.domain.User;

public class UserDaoImpl implements UserDao {
    @Override
    public void save(User user) {
    }
}

com.zze.dao.impl.UserDaoImpl

package com.zze.service;

import com.zze.domain.User;

public interface UserService {
    void save(User user);
}

com.zze.service.UserService

package com.zze.service.impl;

import com.zze.dao.UserDao;
import com.zze.domain.User;
import com.zze.service.UserService;

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void save(User user) {
        userDao.save(user);
    }
}

com.zze.service.impl.UserServiceImpl

package com.zze.web.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.zze.domain.User;
public class UserAction extends ActionSupport implements ModelDriven<User> {
    private User user = new User();

    @Override
    public User getModel() {
        return user;
    }
}

com.zze.web.action.UserAction

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean name="userService" class="com.zze.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean name="userDao" class="com.zze.dao.impl.UserDaoImpl">
    </bean>
</beans>

applicationContext.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>
    <package name="test" extends="struts-default" namespace="/">
        <action name="customer_*" class="com.zze.web.action.UserAction" method="{1}">
        </action>
    </package>
</struts>

struts.xml

Spring整合Struts2

方式一:Action由Struts2自身创建

在 Action 中我们会调用业务层代码,如果按照传统方式,我们要获取到业务类实例,需要通过 Spring 工厂来手动获取,如下:

package com.zze.web.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.zze.domain.User;
import com.zze.service.UserService;
import org.apache.struts2.ServletActionContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class UserAction extends ActionSupport implements ModelDriven<User> {
    private User user = new User();

    @Override
    public User getModel() {
        return user;
    }

    public String save() {
        //传统方式获取 Service
        WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
        UserService userService = (UserService) applicationContext.getBean("userService");
        System.out.println(userService);
        /*
        访问 http://localhost:8080/customer_save,输出结果如下:
            com.zze.service.impl.UserServiceImpl@4b65044b
         */
        return NONE;
    }
}

com.zze.web.action.UserAction

而这种方式的代码显然过于复杂,Struts2 在与 Spring 整合时 Struts2 还为我们提供了更简易的方式哦。

Spring 整合 Struts2 需要引入一个 jar 包 struts2-spring-plugin.jar,这个 jar 包在上述准备工作中就已经引入,查看该 jar 中的 struts-plugin.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!--
/*
 * $Id$
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
-->
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />

    <!--  Make the Spring object factory the automatic default -->
    <constant name="struts.objectFactory" value="spring" />

    <constant name="struts.class.reloading.watchList" value="" />
    <constant name="struts.class.reloading.acceptClasses" value="" />
    <constant name="struts.class.reloading.reloadConfig" value="false" />
    <constant name="xwork.disallowProxyMemberAccess" value="true" />

    <package name="spring-default">
        <interceptors>
            <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
        </interceptors>
    </package>
</struts>

struts2-spring-plugin-2.3.37.jar!/struts-plugin.xml

可以看到在该文件中配置了如下常量:

<constant name="struts.objectFactory" value="spring" />

查看 Struts2 的默认配置:

 #
 # $Id$
 #
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
 # distributed with this work for additional information
 # regarding copyright ownership.  The ASF licenses this file
 # to you under the Apache License, Version 2.0 (the
 # "License"); you may not use this file except in compliance
 # with the License.  You may obtain a copy of the License at
 #
 #  http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing,
 # software distributed under the License is distributed on an
 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
 #
 ### START SNIPPET: complete_file

 ### Struts default properties
 ###(can be overridden by a struts.properties file in the root of the classpath)
 ###

 ### This can be used to set your default locale and encoding scheme
 # struts.locale=en_US
 struts.i18n.encoding=UTF-8

 ### if specified, the default object factory can be overridden here
 ### Note: short-hand notation is supported in some cases, such as "spring"
 ###       Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here
 # struts.objectFactory = spring

 ### specifies the autoWiring logic when using the SpringObjectFactory.
 ### valid values are: name, type, auto, and constructor (name is the default)
 struts.objectFactory.spring.autoWire = name

 ### indicates to the struts-spring integration if Class instances should be cached
 ### this should, until a future Spring release makes it possible, be left as true
 ### unless you know exactly what you are doing!
 ### valid values are: true, false (true is the default)
 struts.objectFactory.spring.useClassCache = true

 ### ensures the autowire strategy is always respected.
 ### valid values are: true, false (false is the default)
 struts.objectFactory.spring.autoWire.alwaysRespect = false

 ### By default SpringObjectFactory doesn't support AOP
 ### This flag was added just temporally to check if nothing is broken
 ### See https://issues.apache.org/jira/browse/WW-4110
 struts.objectFactory.spring.enableAopSupport = false

 ### if specified, the default object type determiner can be overridden here
 ### Note: short-hand notation is supported in some cases, such as "tiger" or "notiger"
 ###       Alternatively, you can provide a com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation name here
 ### Note: By default, com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer is used which handles type detection
 ###       using generics. com.opensymphony.xwork2.util.GenericsObjectTypeDeterminer was deprecated since XWork 2, it's
 ###       functions are integrated in DefaultObjectTypeDeterminer now.
 ###       To disable tiger support use the "notiger" property value here.
 #struts.objectTypeDeterminer = tiger
 #struts.objectTypeDeterminer = notiger

 ### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
 # struts.multipart.parser=cos
 # struts.multipart.parser=pell
 # struts.multipart.parser=jakarta-stream
 struts.multipart.parser=jakarta
 # uses javax.servlet.context.tempdir by default
 struts.multipart.saveDir=
 struts.multipart.maxSize=2097152

 ### Load custom property files (does not override struts.properties!)
 # struts.custom.properties=application,org/apache/struts2/extension/custom

 ### How request URLs are mapped to and from actions
 #struts.mapper.class=org.apache.struts2.dispatcher.mapper.DefaultActionMapper

 ### Used by the DefaultActionMapper
 ### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do
 ### The blank extension allows you to match directory listings as well as pure action names
 ### without interfering with static resources, which can be specified as an empty string
 ### prior to a comma e.g. struts.action.extension=, or struts.action.extension=x,y,z,,
 struts.action.extension=action,,

 ### Used by FilterDispatcher
 ### If true then Struts serves static content from inside its jar.
 ### If false then the static content must be available at <context_path>/struts
 struts.serve.static=true

 ### Used by FilterDispatcher
 ### This is good for development where one wants changes to the static content be
 ### fetch on each request.
 ### NOTE: This will only have effect if struts.serve.static=true
 ### If true -> Struts will write out header for static contents such that they will
 ###             be cached by web browsers (using Date, Cache-Content, Pragma, Expires)
 ###             headers).
 ### If false -> Struts will write out header for static contents such that they are
 ###            NOT to be cached by web browser (using Cache-Content, Pragma, Expires
 ###            headers)
 struts.serve.static.browserCache=true

 ### Set this to false if you wish to disable implicit dynamic method invocation
 ### via the URL request. This includes URLs like foo!bar.action, as well as params
 ### like method:bar (but not action:foo).
 ### An alternative to implicit dynamic method invocation is to use wildcard
 ### mappings, such as <action name="*/*" method="{2}" class="actions.{1}">
 struts.enable.DynamicMethodInvocation = false

 ### Set this to true if you wish to allow slashes in your action names.  If false,
 ### Actions names cannot have slashes, and will be accessible via any directory
 ### prefix.  This is the traditional behavior expected of WebWork applications.
 ### Setting to true is useful when you want to use wildcards and store values
 ### in the URL, to be extracted by wildcard patterns, such as
 ### <action name="*/*" method="{2}" class="actions.{1}"> to match "/foo/edit" or
 ### "/foo/save".
 struts.enable.SlashesInActionNames = false

 ### Disables support for action: prefix
 struts.mapper.action.prefix.enabled = false

 ### Blocks access to actions in other namespace than current with action: prefix
 struts.mapper.action.prefix.crossNamespaces = false

 ### use alternative syntax that requires %{} in most places
 ### to evaluate expressions for String attributes for tags
 struts.tag.altSyntax=true

 ### when set to true, Struts will act much more friendly for developers. This
 ### includes:
 ### - struts.i18n.reload = true
 ### - struts.configuration.xml.reload = true
 ### - raising various debug or ignorable problems to errors
 ###   For example: normally a request to foo.action?someUnknownField=true should
 ###                be ignored (given that any value can come from the web and it
 ###                should not be trusted). However, during development, it may be
 ###                useful to know when these errors are happening and be told of
 ###                them right away.
 struts.devMode = false

 ### when set to true, resource bundles will be reloaded on _every_ request.
 ### this is good during development, but should never be used in production
 ### struts.i18n.reload=false

 ### Standard UI theme
 ### Change this to reflect which path should be used for JSP control tag templates by default
 struts.ui.theme=xhtml
 struts.ui.templateDir=template
 ### Change this to use a different token to indicate template theme expansion
 struts.ui.theme.expansion.token=~~~
 #sets the default template type. Either ftl, vm, or jsp
 struts.ui.templateSuffix=ftl

 ### Configuration reloading
 ### This will cause the configuration to reload struts.xml when it is changed
 ### struts.configuration.xml.reload=false

 ### Location of velocity.properties file.  defaults to velocity.properties
 struts.velocity.configfile = velocity.properties

 ### Comma separated list of VelocityContext classnames to chain to the StrutsVelocityContext
 struts.velocity.contexts =

 ### Location of the velocity toolbox
 struts.velocity.toolboxlocation=

 ### used to build URLs, such as the UrlTag
 struts.url.http.port = 80
 struts.url.https.port = 443
 ### possible values are: none, get or all
 struts.url.includeParams = none

 ### Load custom default resource bundles
 # struts.custom.i18n.resources=testmessages,testmessages2

 ### workaround for some app servers that don't handle HttpServletRequest.getParameterMap()
 ### often used for WebLogic, Orion, and OC4J
 struts.dispatcher.parametersWorkaround = false

 ### configure the Freemarker Manager class to be used
 ### Allows user to plug-in customised Freemarker Manager if necessary
 ### MUST extends off org.apache.struts2.views.freemarker.FreemarkerManager
 #struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager

 ### Enables caching of FreeMarker templates
 ### Has the same effect as copying the templates under WEB_APP/templates
 ### struts.freemarker.templatesCache=false

 ### Enables caching of models on the BeanWrapper
 struts.freemarker.beanwrapperCache=false

 ### See the StrutsBeanWrapper javadocs for more information
 struts.freemarker.wrapper.altMap=true

 ### maxStrongSize for MruCacheStorage for freemarker, when set to 0 SoftCacheStorage which performs better in heavy loaded application
 ### check WW-3766 for more details
 struts.freemarker.mru.max.strong.size=0

 ### configure the XSLTResult class to use stylesheet caching.
 ### Set to true for developers and false for production.
 struts.xslt.nocache=false

 ### Whether to always select the namespace to be everything before the last slash or not
 struts.mapper.alwaysSelectFullNamespace=false

 ### Whether to allow static method access in OGNL expressions or not
 struts.ognl.allowStaticMethodAccess=false

 ### Whether to throw a RuntimeException when a property is not found
 ### in an expression, or when the expression evaluation fails
 struts.el.throwExceptionOnFailure=false

 ### Logs as Warnings properties that are not found (very verbose)
 struts.ognl.logMissingProperties=false

 ### Caches parsed OGNL expressions, but can lead to memory leaks
 ### if the application generates a lot of different expressions
 struts.ognl.enableExpressionCache=true

 ### Indicates if Dispatcher should handle unexpected exceptions by calling sendError()
 ### or simply rethrow it as a ServletException to allow future processing by other frameworks like Spring Security
 struts.handle.exception=true
 ### END SNIPPET: complete_file

struts2-core-2.3.37.jar!/org/apache/struts2/default.properties

在第 34 行可以看到,该常量默认是关闭的,而该常量只要开启,第 38 行的常量就会生效:

### specifies the autoWiring logic when using the SpringObjectFactory.
### valid values are: name, type, auto, and constructor (name is the default)
struts.objectFactory.spring.autoWire = name

而该配置的作用就是让 Action 可以按照变量名称自动注入 Spring 工厂中管理的实例,所以业务类实例还可通过如下方式获取:

package com.zze.web.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.zze.domain.User;
import com.zze.service.UserService;

public class UserAction extends ActionSupport implements ModelDriven<User> {
    private User user = new User();

    @Override
    public User getModel() {
        return user;
    }

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public String save() {
        System.out.println(userService);
        /*
        访问 http://localhost:8080/customer_save,输出结果如下:
            com.zze.service.impl.UserServiceImpl@389b9f55
         */
        return NONE;
    }
}

com.zze.web.action.UserAction

方式二:Action由Spring创建

修改配置:

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--
    让 Spring 来创建 Action 实例
        注意,Action 类要配置为多例
    -->
    <bean name="userAction" class="com.zze.web.action.UserAction" scope="prototype">
        <property name="userService" ref="userService"/>
    </bean>

    <bean name="userService" class="com.zze.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean name="userDao" class="com.zze.dao.impl.UserDaoImpl">
    </bean>
</beans>

applicationContext.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>
    <package name="test" extends="struts-default" namespace="/">
        <!--
        修改 class 对应 applicationContext.xml 中 bean 的名称 (id/name)
        -->
        <action name="customer_*" class="userAction" method="{1}">
        </action>
    </package>
</struts>

struts.xml

测试:

package com.zze.web.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.zze.domain.User;
import com.zze.service.UserService;

public class UserAction extends ActionSupport implements ModelDriven<User> {
    private User user = new User();

    @Override
    public User getModel() {
        return user;
    }

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public String save() {
        System.out.println(userService);
        /*
        访问 http://localhost:8080/customer_save,输出结果如下:
            com.zze.service.impl.UserServiceImpl@4f543a20
         */
        return NONE;
    }
}

com.zze.web.action.UserAction

Spring整合Hibernate

方式一:保留Hibernate配置文件

编写实体映射文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zze.domain.User" table="user">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name" length="32"/>
        <property name="age" column="age"/>
    </class>
</hibernate-mapping>

com/zze/domain/User.hbm.xml

在 Hibernate 核心配置文件中引入实体映射文件:

<mapping resource="com/zze/domain/User.hbm.xml"/>

hibernate.cfg.xml

修改 Dao 代码:

package com.zze.dao.impl;

import com.zze.dao.UserDao;
import com.zze.domain.User;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
// 使用 Hibernate 提供的 Dao 模板类
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

    @Override
    public void save(User user) {
        this.getHibernateTemplate().save(user);
    }
}

com.zze.dao.impl.UserDaoImpl

将 Hibernate 的核心工厂类实例交给 Spring 创建:

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--Spring 整合 Hibernate-->
    <!--引入 Hibernate 配置信息-->
    <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
    </bean>
    <!--
    <bean name="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    -->

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 开启注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--Spring 整合 Struts2-->
    <!--
    让 Spring 来创建 Action 实例
        注意,Action 类要配置为多例
    -->
    <bean name="userAction" class="com.zze.web.action.UserAction" scope="prototype">
        <property name="userService" ref="userService"/>
    </bean>

    <bean name="userService" class="com.zze.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean name="userDao" class="com.zze.dao.impl.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
        <!--
        <property name="hibernateTemplate" ref="hibernateTemplate"/>
        -->
    </bean>
</beans>

applicationContext.xml

测试:

package com.zze.web.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.zze.domain.User;
import com.zze.service.UserService;

public class UserAction extends ActionSupport implements ModelDriven<User> {
    private User user = new User();

    @Override
    public User getModel() {
        return user;
    }

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public String save() {
        userService.save(user);
        return NONE;
    }
}

java框架之Spring(4)-Spring整合Hibernate和Struts2-LMLPHP

java框架之Spring(4)-Spring整合Hibernate和Struts2-LMLPHP

com.zze.web.action.UserAction

方式二:去除Hibernate配置文件

新建数据库连接信息属性文件:

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test
jdbc.username=root
jdbc.password=root

jdbc.properties

删除 Hibernate 配置文件 hibernate.cfg.xml,在 Spring 配置文件中完成 Hibernate 相关配置:

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--配置 C3P0 数据源-->
    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--Spring 整合 Hibernate-->
    <!--引入 Hibernate 配置信息-->
    <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- 注入连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置Hibernate的相关属性 -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>

        <!-- 设置映射文件 -->
        <property name="mappingResources">
            <list>
                <value>com/zze/domain/User.hbm.xml</value>
            </list>
        </property>
    </bean>
    <!--
    <bean name="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    -->

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 开启注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!--Spring 整合 Struts2-->
    <!--
    让 Spring 来创建 Action 实例
        注意,Action 类要配置为多例
    -->
    <bean name="userAction" class="com.zze.web.action.UserAction" scope="prototype">
        <property name="userService" ref="userService"/>
    </bean>

    <bean name="userService" class="com.zze.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean name="userDao" class="com.zze.dao.impl.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
        <!--
        <property name="hibernateTemplate" ref="hibernateTemplate"/>
        -->
    </bean>
</beans>

applicationContext.xml

测试:

package com.zze.web.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.zze.domain.User;
import com.zze.service.UserService;

public class UserAction extends ActionSupport implements ModelDriven<User> {
    private User user = new User();

    @Override
    public User getModel() {
        return user;
    }

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public String save() {
        userService.save(user);
        return NONE;
    }
}

java框架之Spring(4)-Spring整合Hibernate和Struts2-LMLPHP

java框架之Spring(4)-Spring整合Hibernate和Struts2-LMLPHP

com.zze.web.action.UserAction

补充

延迟加载问题

Hibernate 是有延迟加载策略的,Spring 整合 Hibernate 后,session 的是由 Spring 管理的。当我们做一个有延迟加载的查询操作时,默认情况下在 service 层已经完成了 session 的开启与关闭操作,所以如果我们要在 web 层使用延迟加载,此时 session 是关闭的状态,会抛出如下异常:

java框架之Spring(4)-Spring整合Hibernate和Struts2-LMLPHP

对于这个问题 Spring 也给我们提供了解决方案,只需要配置上它提供的一个过滤器即可,如下:

<filter>
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>openSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

WEB-INF/web.xml

抽取通用Dao

package com.zze.dao;

import org.hibernate.criterion.DetachedCriteria;

import java.io.Serializable;
import java.util.List;

public interface BaseDao<T> {
    /**
     * 保存操作
     *
     * @param model 要保存的模型
     */
    void save(T model);

    /**
     * 更新操作
     *
     * @param model 要更新的模型
     */
    void update(T model);

    /**
     * 删除操作
     *
     * @param id 删除的 id
     */
    void delete(Serializable id);

    /**
     * 通过 id 查询单个对象
     *
     * @param id 要删除数据主键
     * @return 返回 id 对应的单个对象
     */
    T findById(Serializable id);

    /**
     * 查询所有数据
     *
     * @return 以 List 方式返回所有数据
     */
    List<T> findAll();

    /**
     * 查询数据条数
     *
     * @param detachedCriteria 离线查询对象
     * @return 数据条数
     */
    Serializable findCount(DetachedCriteria detachedCriteria);

    /**
     * 分页查询
     *
     * @param detachedCriteria 离线查询对象
     * @param begin            数据起始索引
     * @param pageSize         每页数据条数
     * @return 返回分页的珊瑚橘
     */
    List<T> findPage(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize);

}

com.zze.dao.BaseDao

package com.zze.dao.impl;

import com.zze.dao.BaseDao;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {

    private Class clazz;

    public BaseDaoImpl() {
        /*
         例: class UserDaoImpl extends BaseDaoImpl<User>
         */
        // 获取到运行时实际类 UserDaoImpl
        Class<? extends BaseDaoImpl> actualClass = this.getClass();
        // 获取到实际类父类 BaseDaoImpl<User>
        Type genericSuperclass = actualClass.getGenericSuperclass();
        // 转为参数化类型
        ParameterizedType type = (ParameterizedType) genericSuperclass;
        // 获取类型化参数 User
        Type[] actualTypeArguments = type.getActualTypeArguments();
        this.clazz = (Class) actualTypeArguments[0];
    }

    @Override
    public void save(T model) {
        this.getHibernateTemplate().save(model);
    }

    @Override
    public void update(T model) {
        this.getHibernateTemplate().update(model);
    }

    @Override
    public void delete(Serializable id) {
        this.getHibernateTemplate().delete(id);
    }

    @Override
    public T findById(Serializable id) {
        return (T) this.getHibernateTemplate().get(clazz, id);
    }

    @Override
    public List<T> findAll() {
        return (List<T>) this.getHibernateTemplate().find("from " + clazz.getSimpleName());
    }

    @Override
    public Serializable findCount(DetachedCriteria detachedCriteria) {
        detachedCriteria.setProjection(Projections.rowCount());
        List<Long> list = (List<Long>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
        return list.size() > 0 ? list.get(0).intValue() : null;
    }

    @Override
    public List<T> findPage(DetachedCriteria detachedCriteria,Integer begin,Integer pageSize) {
        detachedCriteria.setProjection(null);
        return (List<T>) this.getHibernateTemplate().findByCriteria(detachedCriteria, begin, pageSize);
    }
}

com.zze.dao.impl.BaseDaoImpl

SSH注解整合

1、导包,同上述准备工作中包。

2、配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--Struts2 过滤器-->
    <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>

    <!--Spring 核心监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--配置 Spring 配置文件加载路径,默认加载 WEB-INF/applicationContext.xml-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
</web-app>

WEB-INF/web.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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--开启组件扫描-->
    <context:component-scan base-package="com.zze"/>
    <!--配置 C3P0 数据源-->
    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--Spring 整合 Hibernate-->
    <!--引入 Hibernate 配置信息-->
    <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- 注入连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置Hibernate的相关属性 -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
        <!--配置映射扫描-->
        <property name="packagesToScan" value="com.zze.domain"/>
    </bean>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- 开启注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean name="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
</beans>

applicationContext.xml

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test
jdbc.username=root
jdbc.password=root

jdbc.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###
# error warn info debug trace
log4j.rootLogger= info, stdout

log4j.properties

3、使用注解:

package com.zze.domain;

import javax.persistence.*;

@Table(name = "user")
@Entity
public class User {
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "name")
    private String name;
    @Column(name = "age")
    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

com.zze.domain.User : Hibernate 实体映射注解

package com.zze.dao.impl;

import com.zze.dao.BaseDao;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;

import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {

    /**
     * 注入 sessionFactory
     *
     * @param sessionFactory
     */
    @Autowired
    private void setSF(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    /*
    或
    @Resource(name = "hibernateTemplate")
    private HibernateTemplate hibernateTemplate;
    */
    private Class clazz;

    public BaseDaoImpl() {
        /*
         例: class UserDaoImpl extends BaseDaoImpl<User>
         */
        // 获取到运行时实际类 UserDaoImpl
        Class<? extends BaseDaoImpl> actualClass = this.getClass();
        // 获取到实际类父类 BaseDaoImpl<User>
        Type genericSuperclass = actualClass.getGenericSuperclass();
        // 转为参数化类型
        ParameterizedType type = (ParameterizedType) genericSuperclass;
        // 获取类型化参数 User
        Type[] actualTypeArguments = type.getActualTypeArguments();
        this.clazz = (Class) actualTypeArguments[0];
    }

    @Override
    public void save(T model) {
        this.getHibernateTemplate().save(model);
    }

    @Override
    public void update(T model) {
        this.getHibernateTemplate().update(model);
    }

    @Override
    public void delete(Serializable id) {
        this.getHibernateTemplate().delete(id);
    }

    @Override
    public T findById(Serializable id) {
        return (T) this.getHibernateTemplate().get(clazz, id);
    }

    @Override
    public List<T> findAll() {
        return (List<T>) this.getHibernateTemplate().find("from " + clazz.getSimpleName());
    }

    @Override
    public Serializable findCount(DetachedCriteria detachedCriteria) {
        detachedCriteria.setProjection(Projections.rowCount());
        List<Long> list = (List<Long>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
        return list.size() > 0 ? list.get(0).intValue() : null;
    }

    @Override
    public List<T> findPage(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize) {
        detachedCriteria.setProjection(null);
        return (List<T>) this.getHibernateTemplate().findByCriteria(detachedCriteria, begin, pageSize);
    }
}

com.zze.dao.impl.BaseDaoImpl : dao 层注入 sessionFactory

package com.zze.dao.impl;

import com.zze.dao.UserDao;
import com.zze.domain.User;
import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {

}

com.zze.dao.impl.UserDaoImpl : dao 层实例化注解

package com.zze.service.impl;

import com.zze.dao.UserDao;
import com.zze.domain.User;
import com.zze.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public void save(User user) {
        userDao.save(user);
    }
}

com.zze.service.impl.UserServiceImpl : service 层实例化和事务注解

package com.zze.web.action;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.zze.domain.User;
import com.zze.service.UserService;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.stereotype.Controller;

@Controller("userAction")
@ParentPackage("struts-default")
@Namespace("/user")
public class UserAction extends ActionSupport implements ModelDriven<User> {
    private User user = new User();

    @Override
    public User getModel() {
        return user;
    }

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    // 访问路径 localhost:8080/user/save
    @Action(value = "save",results = {@Result(name = "success",location = "/index.jsp")})
    public String save() {
        userService.save(user);
        return NONE;
    }
}

com.zze.web.action.UserAction : web 层实例化和 Struts2 配置注解

属性文件值注入

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test
jdbc.username=root
jdbc.password=root

jdbc.properties

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="classpath:jdbc.properties"/>
</beans>

applicationContext.xml

package com.zze.spring.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
    @Value("${jdbc.driverClass}")
    private String driverClass;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Test
    public void test() {
        System.out.println(driverClass);
        System.out.println(url);
        System.out.println(username);
        System.out.println(password);

        /*
        com.mysql.jdbc.Driver
        jdbc:mysql:///test
        root
        root
         */
    }
}

com.zze.spring.test.Demo

05-07 15:16