2025年3月31日 星期一 乙巳(蛇)年 正月初一 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Maven

Maven搭建SSH(Struts2+Spring+Hibernate)框架入门教程(附带实例)

时间:12-16来源:作者:点击数:82

前面介绍了基于 Archiva 的私服搭建工作,现在全项目组就可以在私服下共用 Maven 开发环境了。

接下来在 Maven 环境下,基于 Struts2+Spring4.2+Hibernate4.1 框架,体验 Web 应用的开发过程。为了展现 Maven 开发的优势,将按如下步骤进行。

  1. 创建三个 POM 工程,定义好 Hibernate、Spring 和 Struts 的基本依赖。
  2. 创建 Service 和 DAO 层的接口模块。
  3. 创建 Service 和 DAO 层的实现模块。
  4. 创建基于 Struts 的 Web 模块。
  5. 整合前面的所有模块,形成一个完整的 SSH 项目。
  6. 完善相关的文档插件的配置,进行安装和测试。

创建公共 POM 模块

1. 创建 Hibernate 的公共 POM 模块

基于 MyEclipse 的 maven-archetype-quickstart 创建 Maven 工程(同前面创建基本的 Maven 工程一样)。因为用的是公共 POM 模块,这里不需要写代码,只需将 Hibernate 和相关的依赖配置在 pom.xml 中,并且在 pom.xml 中将 packaging 方式设置成 pom,表示是一个公共的父 pom。代码如下:

  • <project xmlns="http://maven.apache.org/POM/4.0.0"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  • <modelVersion>4.0.0</modelVersion>
  • <groupId>cn.com.mvn.ssh.pom</groupId>
  • <artifactId>Hibernate4MySQLPOM</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • <packaging>pom</packaging>
  • <name>Hibernate4MySQLPOM</name>
  • <url>http://maven.apache.org</url>
  • <properties>
  • <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  • </properties>
  • <dependencies>
  • <dependency>
  • <groupId>junit</groupId>
  • <artifactId>junit</artifactId>
  • <version>4.7</version>
  • <scope>test</scope>
  • </dependency>
  • <!--hibernate -->
  • <dependency>
  • <groupId>org.hibernate</groupId>
  • <artifactId>hibernate-core</artifactId>
  • <version>${project.build.hibernate.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.hibernate</groupId>
  • <artifactId>hibernate-ehcache</artifactId>
  • <version>${project.build.hibernate.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.hibernate.javax.persistence</groupId>
  • <artifactId>hibernate-jpa-2.0-api</artifactId>
  • <version>1.0.0.Final</version>
  • </dependency>
  • <dependency>
  • <groupId>mysql</groupId>
  • <artifactId>mysql-connector-java</artifactId>
  • <version>5.1.34</version>
  • </dependency>
  • </dependencies>
  • <distributionManagement>
  • <repository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/internal</url>
  • </repository>
  • <snapshotRepository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/snapshots</url>
  • </snapshotRepository>
  • </distributionManagement>
  • </project>

注意 pom.xml 中的第 9 行,<packaging>pom</packaging>表示当前的 pom 是一个独立的 pom 父模块,可以独立安装到仓库中,被其他工程继承使用。

同时注意最后的 distributionManagement 配置,该配置可以让工程以构件的形式发布到指定的私服。

右击“工程”,选择 Run As→Maven install 命令,就可以把当前 pom 安装到前面搭建好 Archiva 私服。安装后,可以在 Archiva 管理界面的 Browse 导航页中,看到 Hibernate4MySQLPOM 构件。

2. 创建 Spring 的公共 POM 模块

同前面 Hibernate 的 POM 创建一样,可以创建基于 Spring 的 POM 公共构件模块。具体工程创建就不演示了,直接复制到 pom.xml 中。

  • <project xmlns="http://maven.apache.org/POM/4.0.0"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  • <modelVersion>4.0.0</modelVersion>
  • <groupId>cn.com.mvn.pom</groupId>
  • <artifactId>SpringPOM</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • <packaging>pom</packaging>
  • <name>SpringPOM</name>
  • <url>http://maven.apache.org</url>
  • <properties>
  • <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  • <!-- 3.2.16.RELEASE,3.1.4.RELEASE -->
  • <project.build.spring.version>4.2.7.RELEASE
  • </project.build.spring.version>
  • </properties>
  • <dependencies>
  • <dependency>
  • <groupId>junit</groupId>
  • <artifactId>junit</artifactId>
  • <version>4.7</version>
  • <scope>test</scope>
  • </dependency>
  • <!-- spring -->
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-core</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-aop</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-beans</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-context</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-context-support</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-web</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-webmvc</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-aspects</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.springframework</groupId>
  • <artifactId>spring-orm</artifactId>
  • <version>${project.build.spring.version}</version>
  • </dependency>
  • <dependency>
  • <groupId>org.hibernate</groupId>
  • <artifactId>hibernate-validator</artifactId>
  • <version>5.0.0.Final</version>
  • </dependency>
  • </dependencies>
  • <distributionManagement>
  • <repository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/internal</url>
  • </repository>
  • <snapshotRepository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/snapshots</url>
  • </snapshotRepository>
  • </distributionManagement>
  • </project>

同样注意粗体提示部分。右击“工程”,选择 Run As→Maven install 命令,安装 POM 构件。

3. 创建 Struts 的公共 POM 模块

重复前面的流程,直接复制 pom.xml 代码和安装 pom 后的管理界面。需要注意,在 pom.xml 中,除了 Struts 的依赖之外,还有 jsp/servlet 的依赖和 Struts 同 Spring 集成的插件依赖。

pom.xml 内容如下:

  • <project xmlns="http://maven.apache.org/POM/4.0.0"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  • <modelVersion>4.0.0</modelVersion>
  • <groupId>cn.com.mvn.pom</groupId>
  • <artifactId>StrutsPOM</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • <packaging>pom</packaging>
  • <name>StrutsPOM</name>
  • <url>http://maven.apache.org</url>
  • <properties>
  • <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  • </properties>
  • <dependencies>
  • <!-- jsp servlet -->
  • <dependency>
  • <groupId>javax.servlet</groupId>
  • <artifactId>servlet-api</artifactId>
  • <version>2.5</version>
  • <scope>provided</scope>
  • </dependency>
  • <dependency>
  • <groupId>javax.servlet.jsp</groupId>
  • <artifactId>jsp-api</artifactId>
  • <version>2.1</version>
  • <scope>provided</scope>
  • </dependency>
  • <dependency>
  • <groupId>javax.servlet</groupId>
  • <artifactId>jstl</artifactId>
  • <version>1.2</version>
  • </dependency>
  • <!-- struts2 -->
  • <!-- https://mvnrepository.com/artifact/org.apache.struts/struts2-core -->
  • <dependency>
  • <groupId>org.apache.struts</groupId>
  • <artifactId>struts2-core</artifactId>
  • <version>2.3.16</version>
  • </dependency>
  • <!-- https://mvnrepository.com/artifact/org.apache.struts/struts2-spring-plugin -->
  • <dependency>
  • <groupId>org.apache.struts</groupId>
  • <artifactId>struts2-spring-plugin</artifactId>
  • <version>2.3.4.1</version>
  • </dependency>
  • <dependency>
  • <groupId>junit</groupId>
  • <artifactId>junit</artifactId>
  • <version>4.7</version>
  • <scope>test</scope>
  • </dependency>
  • </dependencies>
  • <distributionManagement>
  • <repository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/internal</url>
  • </repository>
  • <snapshotRepository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/snapshots</url>
  • </snapshotRepository>
  • </distributionManagement>
  • </project>

实现 Hibernate DAO 模块

在实际项目中,一般会使用面向接口编程,从而实现调用者和被调用者的完全解耦,方便项目的团队开发和后期的扩展。鉴于这样的考虑,Hibernate 持久层的实现分两步进行:第 1 步定义公共 DAO 接口和类;第 2 步基于 Hibernate 完成 DAO 接口的实现。详细介绍如下。

1. 定义公共 DAO 接口和类

创建一个普通的 Maven 工程:MvnSSHDemo.DAO。目录结构如图 1 所示。 


图 1  DAO项目结构

pom.xml 内容如下:

  • <project xmlns="http://maven.apache.org/POM/4.0.0"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  • <modelVersion>4.0.0</modelVersion>
  • <groupId>cn.com.mvn.ssh.demo</groupId>
  • <artifactId>MvnSSHDemo.DAO</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • <packaging>jar</packaging>
  • <name>MvnSSHDemo.DAO</name>
  • <url>http://maven.apache.org</url>
  • <properties>
  • <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  • </properties>
  • <dependencies>
  • <dependency>
  • <groupId>junit</groupId>
  • <artifactId>junit</artifactId>
  • <version>4.7</version>
  • <scope>test</scope>
  • </dependency>
  • </dependencies>
  • <distributionManagement>
  • <repository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/internal</url>
  • </repository>
  • <snapshotRepository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/snapshots</url>
  • </snapshotRepository>
  • </distributionManagement>
  • </project>

这里有两类代码:一类是实体类(MvnUser),另一类是实体 DAO 接口(IMvnUserDAO)。因为 MvnUser 里面有个状态(status)属性,定义了一个枚举状态类(Status)。具体内容如下。

1)Status.java 代码如下所示:

  • package cn.com.mvn.ssh.demo.entity;
  • public enum Status {
  • ACTIVE("Active"), INACTIVE("Inactive"), DELETED("Deleted"), LOCKED("Locked");
  • private String status;
  • private Status(final String status) {
  • this.status = status;
  • }
  • public String getStatus() {
  • return status;
  • }
  • public void setStatus(String status) {
  • this.status = status;
  • }
  • public String toString() {
  • return this.status;
  • }
  • }

2)MvnUser.java 如下所示:

  • package cn.com.mvn.ssh.demo.entity;
  • public class MvnUser {
  • private int urId;
  • private String urUserName;
  • private String urPassword;
  • private int urAge;
  • private String urStatus = Status.ACTIVE.getStatus();// Active
  • public int getUrId() {
  • return urId;
  • }
  • public void setUrId(int urId) {
  • this.urId = urId;
  • }
  • public String getUrUserName() {
  • return urUserName;
  • }
  • public void setUrUserName(String urUserName) {
  • this.urUserName = urUserName;
  • }
  • public String getUrPassword() {
  • return urPassword;
  • }
  • public void setUrPassword(String urPassword) {
  • this.urPassword = urPassword;
  • }
  • public int getUrAge() {
  • return urAge;
  • }
  • public void setUrAge(int urAge) {
  • this.urAge = urAge;
  • }
  • public String getUrStatus() {
  • return urStatus;
  • }
  • public void setUrStatus(String urStatus) {
  • this.urStatus = urStatus;
  • }
  • }

3)IMvnUserDAO.java 代码如下所示:

  • package cn.com.mvn.ssh.demo.dao;
  • import java.util.List;
  • import cn.com.mvn.ssh.demo.entity.MvnUser;
  • /**
  • * MvnUser实体对象的持久层代码,封装了对MvnUser实体对象的CRUD方法
  • *
  • * @author Noble
  • * @version 1.0
  • */
  • public interface IMvnUserDAO {
  • /**
  • * 在数据库中,添加一个新的MvnUser对象
  • *
  • * @param user 需要添加的用户实体对象,该对象需要有用户名、密码、年龄和状态属性
  • *
  • * @return void
  • * @throws RuntimeException 添加失败或出现其它意外
  • */
  • public void addUser(MvnUser user);
  • /**
  • * 更新MvnUser对象。该对象中需要设置年龄、状态和id属性,属性和状态是要更新的新值,id为条件
  • *
  • * @param user 需要更新的MvnUser对象
  • *
  • * @return void
  • * @throws RuntimeException 更新失败或出现其它意外
  • */
  • public void update(MvnUser user);
  • /**
  • * 删除MvnUser对象,该对象中需要有要删除对象的id属性,id属性为删除条件
  • *
  • * @param user 要删除的MvnUser对象
  • *
  • * @return void
  • * @throws RuntimeException 删除失败或出现其它意外
  • */
  • public void deleteUser(MvnUser user);
  • /**
  • * 根据id查询对应的MvnUser对象
  • *
  • * @param id 要查询的MvnUser对象的id
  • * @return MvnUser id对应的MvnUser对象,如果没有对象,返回null
  • * @throws RuntimeException 出现意外情况
  • */
  • public MvnUser findUserById(int id);
  • /**
  • * 根据用户名查询对应的MvnUser对象
  • *
  • * @param userName 要查询的MvnUser对象的用户名
  • * @return MvnUser 用户对应的MvnUser对象,如果没有对象,返回null
  • * @throws RuntimeException 出现意外情况
  • */
  • public MvnUser findUserByUserName(String userName);
  • /**
  • * 查找数据库中所有的用户对象,以List集合的形式返回
  • *
  • * @return List<MvnUser> 所有用户对象的集合
  • * @throws RuntimeException 出现意外情况
  • */
  • public List<MvnUser> findUsers();
  • }

右击“工程”,选择 Run As→Maven install 命令,MyEclipse 会自动将工程代码编译打包。如果没有错误,最后会以构件的形式安装在本地仓库中。结果如图 5 所示。

为了方便公司其他开发人员使用,接下来将该项目以构件的形式发布到前面搭建好的私服。为了使发布成功,请按前面的私服介绍搭建并启动私服,同时在当前工程的 pom.xml 中,添加 distributionManagement 配置,详细参考前面的 pom.xml。具体操作和效果图如下所示。

右击“工程”,选择 Run As→Maven build… 命令。

在 Goals 中输入 deploy,单击 Run 按钮。

2. 基于 Hibernate 完成 DAO 接口的实现

团队商量确定好接口,接下来就是对接口的实现和基于接口上的开发工作了。因为有共同的接口,所以这两个工作可以同步进行。这种现象同计算机配件一样(硬盘、内存、CPU、显卡等),事先定义好标准(插口),不同厂商就可以按同样的标准各自生产,然后顺利组装在一起,不用管是哪个厂家、在哪里、用哪条流水线生产的。

接下来介绍 DAO 接口的实现,分以下 4 步进行。

1)创建工程,添加相关依赖

这个步骤比较简单,创建工程的方式同以前一样,具体创建过程不重复,项目结构如图 2 所示。 

Hibernate DAO项目结构
图 2  Hibernate DAO项目结构

注意如下:

① 因为前面创建了公共的 Hibernate POM 工程,里面有描述好了 Hibernate 相关的依赖(目的是让所有开发人员重用,不再重复编写),并且以构件的形式安装发布好了。这里要体现的是怎样继承前面定义好的 pom。

② 同样地,因为新工程里面要实现 MvnSSHDemo.DAO 中定义的接口,并且用到里面定义的公共类,而且根据前面的介绍,MvnSSHDemo.DAO,也以构件的形式安装发布到私服中了。在这里,要介绍一下怎样在自己的工程里面设置团队内部发布的构件。

这两点注意事项主要体现在 pom.xml 中,pom.xml 内容如下:

  • <?xml version="1.0" encoding="UTF-8"?>
  • <project
  • xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
  • xmlns="http://maven.apache.org/POM/4.0.0"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  • <modelVersion>4.0.0</modelVersion>
  • <parent>
  • <groupId>cn.com.mvn.pom</groupId>
  • <artifactId>Hibernate4MySQLPOM</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • </parent>
  • <groupId>cn.com.mvn.ssh.demo.dao.hibernate</groupId>
  • <artifactId>MvnSSHDemo.DAO.Hibernate</artifactId>
  • <name>MvnSSHDemo.DAO.Hibernate</name>
  • <url>http://maven.apache.org</url>
  • <properties>
  • <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  • </properties>
  • <dependencies>
  • <dependency>
  • <groupId>cn.com.mvn.ssh.demo</groupId>
  • <artifactId>MvnSSHDemo.DAO</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • </dependency>
  • <dependency>
  • <groupId>cn.com.mvn.pom</groupId>
  • <artifactId>SpringPOM</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • <type>pom</type>
  • </dependency>
  • </dependencies>
  • <distributionManagement>
  • <repository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/internal</url>
  • </repository>
  • <snapshotRepository>
  • <id>archivaServer</id>
  • <url>http://localhost:8080/repository/snapshots</url>
  • </snapshotRepository>
  • </distributionManagement>
  • </project>

其中 7~11 行,它描述的是当前的 pom.xml,继承了 Hibernate4-MySQLPOM 构件中定义的 pom 内容,其中 groupId、artifactId 和 version 共同形成构件的坐标。

当 pom 需要继承别人定义好的 pom 时,只需要使用如上 parent 配置指定就行。不过这里的继承同 Java 中继承一样,只能单继承,而且只能继承 packaging 类型为 pom 的构件(这点可以看 Hibernate4MySQLPOM 中的 pom.xml 文件,里面的 packaging 是 pom)。

20~30 行,描述的是两个依赖。第 1 个依赖是前面定义的 DAO 接口和公共类的构件依赖。通过查看代码,其实同使用从网上找的其他依赖一样。

第 2 个虽然也是使用前面定义的 Spring 的公共 pom 依赖,但是有点不同,里面包含了一个<type>pom</type>,这个元素指定的是依赖的 packaging 类型。

依赖的 packaging 类型默认是 jar(前面所有 pom.xml 中没有指定 type 的情况),如果 pom 引用的依赖是 pom 类型,就需要在 dependency 中添加 type 元素,指定是类型 pom,形同这里用到的第 2 个依赖,否则构建的时候会报错。

2)编写实现代码

基于 Hibernate 的 DAO 实现代码主要有如下几个类。

① MvnUser4Hibernate.java,该类继承了 MvnUser 类,里面用注解描述了实体信息,代码如下所示。

  • package cn.com.mvn.ssh.demo.entity.hibernate;
  • import javax.persistence.Column;
  • import javax.persistence.Entity;
  • import javax.persistence.GeneratedValue;
  • import javax.persistence.GenerationType;
  • import javax.persistence.Id;
  • import javax.persistence.Table;
  • import cn.com.mvn.ssh.demo.entity.MvnUser;
  • @Entity
  • @Table(catalog = "mvn_db", name = "mvn_user")
  • public class MvnUser4Hibernate extends MvnUser {
  • @Id
  • @GeneratedValue(strategy = GenerationType.IDENTITY)
  • @Column(name = "ur_id")
  • public int getUrId() {
  • // TODO Auto-generated method stub
  • return super.getUrId();
  • }
  • @Column(name = "ur_user_name", length = 20, unique = true, nullable = false)
  • public String getUrUserName() {
  • // TODO Auto-generated method stub
  • return super.getUrUserName();
  • }
  • @Column(name = "ur_password", length = 10, nullable = false)
  • public String getUrPassword() {
  • // TODO Auto-generated method stub
  • return super.getUrPassword();
  • }
  • @Column(name = "ur_age")
  • public int getUrAge() {
  • // TODO Auto-generated method stub
  • return super.getUrAge();
  • }
  • @Column(name = "ur_status", length = 20, nullable = true)
  • public String getUrStatus() {
  • // TODO Auto-generated method stub
  • return super.getUrStatus();
  • }
  • }

② AbstractDAO.java,该类定义了实体的公共持久化方法,所有的 DAO 实现类就继承它,代码如下所示。

  • package cn.com.mvn.ssh.demo.dao.hibernate;
  • import java.io.Serializable;
  • import java.lang.reflect.ParameterizedType;
  • import java.util.List;
  • import org.hibernate.Criteria;
  • import org.hibernate.Session;
  • import org.hibernate.SessionFactory;
  • import org.springframework.beans.factory.annotation.Autowired;
  • import cn.com.mvn.ssh.demo.entity.MvnUser;
  • import cn.com.mvn.ssh.demo.entity.hibernate.MvnUser4Hibernate;
  • public abstract class AbstractDAO<PK extends Serializable, T> {
  • private final Class<T> persistentClass;
  • @SuppressWarnings("unchecked")
  • public AbstractDAO() {
  • this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
  • .getActualTypeArguments()[1];
  • }
  • @Autowired
  • private SessionFactory sessionFactory;
  • protected Session getSession() {
  • return sessionFactory.getCurrentSession();
  • }
  • @SuppressWarnings("unchecked")
  • public T getByKey(PK key) {
  • return (T) getSession().get(persistentClass, key);
  • }
  • public void persist(T entity) {
  • getSession().persist(entity);
  • }
  • public void delete(T entity) {
  • getSession().delete(entity);
  • }
  • public void update(T entity) {
  • getSession().merge(entity);
  • }
  • public List<T> findAll() {
  • Criteria cri = this.createEntityCriteria();
  • cri.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);// 消除重复对象
  • return cri.list();
  • }
  • protected Criteria createEntityCriteria() {
  • return getSession().createCriteria(persistentClass);
  • }
  • }

③ MvnUserDAOImpl.java,该类实现了 MvnUser 实体类的所有持久化方法,代码如下所示。

  • package cn.com.mvn.ssh.demo.dao.hibernate.impl;
  • import java.util.List;
  • import org.hibernate.Criteria;
  • import org.hibernate.criterion.Restrictions;
  • import org.springframework.stereotype.Repository;
  • import org.springframework.transaction.annotation.Transactional;
  • import cn.com.mvn.ssh.demo.dao.IMvnUserDAO;
  • import cn.com.mvn.ssh.demo.dao.hibernate.AbstractDAO;
  • import cn.com.mvn.ssh.demo.entity.MvnUser;
  • import cn.com.mvn.ssh.demo.entity.hibernate.MvnUser4Hibernate;
  • @Repository("userDAO")
  • @Transactional // 标记使用事务,为了方便DAO设置,是临时的,正式事务应该设置在服务层
  • public class MvnUserDAOImpl extends AbstractDAO<Integer, MvnUser4Hibernate> implements IMvnUserDAO {
  • public void addUser(MvnUser user) {
  • MvnUser4Hibernate u = this.convertToMvnUser4Hibernate(user);
  • super.persist(u);
  • }
  • public void update(MvnUser user) {
  • MvnUser4Hibernate u = this.convertToMvnUser4Hibernate(user);
  • super.update(u);
  • }
  • public void deleteUser(MvnUser user) {
  • MvnUser4Hibernate u = this.convertToMvnUser4Hibernate(user);
  • super.delete(u);
  • }
  • public MvnUser findUserById(int id) {
  • return super.getByKey(id);
  • }
  • public MvnUser findUserByUserName(String userName) {
  • Criteria criteria = super.createEntityCriteria();
  • criteria.add(Restrictions.eq("urUserName", userName));
  • return (MvnUser) criteria.uniqueResult();
  • }
  • public List<MvnUser> findUsers() {
  • Criteria criteria = super.createEntityCriteria();
  • return criteria.list();
  • }
  • private MvnUser4Hibernate convertToMvnUser4Hibernate(MvnUser user) {
  • MvnUser4Hibernate u = (MvnUser4Hibernate) this.findUserById(user.getUrId());
  • // 这里不要轻易new一个同已经存在的一样的对象,否则会抛
  • // org.hibernate.NonUniqueObjectException:
  • // a different object with the same identifier value was
  • // already associated withthe session异常
  • if (u == null) {
  • u = new MvnUser4Hibernate();
  • u.setUrId(user.getUrId());
  • }
  • u.setUrAge(user.getUrAge());
  • u.setUrPassword(user.getUrPassword());
  • u.setUrStatus(user.getUrStatus());
  • u.setUrUserName(user.getUrUserName());
  • return u;
  • }
  • }

④ HibernateConfiguration.java,Hibernate 的配置类,描述 Hibernate 的配置信息,代替 hibernate.cfg.xml,代码如下所示。

  • package cn.com.mvn.ssh.demo.dao.hibernate.config;
  • import java.util.Properties;
  • import javax.sql.DataSource;
  • import org.hibernate.SessionFactory;
  • import org.springframework.beans.factory.annotation.Autowired;
  • import org.springframework.context.annotation.Bean;
  • import org.springframework.context.annotation.ComponentScan;
  • import org.springframework.context.annotation.Configuration;
  • import org.springframework.context.annotation.PropertySource;
  • import org.springframework.core.env.Environment;
  • import org.springframework.jdbc.datasource.DriverManagerDataSource;
  • import org.springframework.orm.hibernate4.HibernateTransactionManager;
  • import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
  • import org.springframework.transaction.annotation.EnableTransactionManagement;
  • //配置类
  • @Configuration
  • @EnableTransactionManagement // 要支持事务管理
  • @ComponentScan({ "cn.com.mvn.ssh.demo.dao.hibernate.config" })
  • @PropertySource(value = { "classpath:db.properties" }) // 自动读入的属性文件
  • public class HibernateConfiguration {
  • // 自动注入 Spring的环境对象(上下文)
  • @Autowired
  • private Environment environment;
  • // 创建一个SessionFactory
  • @Bean(name = "sessionFactory")
  • public LocalSessionFactoryBean sessionFactory() {
  • LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
  • // 数据源
  • sessionFactory.setDataSource(dataSource());
  • // 指定数据实体类的包
  • sessionFactory.setPackagesToScan(new String[] { "cn.com.mvn.ssh.demo.entity.hibernate" });
  • // hibernate的属性信息
  • sessionFactory.setHibernateProperties(hibernateProperties());
  • return sessionFactory;
  • }
  • // 初始化数据源对象
  • @Bean(name = "dataSource") // 将当前方法返回的对象,当成普通Bean对象,放入IOC容器中
  • public DataSource dataSource() {
  • DriverManagerDataSource dataSource = new DriverManagerDataSource();
  • // 设置连接数据库的四要素
  • dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
  • dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
  • dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
  • dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
  • return dataSource;
  • }
  • // 将Hibernate除连接数据库之外的配置,封装到Properties
  • private Properties hibernateProperties() {
  • Properties properties = new Properties();
  • properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
  • properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
  • properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
  • properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
  • return properties;
  • }
  • @Bean
  • @Autowired
  • public HibernateTransactionManager transactionManager(SessionFactory s) {
  • HibernateTransactionManager txManager = new HibernateTransactionManager();
  • txManager.setSessionFactory(s);
  • return txManager;
  • }
  • }

⑤ db.properties,描述数据库连接信息和 Hibernate 的一些配置信息,代码如下所示。

jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/mvn_db
jdbc.driverClassName=com.mysql.jdbc.Driver
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto = update

3)编写测试代码

测试代码基于 JUnit,相对比较简单,只有一个类,针对 MvnUserDAOImpl.java 进行测试,另外还有一个 Spring 的配置文件 applicationContext.xml。

需要注意的是,测试的所有代码和资源文件,都分别放在 src/test 目录下对应的子目录中。在 Maven 中具体文件的存放位置是固定的。测试代码和配置文件的内容如下所示。

① TestMvnUserDAOImpl.java 代码如下所示:

  • package cn.com.mvn.ssh.demo.dao.hibernate.impl;
  • import org.junit.After;
  • import org.junit.Before;
  • import org.junit.Test;
  • import org.springframework.context.ApplicationContext;
  • import org.springframework.context.support.ClassPathXmlApplicationContext;
  • import cn.com.mvn.ssh.demo.dao.IMvnUserDAO;
  • import cn.com.mvn.ssh.demo.entity.MvnUser;
  • import cn.com.mvn.ssh.demo.entity.Status;
  • import junit.framework.Assert;
  • public class TestMvnUserDAOImpl {
  • private IMvnUserDAO userDAO;
  • private ApplicationContext ctx = null;
  • @Before
  • public void init() {
  • ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  • userDAO = (IMvnUserDAO) this.ctx.getBean("userDAO");
  • // userDAO = (IMvnUserDAO) this.ctx.getBean(MvnUserDAOImpl.class);
  • }
  • @Test
  • public void testAddUser() {
  • MvnUser user = new MvnUser();
  • user.setUrAge(11);
  • user.setUrPassword("11");
  • user.setUrStatus(Status.ACTIVE.getStatus());
  • user.setUrUserName("userName11");
  • this.userDAO.addUser(user);
  • MvnUser u = this.userDAO.findUserByUserName("userName11");
  • Assert.assertTrue(u != null && u.getUrAge() == 11);
  • this.userDAO.deleteUser(u);
  • }
  • @Test
  • public void testFindUserById() {
  • MvnUser user = this.userDAO.findUserById(1);
  • Assert.assertEquals("zhangsan", user.getUrUserName());
  • }
  • @Test
  • public void testUpdate() {
  • MvnUser user = this.userDAO.findUserById(1);
  • user.setUrAge(99);
  • this.userDAO.update(user);
  • user = this.userDAO.findUserById(1);
  • Assert.assertEquals(99, user.getUrAge());
  • }
  • @After
  • public void destory() {
  • this.userDAO = null;
  • this.ctx = null;
  • }
  • }

② applicationContext.xml 代码如下所示。

  • <?xml version="1.0" encoding="UTF-8"?>
  • <beans xmlns="http://www.springframework.org/schema/beans"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xmlns:mvc="http://www.springframework.org/schema/mvc"
  • xmlns:context="http://www.springframework.org/schema/context"
  • xsi:schemaLocation="http://www.springframework.org/schema/beans
  • http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  • http://www.springframework.org/schema/mvc
  • http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
  • http://www.springframework.org/schema/context
  • http://www.springframework.org/schema/context/spring-context-4.0.xsd">
  • <!--spring自动扫描组件类的包,包括子包和子子包等 -->
  • <context:component-scan
  • base-package="cn.com.mvn.ssh.demo"></context:component-scan>
  • </beans>

4)测试安装发布

右击“工程”,选择 Run As→Maven test 命令,Maven 会自动对 JUnit 写的测试代码进行测试,并且显示测试结果。

右击“工程”,选择 Run As→Maven install 命令,Maven 会自动将工程代码编译,运行完测试代码,通过后,打包成构件,发布到本地仓库。

右击“工程”,选择 Run As→Maven build… 命令,在弹出框的 Goals 输入框中输入 deploy,单击 Run 按钮,Maven 会自动将工程构件发布到指定的私服仓库。需要注意,一定要在 pom.xml 中配置 distributionManagement.

实现 Service 模块

同 DAO 层定义的接口类似,先将 Service 的接口定义好,并且发布成一个单独的构件,在自己的计算机上创建一个新的工程,继承 SpringPOM,集成 DAO 接口的依赖和 Service 接口的依赖,独立进行 Service 的实现代码编写和测试。

因为要对 Service 实现方法进行测试,编码的时候可以面向接口编程。测试的时候,肯定要基于 DAO 的实现才能操作数据库。所以在测试的时候还需要额外添加前面 Hibernate 的 DAO 实现依赖,不过该依赖的 score 是 test,即只在测试的时候有效。详细情况请注意接下来介绍的工程 pom.xml 中的备注。

下面按类似 Hibernate 的 DAO 实现的思路,介绍 Service 的实现模块。

1)配置 pom.xml

同之前一样,创建一个 Maven 工程,工程目录结构如图 3 所示。 

Maven Service项目结构
图 3  Maven Service项目结构

根据本节开始的介绍,需要在 pom.xml 中做如下设置。

  • 配置继承 SpringPOM 构件的信息(里面配置了 Spring 需要的依赖)。
  • 添加 DAO 接口构件和 Service 接口构件的依赖。
  • 添加 Hibernate DAO 实现构件的依赖,作用范围是 test。

请查看如下 pom.xml,注意加粗部分内容和注释,细心的读者会发现里面没有添加 DAO 接口的构件依赖,只添加 Service 接口的构件依赖,同前面介绍的第 2 点要求不符合。

原因是 Service 接口构件内部有配置好对应 DAO 接口构件的依赖,只要在这里配置 Service 接口构件的依赖,Maven 会在加载 Service 接口构件依赖的同时,自动地连带着将 Service 接口构件内部所需要的其他依赖加进来。

pom.xml 内容如下:

  • <project xmlns="http://maven.apache.org/POM/4.0.0"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  • <modelVersion>4.0.0</modelVersion>
  • <!--继承SpringPOM构件 -->
  • <parent>
  • <groupId>cn.com.mvn.pom</groupId>
  • <artifactId>SpringPOM</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • </parent>
  • <groupId>cn.com.mvn.ssh.demo</groupId>
  • <artifactId>MvnSSHDemo.Service.impl</artifactId>
  • <packaging>jar</packaging>
  • <name>MvnSSHDemo.Service.impl</name>
  • <url>http://maven.apache.org</url>
  • <properties>
  • <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  • </properties>
  • <dependencies>
  • <!--Service接口构件依赖 -->
  • <dependency>
  • <groupId>cn.com.mvn.ssh.demo</groupId>
  • <artifactId>MvnSSHDemo.Service</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • </dependency>
  • <!--Hibernate DAO实现构件依赖 -->
  • <dependency>
  • <groupId>cn.com.mvn.ssh.demo.dao.hibernate</groupId>
  • <artifactId>MvnSSHDemo.DAO.Hibernate</artifactId>
  • <version>0.0.1-SNAPSHOT</version>
  • <!--作用范围 -->
  • <scope>test</scope>
  • </dependency>
  • </dependencies>
  • </project>

2) 编写 Service 实现代码

Service 的实现代码相对比较简单,只是要有 Spring 容器管理相关的基础,因为里面用到 Spring 内部的组件注解、依赖注入注解和事务管理注解,详情请看代码和 Spring 相关的资料。

  • package cn.com.mvn.ssh.demo.service.impl;
  • import java.util.List;
  • import org.springframework.beans.factory.annotation.Autowired;
  • import org.springframework.beans.factory.annotation.Qualifier;
  • import org.springframework.stereotype.Service;
  • import org.springframework.transaction.annotation.Propagation;
  • import org.springframework.transaction.annotation.Transactional;
  • import cn.com.mvn.ssh.demo.dao.IMvnUserDAO;
  • import cn.com.mvn.ssh.demo.entity.MvnUser;
  • import cn.com.mvn.ssh.demo.service.IUserService;
  • @Service("userService") // 注册成服务组件
  • @Transactional // 要求启动事务
  • public class UserServiceImpl implements IUserService {
  • @Autowired // 自动根据类型注入
  • @Qualifier("userDAO") // 根据name注入
  • private IMvnUserDAO userDAO;
  • @Transactional(propagation = Propagation.REQUIRED) // 需要進行事务管理
  • public void createUser(MvnUser user) {
  • // 验证输入的用户是否为null
  • if (user == null) {
  • throw new RuntimeException("创建的user不能为null");
  • }
  • // 验证用户名是否有存在
  • MvnUser u = this.userDAO.findUserByUserName(user.getUrUserName());
  • if (u != null) {
  • throw new RuntimeException(u.getUrUserName() + " 已经存在");
  • }
  • this.userDAO.addUser(user);
  • }
  • @Transactional(propagation = Propagation.REQUIRED) // 需要進行事务管理
  • public void editUser(int age, String status, int id) {
  • // 根据id找到以前的用户对象
  • MvnUser user = this.userDAO.findUserById(id);
  • // 判断用户是否存在,不存在抛异常,存在就更新
  • if (user == null) {
  • throw new RuntimeException("id为" + id + "用户不存在");
  • } else {
  • user.setUrAge(age);
  • user.setUrStatus(status);
  • this.userDAO.update(user);
  • }
  • }
  • @Transactional(propagation = Propagation.REQUIRED) // 需要進行事务管理
  • public void deleteUser(int id) {
  • // 根据id找到以前的用户对象
  • MvnUser user = this.userDAO.findUserById(id);
  • // 判断用户是否存在,不存在抛异常,存在就删除
  • if (user == null) {
  • throw new RuntimeException("id为" + id + "用户不存在");
  • } else {
  • this.userDAO.deleteUser(user);
  • }
  • }
  • @Transactional(readOnly = true) // 只读,不需要进行事务管理
  • public MvnUser searchUser(int id) {
  • MvnUser user = null;
  • user = this.userDAO.findUserById(id);
  • return user;
  • }
  • @Transactional(readOnly = true) // 只读,不需要进行事务管理
  • public MvnUser searchUser(String userName) {
  • MvnUser user = null;
  • user = this.userDAO.findUserByUserName(userName);
  • return user;
  • }
  • @Transactional(readOnly = true) // 只读,不需要进行事务管理
  • public List<MvnUser> searchUsers() {
  • List<MvnUser> userList = null;
  • userList = this.userDAO.findUsers();
  • return userList;
  • }
  • }

3)编写 Service 的测试案例代码和必需的配置资源文件

因为测试代码的测试环境是依赖 Spring 容器的,所以测试部分的内容除了有针对 UserServiceImpl.java 的测试案例类之外,还需要配置一个 applicationContext.xml。而且还要注意,不管是测试类还是测试资源,都需要放在 src/test 的对应子目录下。

① TestUserServiceImpl.java 代码如下所示:

  • package cn.com.mvn.ssh.demo.service.impl;
  • import java.util.List;
  • import org.junit.After;
  • import org.junit.Before;
  • import org.junit.Test;
  • import org.springframework.context.ApplicationContext;
  • import org.springframework.context.support.ClassPathXmlApplicationContext;
  • import cn.com.mvn.ssh.demo.entity.MvnUser;
  • import cn.com.mvn.ssh.demo.entity.Status;
  • import cn.com.mvn.ssh.demo.service.IUserService;
  • import junit.framework.Assert;
  • public class TestUserServiceImpl {
  • private IUserService userService;
  • private ApplicationContext ctx = null;
  • @Before
  • public void init() {
  • this.ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
  • this.userService = (IUserService) ctx.getBean("userService");
  • }
  • @Test
  • public void testCreateUser() {
  • MvnUser user = new MvnUser();
  • user.setUrAge(11);
  • user.setUrPassword("11");
  • user.setUrStatus(Status.ACTIVE.getStatus());
  • user.setUrUserName("service1");
  • this.userService.createUser(user);
  • MvnUser u = this.userService.searchUser("service1");
  • boolean bool = u != null && u.getUrAge() == 11 && u.getUrStatus().equals(Status.ACTIVE.getStatus());
  • Assert.assertTrue(bool);
  • // 删除用户
  • this.userService.deleteUser(u.getUrId());
  • }
  • @Test
  • public void testEditUser() {
  • MvnUser user = new MvnUser();
  • user.setUrAge(11);
  • user.setUrPassword("11");
  • user.setUrStatus(Status.ACTIVE.getStatus());
  • user.setUrUserName("service1");
  • this.userService.createUser(user);
  • MvnUser u = this.userService.searchUser("service1");
  • this.userService.editUser(88, Status.INACTIVE.getStatus(), u.getUrId());
  • u = this.userService.searchUser("service1");
  • Assert.assertTrue(u.getUrAge() == 88 && u.getUrStatus().equals(Status.INACTIVE.getStatus()));
  • this.userService.deleteUser(u.getUrId());
  • }
  • @Test
  • public void testDeleteUser() {
  • MvnUser user = new MvnUser();
  • user.setUrAge(11);
  • user.setUrPassword("11");
  • user.setUrStatus(Status.ACTIVE.getStatus());
  • user.setUrUserName("service1");
  • this.userService.createUser(user);
  • MvnUser u = this.userService.searchUser("service1");
  • this.userService.deleteUser(u.getUrId());
  • MvnUser u2 = this.userService.searchUser(u.getUrId());
  • Assert.assertTrue(u != null && u2 == null);
  • }
  • @Test
  • public void testSearchUserById() {
  • MvnUser user = this.userService.searchUser(1);
  • Assert.assertNotNull(user);
  • }
  • @Test
  • public void testSearchUserByUserName() {
  • MvnUser user = this.userService.searchUser("zhangsan");
  • Assert.assertNotNull(user);
  • }
  • @Test
  • public void testSearchUsers() {
  • List<MvnUser> userList = this.userService.searchUsers();
  • Assert.assertTrue(userList != null && userList.size() > 0);
  • }
  • @After
  • public void destory() {
  • this.userService = null;
  • this.ctx = null;
  • }
  • }

2)applicationContext.xml 代码如下所示:

  • <?xml version="1.0" encoding="UTF-8"?>
  • <beans xmlns="http://www.springframework.org/schema/beans"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xmlns:mvc="http://www.springframework.org/schema/mvc"
  • xmlns:context="http://www.springframework.org/schema/context"
  • xsi:schemaLocation="http://www.springframework.org/schema/beans
  • http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  • http://www.springframework.org/schema/mvc
  • http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
  • http://www.springframework.org/schema/context
  • http://www.springframework.org/schema/context/spring-context-4.0.xsd">
  • <context:component-scan base-package="cn.com.mvn.ssh.demo"/>
  • </beans>

4. 测试安装和发布

这里的测试安装和发布同 Hibernate DAO 实现里面的一样。右击“工程”,选择 Run As→Maven test 命令。

由于篇幅有限,请看下一节《Maven搭建SSH框架(二)》继续阅读。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门