Maven搭建SSM(SpringMVC+Spring+MyBatis)框架入门教程(超级详细)
前面介绍了基于 Maven 使用 Struts+Spring+Hibernate(SSH)框架,模仿企业级应用的开发过程,实现了用户的 CRUD 功能。接下来再使用 SpringMVC+Spring+MyBatis(SSM)框架,同样模仿企业级应用的开发过程,实现用户的 CRUD 功能。
目的很明确,让用户能直接基于 SSH 和 SSM 两个流行框架进行项目开发,减少学习到使用之间的转换过程。
基于 SSM 框架,用户可以独立搭建 SpringMVC、Spring 和 MyBatis 三个基本的 POM 构件。其中,Spring 的 POM 在前面的样例中已经搭建好了,叫 SpringPOM 构件。本节主要介绍 SpringMVC 和 MyBatis 构件 POM。
另外,SpringMVC 封装的是 Web 层应用,底层使用的是 Jsp/Servlet 技术,所以在 SpringMVC POM 中需要加入 Jsp/Servlet 相关的依赖。
因为在用户 CRUD 样例中需要有 JSON 的响应,而且 JSON 的请求和响应在实际项目中也很普通,所以在 SpringMVC POM 中也添加了 JSON 的相关依赖。
pom.xml 的详细内容如下:
MyBatis4MySQLPOM 的 pom.xml 详细内容如下:
注意,因为 SpringPOM 是 pom 构件,所以在应用它的依赖的时候,需要指定 type 为 pom,详细情况查看 pom.xml。
pom.xml 内容如下:
MyBatisConfiguration.java,配置 MyBatis 的基本信息,包括数据库连接信息。
为了完成它,同时避免 MyBatisDAO 集成到系统项目中的改动,添加了一个供 MvnUserDAOImpl 测试的服务类。里面不加业务逻辑,直接调用 DAO 接口中的方法,只是在类上面添加了事务管理。所以测试代码主要有以下几个部分。
1)IMvnUserService.java,临时测试用的服务层接口。
因为前面 MyBatis DAO 的实现使用的是 MyBatis3 的新特征:接口和映射文件自动绑定,没有自己独立实现 DAO 类,更没有在 Spring 容器中配置 DAO Bean、指定 Bean 的名称。
MvnSSMDemo.Service.Impl 工程的实现步骤如下。
pom.xml 的代码如下所示:
UserServiceImpl.java,实现用户的 CRUD 功能。
所以要理解后面的代码实现需要有 SpringMVC 4.x 的开发基础,建议没有接触过的读者先参考 SpringMVC 4.0 注解开发 Web 应用的相关资料。
Web 层基于框架的开发流程可以抽象成以下几个部分。
基于 SpringMVC 4.x 用零配置方式开发 Web 层也是同样的流程。只是因为是零配置方式,也就看不到配置文件相关的代码,但是以前配置文件描述的信息肯定还是要描述的,只是用注解或其他方式体现。
对 SpringMVC Web 的实现思路有了基本了解后,接下来就开始实现 SSMDemo 的 Web 层功能。
单击 Maven 中的创建 Maven Project 的选项,如图 1 所示。
图 1 创建 Maven Project
单击 Next 按钮,进入 Archetype 的选择界面,选择 webapp-javaee6 插件,如图 2 所示。
图 2 选择webapp-javaee6
单击 Next 按钮,进入类似如图 3 所示的界面,在界面中输入工程的 Group Id、Artifact Id、Package,选择一个 Version 版本。
图 3 输入项目坐标
单击 Finish 按钮,创建 Web 工程,项目就创建好了。
所以 pom.xml 中主要体现在对 SpringPOM 父 pom 构件的继承和对后面四个构件的依赖。
另外,为了发布到 Web 服务器上运行,需要配置 cargo-maven2-plugin 插件。
pom.xml 详细内容如下:
1)SpringMVCIntializer.java。在 Web 容器中初始化 DispatcherServlet。Web 服务器启动时会自己调用初始化,代替以前在 web.xml 中配置 DispatcherServlet 的 servlet 和 servlet-mapping。
具体操作都是:右击“工程”,选择 Run As→Maven test→install→deploy 命令。
发布好后,在 Tomcat 的 webapps 发布目录下会有 MvnSSMDemo.war 文件,启动 Tomcat 就可以自动发布 Web 应用。
但是为了方便管理,有必要创建一个工程,将前面独立实现的各个模块管理起来。这样每次编译、测试、安装和发布的时候都能基于 Maven 实现自动同步。
整合 SSM 模块的具体步骤如下。
前面介绍的是基于编辑器直接编写 pom.xml,这里介绍基于 MyEclipse 的图形化界面,基于向导界面修改 pom.xml(添加模块)。
通过单击不同标签选择打开方式,如图 4 所示。
图 4 pom.xml
如果选择的是 pom.xml,显示的是 pom.xml 源文件,可以按以前的方式基于源代码修改 pom.xml。现在选择 Overview 标签,显示界面如图 5 所示。
图 5 可视化pom.xml
单击 Modules 范围内的 Add… 按钮就可以通过图形界面选择需要添加的模块。保存后就完成了模块的集成。
目的很明确,让用户能直接基于 SSH 和 SSM 两个流行框架进行项目开发,减少学习到使用之间的转换过程。
创建公共 POM
为了使公司项目有正常的沉淀和重用,先创建基于 SSM 框架开发的公共 POM 构件,以免以后项目和开发人员的重复搭建。基于 SSM 框架,用户可以独立搭建 SpringMVC、Spring 和 MyBatis 三个基本的 POM 构件。其中,Spring 的 POM 在前面的样例中已经搭建好了,叫 SpringPOM 构件。本节主要介绍 SpringMVC 和 MyBatis 构件 POM。
1. SpringMVC POM
因为 SpringMVC 同 Spring 已经在 SpringPOM 配置好了,现在只需继承 SpringPOM。另外,SpringMVC 封装的是 Web 层应用,底层使用的是 Jsp/Servlet 技术,所以在 SpringMVC POM 中需要加入 Jsp/Servlet 相关的依赖。
因为在用户 CRUD 样例中需要有 JSON 的响应,而且 JSON 的请求和响应在实际项目中也很普通,所以在 SpringMVC POM 中也添加了 JSON 的相关依赖。
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>
2. MyBatis POM
考虑到 MyBatis 最终要同 Spring 集成,并且是基于 MySQL 数据库。在 MyBatis 的 POM 中需要定义如下关键的依赖。- MyBatis 构件。
- MyBatis 同 Spring 集成的构件。
- 连接池构件。
- MySQL 数据库驱动构件。
MyBatis4MySQLPOM 的 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>MyBatis4MySQLPOM</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <name>MyBatis4MySQLPOM</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 3.6.5.Final,3.3.2.GA --> <project.build.mybatis.version>3.4.0</project.build.mybatis.version> </properties> <dependencies> <!-- MyBatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${project.build.mybatis.version}</version> </dependency> <!-- MyBatis同Spring的集成构件 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> <!-- Datasource连接池 --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <!-- MySQL数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</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>
实现MyBatis DAO模块
因为它同 SSH 框架实现的用户 CRUD 功能一样,所以在 SSM 中,DAO 层的接口同 SSH 中的 DAO 层接口是一样的,这里就不再重新定义了,直接重用前面样例中创建的 MvnSSHDemo.DAO 构件。这里直接创建 MyBatis 的 DAO 实现部分工程,对 DAO 层接口基于 MyBatis 进行实现。1. 创建 MvnSSMDemo.DAO.MyBatis 工程
MvnSSMDemo.DAO.MyBatis 的工程中,只需创建 Maven 的普通 Java 工程就行。2. 编写 pom.xml
MvnSSMDemo.DAO.MyBatis 是基于 MyBatis 实现的,所以 pom 先继承 MyBatis4MySQLPOM,然后考虑到同 Spring 集成,并且实现的是 MvnSSHDemo.DAO 中定义的接口,所以需要添加 SpringPOM 和 MvnSSHDemo.DAO 的构件依赖。注意,因为 SpringPOM 是 pom 构件,所以在应用它的依赖的时候,需要指定 type 为 pom,详细情况查看 pom.xml。
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> <parent> <groupId>cn.com.mvn.pom</groupId> <artifactId>MyBatis4MySQLPOM</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>cn.com.mvn.ssm.demo</groupId> <artifactId>MvnSSMDemo.DAO.MyBatis</artifactId> <packaging>jar</packaging> <name>MvnSSMDemo.DAO.MyBatis</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!--SpringPOM构件依赖 --> <dependency> <groupId>cn.com.mvn.pom</groupId> <artifactId>SpringPOM</artifactId> <version>0.0.1-SNAPSHOT</version> <type>pom</type> </dependency> <!--DAO接口依赖 --> <dependency> <groupId>cn.com.mvn.ssh.demo</groupId> <artifactId>MvnSSHDemo.DAO</artifactId> <version>0.0.1-SNAPSHOT</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>
3. 编写实现代码
基于 MyBatis 实现的 DAO 持久层,需要写以下代码。MyBatisConfiguration.java,配置 MyBatis 的基本信息,包括数据库连接信息。
package cn.com.mvn.ssm.demo.dao.mybatis; import java.io.IOException; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; import org.apache.ibatis.io.Resources; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @Configuration // 允许注解 @ComponentScan(basePackages = { "cn.com.mvn" }) // 注解类的基本包 public class MyBatisConfiguration { // 将方法结果按Bean管理,别的地方可以按类型进行装配 @Bean(autowire = Autowire.BY_TYPE) public DataSource dataSource() { // 创建数据源 BasicDataSource dataSource = new BasicDataSource(); Properties prop = null; try { // 读资源文件中的数据库连接信息 prop = Resources.getResourceAsProperties("db.properties"); String driverClass = prop.getProperty("jdbc.driverClassName"); String jdbcUrl = prop.getProperty("jdbc.url"); String uname = prop.getProperty("jdbc.username"); String password = prop.getProperty("jdbc.password"); dataSource.setDriverClassName(driverClass); dataSource.setUrl(jdbcUrl); dataSource.setUsername(uname); dataSource.setPassword(password); dataSource.setRemoveAbandonedTimeout(60); dataSource.setRemoveAbandoned(true); dataSource.setLogAbandoned(false); dataSource.setMinIdle(10); dataSource.setMinEvictableIdleTimeMillis(30000); dataSource.setMaxWait(10); dataSource.setInitialSize(2); dataSource.setMaxActive(10); dataSource.setTimeBetweenEvictionRunsMillis(30000); dataSource.setValidationQuery("SELECT 1"); dataSource.setTestOnReturn(false); dataSource.setTestOnBorrow(true); dataSource.setTestWhileIdle(true); } catch (IOException e) { e.printStackTrace(); } return dataSource; } // 将返回结果对象定义成一个name为sqlSessionFactory的bean @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean getSqlSesssionFactoryBean() { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource()); /* * ClassPathResource re = new ClassPathResource("myBatisConfig.xml"); * bean.setConfigLocation(re); */ ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] resources; try { // 设置MyBatis视图映射文件的路径 resources = resolver.getResources("classpath:cn/com/mvn/ssm/demo/dao/mybatis/entity/*Mapper.xml"); bean.setMapperLocations(resources); } catch (IOException e) { e.printStackTrace(); } return bean; } // 创建Mapper和接口的绑定配置器Bean,名称为mapper @Bean(name = "mapper", autowire = Autowire.BY_NAME) public MapperScannerConfigurer getMapperScannerConfigurer() { MapperScannerConfigurer conf = new MapperScannerConfigurer(); // 设置要绑定的接口基本包路径 conf.setBasePackage("cn.com.mvn.ssm.demo.dao.mybatis.impl"); // 设置连接数据库的sqlSessionFactory conf.setSqlSessionFactoryBeanName("sqlSessionFactory"); return conf; } }IMvnDAO4MyBatis.java,继承前面定义的 DAO 接口,完成 MyBatis 接口定义。
package cn.com.mvn.ssm.demo.dao.mybatis.impl; import cn.com.mvnb.ssh.demo.dao.IMvnUserDAO; public interface IMvnUserDAO4MyBatis extends IMvnUserDAO { }MvnUserMapper.xml,MvnUser 实体的映射文件。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.com.mvn.ssm.demo.dao.mybatis.impl.IMvnUserDAO4MyBatis"> <resultMap type="cn.com.mvn.ssh.demo.entity.MvnUser" id="UserMap"> <id column="ur_id" property="urId" /> <result column="ur_user_name" property="urUserName" /> <result column="ur_password" property="urPassword" /> <result column="ur_age" property="urAge" /> <result column="ur_status" property="urStatus" /> </resultMap> <insert id="addUser" useGeneratedKeys="true" keyProperty="urId" parameterType="cn.com.mvn.ssh.demo.entity.MvnUser"> insert into mvn_user (ur_user_name,ur_password,ur_age,ur_status) values (#{urUserName},#{urPassword},#{urAge},#{urStatus}) </insert> <update id="update" parameterType="cn.com.mvn.ssh.demo.entity.MvnUser"> update mvn_user set ur_age=#{urAge},ur_status=#{urStatus} where ur_id=#{urId} </update> <delete id="deleteUser" parameterType="cn.com.mvn.ssh.demo.entity.MvnUser"> delete from mvn_user where ur_id=#{urId} </delete> <select id="findUserById" resultMap="UserMap" parameterType="int"> select * from mvn_user where ur_id=#{id} </select> <select id="findUserByUserName" resultMap="UserMap" parameterType="java.lang.String"> select * from mvn_user where ur_user_name=#{userName} </select> <select id="findUsers" resultMap="UserMap"> select * from mvn_user order by ur_id </select> </mapper>db.properties,数据库连接信息配置文件。
jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/mvn_db
jdbc.driverClassName=com.mysql.jdbc.Driver
4. 编写测试代码
测试代码是 TestMvnUserDAOImp.java 类,里面基于 JUnit 对 DAO 接口中的每个方法做了测试。为了完成它,同时避免 MyBatisDAO 集成到系统项目中的改动,添加了一个供 MvnUserDAOImpl 测试的服务类。里面不加业务逻辑,直接调用 DAO 接口中的方法,只是在类上面添加了事务管理。所以测试代码主要有以下几个部分。
1)IMvnUserService.java,临时测试用的服务层接口。
package cn.com.mvn.ssm.demo.mybatis.service; import java.util.List; import cn.com.mvn.ssh.demo.entity.MvnUser; public interface IMvnUserService { /** * 在数据库中,添加一个新的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(); }2)MvnUserServiceImpl.java,临时测试的服务层实现类。
package cn.com.mvn.ssm.demo.mybatis.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; 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.ssm.demo.mybatis.service.IMvnUserService; @Service("userService") @Transactional public class MvnUserServiceImpl implements IMvnUserService { @Autowired private IMvnUserDAO userDAO; public void addUser(MvnUser user) { this.userDAO.addUser(user); } public void update(MvnUser user) { this.userDAO.update(user); } public void deleteUser(MvnUser user) { this.userDAO.deleteUser(user); } public MvnUser findUserById(int id) { return this.userDAO.findUserById(id); } public MvnUser findUserByUserName(String userName) { return this.userDAO.findUserByUserName(userName); } public List<MvnUser> findUsers() { return this.userDAO.findUsers(); } }3)TestMvnUserDAOImpl.java,基于 JUnit 的单元测试类。
package cn.com.mvn.ssm.demo.dao.mybatis.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.ssm.demo.mybatis.service.IMvnUserService; import junit.framework.Assert; public class TestMvnUserDAOImpl { private ApplicationContext ctx; private IMvnUserService userService; @Before public void init() { this.ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); this.userService = (IMvnUserService) ctx.getBean("userService"); } @Test public void testAddUser() { MvnUser user = new MvnUser(); user.setUrAge(11); user.setUrPassword("11"); user.setUrStatus(Status.ACTIVE.getStatus()); user.setUrUserName("myBatisUserName"); this.userService.addUser(user); user = this.userService.findUserByUserName("myBatisUserName"); Assert.assertTrue(user != null && user.getUrAge() == 11); this.userService.deleteUser(user); } @Test public void testDeleteUser() { MvnUser user = new MvnUser(); user.setUrAge(11); user.setUrPassword("11"); user.setUrStatus(Status.ACTIVE.getStatus()); user.setUrUserName("myBatisUserName"); this.userService.addUser(user); user = this.userService.findUserByUserName("myBatisUserName"); this.userService.deleteUser(user); MvnUser u = this.userService.findUserByUserName("myBatisUserName"); Assert.assertTrue(user != null && u == null); } @Test public void testFindUserById() { MvnUser user = this.userService.findUserById(1); Assert.assertEquals(user.getUrUserName(), "zhangsan"); } @Test public void testFindByUserName() { MvnUser user = this.userService.findUserByUserName("zhangsan"); Assert.assertEquals("123", user.getUrPassword()); } @Test public void testFindUsers() { List<MvnUser> userList = this.userService.findUsers(); Assert.assertTrue(userList.size() > 0); } @After public void destory() { this.userService = null; this.ctx = null; } }4)applicationContext.xml,测试的时候,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: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" /> </beans>
5. 测试、安装和发布
同前面的类似。实现 Spring 的 Service 层模块
SSM 中的 Service 层实现同 SSH 框架中的 Service 层实现一样。唯一不同的是 DAO 的注入只能用 @Autowired 根据类型注入,不能用 @Qualifier 根据名称注入。因为前面 MyBatis DAO 的实现使用的是 MyBatis3 的新特征:接口和映射文件自动绑定,没有自己独立实现 DAO 类,更没有在 Spring 容器中配置 DAO Bean、指定 Bean 的名称。
MvnSSMDemo.Service.Impl 工程的实现步骤如下。
1. 创建 MvnSSMDemo.Service.Impl 工程
只需创建 Maven 的简单 Java 工程。2. 编写 pom.xml 骨架文件
pom 内容主要体现在以下几个方面。- 继承 SpringPOM 公共构件,避免重复配置对 Spring 相关构件的依赖。
- 添加 MvnSSHDemo.DAO 接口依赖和 MvnSSHDemo.Service 接口依赖。
- 为了方便测试,添加 MvnSSMDemo.DAO.MyBatis 依赖,scope 范围是 test。
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> <parent> <groupId>cn.com.mvn.pom</groupId> <artifactId>SpringPOM</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>cn.com.mvn.ssm.demo</groupId> <artifactId>MvnSSMDemo.Service.Impl</artifactId> <packaging>jar</packaging> <name>MvnSSMDemo.Service.Impl</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.ssh.demo</groupId> <artifactId>MvnSSHDemo.Service</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>cn.com.mvn.ssm.demo</groupId> <artifactId>MvnSSMDemo.DAO.MyBatis</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>test</scope> </dependency> </dependencies> </project>
3. 编写实现代码
Service 层主要实现用户对象的 CRUD 功能,同 SSH 中的 Service 层的代码类似,唯一不同的是,对 DAO 对象的注入只能用 byType 的自动注入,不能用 byName。Service 层的内容如下。UserServiceImpl.java,实现用户的 CRUD 功能。
package cn.com.mvn.ssh.demo.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; 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; //@Configuration @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; } }
4. 编写测试代码
MvnSSMDemo.Service.Impl 的测试代码有两个。1)TestUserServiceImpl.java
实现测试 UserServiceImpl.java 的 JUnit 代码,内容如下所示: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
测试时要初始化 Spring 容器。因为只在测试起作用,所以该文件要同前面的 TestUserServiceImpl.java 代码一样,放在 src/test 的对应子目录下,代码如下所示:<?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" /> </beans>
5. 测试安装和发布
右击“工程”,选择 Run As→Maven test→install→deploy 命令完成测试安装和发布,发布完成后,Archiva 私服上可以看到 MvnSSMDemo.Service.Impl 的构件。实现 SpringMVC Web 模块
用户 CRUD 模块的 SSM Web 层实现,这里采用的是 SpringMVC 4.x 版本,用的是零配置方式实现的。所以要理解后面的代码实现需要有 SpringMVC 4.x 的开发基础,建议没有接触过的读者先参考 SpringMVC 4.0 注解开发 Web 应用的相关资料。
Web 层基于框架的开发流程可以抽象成以下几个部分。
- 在 web.xml 中配置框架的拦截入口,可能是过滤器,也可能是 servlet。
- 开发显示层代码一般是 jsp 页面。
- 开发控制层代码,实现接收请求数据,调用 service 处理请求数据,返回结果 view 层的标记。
- 通过配置文件描述框架运行时,对请求的处理代码的对应关系和页面转换流程。
基于 SpringMVC 4.x 用零配置方式开发 Web 层也是同样的流程。只是因为是零配置方式,也就看不到配置文件相关的代码,但是以前配置文件描述的信息肯定还是要描述的,只是用注解或其他方式体现。
对 SpringMVC Web 的实现思路有了基本了解后,接下来就开始实现 SSMDemo 的 Web 层功能。
1. 创建 Maven 的 Web 工程
前面大部分工程都是基于 Maven 的普通 Java 工程。这里要基于创建 Web 应用的插件创建 Web 工程,详细过程如下。单击 Maven 中的创建 Maven Project 的选项,如图 1 所示。
图 1 创建 Maven Project
单击 Next 按钮,进入 Archetype 的选择界面,选择 webapp-javaee6 插件,如图 2 所示。
图 2 选择webapp-javaee6
单击 Next 按钮,进入类似如图 3 所示的界面,在界面中输入工程的 Group Id、Artifact Id、Package,选择一个 Version 版本。
图 3 输入项目坐标
单击 Finish 按钮,创建 Web 工程,项目就创建好了。
2. 编写和完善 pom.xml
用户 CRUD 的模块实现,需要有 Spring 和 Spring web,Spring webmvc 的相关 jar 包,同时还需要在前面阶段开发的 MvnSSHDAO.DAO 和 MvnSSHService.Service 定义的接口上进行开发,MvnSSMDAO.MyBatis 和 MvnSSMService.Service.Impl 的实现基础上进行测试。所以 pom.xml 中主要体现在对 SpringPOM 父 pom 构件的继承和对后面四个构件的依赖。
另外,为了发布到 Web 服务器上运行,需要配置 cargo-maven2-plugin 插件。
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> <parent> <groupId>cn.com.mvn.pom</groupId> <artifactId>SpringMVCPOM</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>cn.com.mvn.ssm.demo</groupId> <artifactId>MvnSSMDemo.SpringMVC</artifactId> <packaging>war</packaging> <name>MvnSSMDemo.SpringMVC</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>cn.com.mvn.ssh.demo</groupId> <artifactId>MvnSSHDemo.Service</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <!-- 接口和实现 --> <dependency> <groupId>cn.com.mvn.ssm.demo</groupId> <artifactId>MvnSSMDemo.Service.Impl</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>cn.com.mvn.ssm.demo</groupId> <artifactId>MvnSSMDemo.DAO.MyBatis</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>cn.com.mvn.ssh.demo</groupId> <artifactId>MvnSSHDemo.DAO</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <!-- Cargo插件 --> <plugin> <!-- 指定插件名称及版本号 --> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <version>1.4.8</version> <configuration> <wait>true</wait> <!--是否说明,操作start、stop等后续操作必须等前面操作完成才能继续 --> <container> <!-- 容器的配置 --> <containerId>tomcat7x</containerId> <!-- 指定tomcat版本 --> <type>installed</type> <!-- 指定类型:standalone, installed等 --> <home>C:\java\servers\apache-tomcat-7.0.69_64</home> <!-- 指定Tomcat的位置,即catalina.home --> </container> <configuration> <!-- 具体的配置 --> <type>existing</type> <!-- 类型,existing:存在 --> <home>C:\java\servers\apache-tomcat-7.0.69_64</home> <!-- Tomcat的位置,即catalina.home --> </configuration> <deployables> <!-- 部署设置 --> <deployable> <!-- 部署的War包名等 --> <groupId>cn.com.mvn.ssm.demo</groupId> <artifactId>MvnSSMDemo.SpringMVC</artifactId> <type>war</type> <properties> <context>MvnSSMDemo</context> <!-- 部署路径 --> </properties> </deployable> </deployables> <deployer> <!-- 部署配置 --> <type>installed</type> <!-- 类型 --> </deployer> </configuration> <executions> <!-- 执行的动作 --> <execution> <id>verify-deployer</id> <phase>install</phase> <!-- 解析install --> <goals> <goal>deployer-deploy</goal> </goals> </execution> <execution> <id>clean-deployer</id> <phase>clean</phase> <goals> <goal>deployer-undeploy</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <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>
3. 编写实现代码
SpringMVC Web 的代码列表和对应的作用描述如下。1)SpringMVCIntializer.java。在 Web 容器中初始化 DispatcherServlet。Web 服务器启动时会自己调用初始化,代替以前在 web.xml 中配置 DispatcherServlet 的 servlet 和 servlet-mapping。
package cn.com.mvn.ssm.demo.web.configuration; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; //继承初始化父类,让web服务器能自动识别,初始化SpringMVC Servlet入口组件 //代替在web.xml中配置org.springframework.web.servlet.DispatcherServlet public class SpringMVCInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { // 加载SpringMVC的基本配置类 return new Class[] { SpringMVCConfiguration.class }; } @Override protected Class<?>[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { // 指定SpringMVC的mapping url-pattern return new String[] { "/" }; } }2)SpringMVCConfiguration.java。完成 SpringMVC 框架运行的基本信息配置,包括视图转换器、类型转换器、多国语言的资源文件、请求路径匹配和不被 SpringMVC 框架拦截的请求等。
package cn.com.mvn.ssm.demo.web.configuration; import java.util.ArrayList; import java.util.List; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration @EnableWebMvc // 支持SpringMVC @ComponentScan(basePackages = "cn.com.mvn") // SpringMVC自动扫描组件类的基本包 public class SpringMVCConfiguration extends WebMvcConfigurerAdapter { @Override public void configureViewResolvers(ViewResolverRegistry registry) { // 注册视图转换器 InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView.class); viewResolver.setPrefix("/"); viewResolver.setSuffix(".jsp"); registry.viewResolver(viewResolver); } /* * Configure ResourceHandlers to serve static resources like CSS/ Javascript * etc... * */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 设置不需要经过SpringMVC框架过滤的资源,比如js css 和 images等 registry.addResourceHandler("/static/**").addResourceLocations("/static/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); } /* * Configure Converter to be used. In our example, we need a converter to * convert string values[Roles] to UserProfiles in newUser.jsp */ @Override public void addFormatters(FormatterRegistry registry) { // registry.addConverter(roleToUserProfileConverter); } /** * Configure MessageSource to lookup any validation/error message in * internationalized property files */ @Bean public MessageSource messageSource() { // 添加资源文件(多国语言) ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("messages"); return messageSource; } /** * Optional. It's only required when handling '.' in @PathVariables which * otherwise ignore everything after last '.' in @PathVaidables argument. It's a * known bug in Spring [https://jira.spring.io/browse/SPR-6164], still present * in Spring 4.1.7. This is a workaround for this issue. */ @Override public void configurePathMatch(PathMatchConfigurer matcher) { matcher.setUseRegisteredSuffixPatternMatch(true); } }3)Message.java。定义 VO 类,封装页面提示信息,主要是 id 和 message。
package cn.com.mvn.ssm.demo.web.vo; public class Message { private String code; private String message; public Message(String message) { super(); this.message = message; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }4)UserController.java。实现用户 CRUD 的所有控制逻辑代码,包括请求映射注解的描述。
package cn.com.mvn.ssm.demo.web.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import cn.com.mvn.ssh.demo.entity.MvnUser; import cn.com.mvn.ssh.demo.service.IUserService; import cn.com.mvn.ssm.demo.web.vo.Message; @Controller("userController") @RequestMapping("/user") public class UserController { @Autowired @Qualifier("userService") private IUserService userService; @RequestMapping("/add") @ResponseBody public Message addUser(MvnUser user) { Message msg = new Message("添加成功"); try { this.userService.createUser(user); } catch (Exception e) { e.printStackTrace(); msg.setMessage("添加失败:" + e.getMessage()); } return msg; } @RequestMapping("/delete") @ResponseBody public Message deleteUser(int id) { Message msg = new Message("删除成功"); try { this.userService.deleteUser(id); } catch (Exception e) { e.printStackTrace(); msg.setMessage("删除失败:" + e.getMessage()); } return msg; } @RequestMapping("/edit") @ResponseBody public Message editUser(@RequestParam("status") String status, @RequestParam("age") int age, @RequestParam("id") int id) { Message msg = new Message("修改成功"); try { this.userService.editUser(age, status, id); } catch (Exception e) { e.printStackTrace(); msg.setMessage("修改失败:" + e.getMessage()); } return msg; } @RequestMapping("/searchUser") @ResponseBody public MvnUser searchUser(@RequestParam("id") int id) { MvnUser user = this.userService.searchUser(id); return user; } @RequestMapping("/searchUsers") public ModelAndView searchUsers() { ModelAndView mv = new ModelAndView(); mv.setViewName("userList"); mv.addObject("userList", this.userService.searchUsers()); return mv; } }5)index.jsp。CRUD 的框架页面,里面包含 CRUD 的操作按钮和内嵌用户列表的 Div,还有每个操作对应的 JS 代码。
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>测试用户CRUD操作</title> <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script> <script type="text/javascript"> $(document).ready(function() { // 页面加载完后,自动发searchUsersServlet请求,加载到userListDiv中显示 $("#userListDiv").load("user/searchUsers"); }); // 新增 按钮事件触发函数 function toAdd() { // 获取addForm中的请求信息 var _data = $("#addForm").serialize(); //alert(_data); // 发添加新用户的Ajax请求 $.ajax({ type : 'post', url : 'user/add', data : _data, dataType : 'json', // 指定返回数据的格式:json success : function(msg) { alert(msg.message); // 更新最新的用户列表信息 $("#userListDiv").load("user/searchUsers"); } }); } function toEdit() { var _data = $("#editForm").serialize(); alert(_data); $.ajax({ type : 'post', url : 'user/edit', data : _data, dataType : 'json', success : function(msg) { alert(msg.message); $("#userListDiv").load("user/searchUsers"); } }); } function toDelete() { var chks = $("input[name='checkbox']:checked"); if (chks.length == 0) { alert("请选择要删除的用户"); } else if (chks.length > 1) { alert("一次只能删除一个用户"); } else { var to = confirm("您确定要删除选中的用户?"); if (to) { var _data = "id=" + chks.val(); $.ajax({ type : 'post', data : _data, url : 'user/delete', dataType : 'json', success : function(msg) { alert(msg); $("#userListDiv").load("user/searchUsers"); } }); } } } function toShowAdd() { $("#LayerAdd").show(1000); } function toShowEdit() { //alert($("input[name='checkbox']:checked").length); var chks = $("input[name='checkbox']:checked"); if (chks.length == 0) { alert("请选择要编辑的用户"); } else if (chks.length > 1) { alert("一次只能修改一个用户"); } else { var _data = "id=" + chks.val(); $.ajax({ type : 'post', data : _data, url : 'user/searchUser', dataType : 'json', //contentType:'application/json;charset=UTF-8', success : function(msg) { $("#editForm #id").val(msg.urId); $("#editForm #userName").val(msg.urUserName); $("#editForm #age").val(msg.urAge); $("#editForm #status").val(msg.urStatus); //alert($("#editForm #age").val()); $("#LayerEdit").show(1000); } }); } } function toCloseAdd() { $("#LayerAdd").hide(1000); } function toCloseEdit() { $("#LayerEdit").hide(1000); } </script> <style type="text/css"> <!-- .STYLE2 { color: #000000 } #LayerAdd { position: absolute; left: 113px; top: 183px; width: 434px; height: 193px; z-index: 1; background-color: #99FFFF; display: none; } #LayerEdit { position: absolute; left: 113px; top: 183px; width: 434px; height: 193px; z-index: 1; background-color: #99FFFF; display: none; } --> </style> </head> <body> <div id="LayerAdd"> <form name="addForm" name="addForm" id="addForm" method="post" action=""> <table width="98%" border="0" align="center" cellpadding="0" cellspacing="0"> <tr> <td colspan="2" align="center"> <strong><BR>添加新用户<br></strong> </td> </tr> <tr> <td width="47%" align="right">用户名:</td> <td width="53%"> <input name="urUserName" type="text" id="userName"> </td> </tr> <tr> <td align="right">密码:</td> <td> <input name="urPassword" type="password" id="password"> </td> </tr> <tr> <td align="right">年龄:</td> <td> <input name="urAge" type="text" id="age"> </td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td colspan="2" align="center"> <input type="button" name="Submit4" value="添加" onclick="toAdd()"> <input type="button" name="Submit5" value="关闭" onclick="toCloseAdd()"> </td> </tr> </table> </form> </div> <div id="LayerEdit"> <form name="editForm" id="editForm" method="post" action=""> <input type="hidden" name="id" id="id" /> <table width="98%" border="0" align="center" cellpadding="0" cellspacing="0"> <tr> <td colspan="2" align="center"> <strong><br>修改用户信息<br> </strong> </td> </tr> <tr> <td width="47%" align="right">用户名:</td> <td width="53%"> <input name="userName" type="text" id="userName" readonly="readonly"> </td> </tr> <tr> <td align="right">年龄:</td> <td> <input name="age" type="text" id="age"> </td> </tr> <tr> <td align="right">状态:</td> <td> <select name="status" id="status"> <option value="Active">Active</option> <option value="Inactive">Inactive</option> <option value="Locked">Locked</option> <option value="Deleted">Deleted</option> </select> </td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td colspan="2" align="center"> <input type="button" name="Submit4" value="修改" onclick="toEdit()"> <input type="button" name="Submit5" value="关闭" onclick="toCloseEdit()"> </td> </tr> </table> </form> </div> <p> </p> <p>测试用户CRUD页面</p> <table width="539" border="1"> <tr> <td colspan="5" align="right"> <input type="button" name="Submit" value="新增" onclick="toShowAdd()"> <input type="submit" name="Submit2" value="修改" onclick="toShowEdit()"> <input type="button" name="Submit3" value="删除" onclick="toDelete()"> </td> </tr> <tr> <td> <div id="userListDiv"></div> </td> </tr> </table> <p> </p> </body> </html>6)userList.jsp。显示用户列表的页面。
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <table width="100%" border="1"> <tr> <td width="51" bgcolor="#CCCCCC"> <div align="center"> <strong><span class="STYLE2">选择</span></strong> </div> </td> <td width="111" bgcolor="#CCCCCC"> <div align="center"> <strong>序号</strong> </div> </td> <td width="137" bgcolor="#CCCCCC"> <div align="center"> <strong>用户名</strong> </div> </td> <td width="105" bgcolor="#CCCCCC"> <div align="center"> <strong>年龄</strong> </div> </td> <td width="101" bgcolor="#CCCCCC"> <div align="center"> <strong>状态</strong> </div> </td> </tr> <c:forEach items="${userList }" var="_user" varStatus="status"> <c:choose> <c:when test="${status.index%2==0 }"> <tr bgcolor="#FFFFFF"> </c:when> <c:otherwise> <tr bgcolor="#99FFFF"> </c:otherwise> </c:choose> <td> <input type="checkbox" name="checkbox" value="${_user.urId }"> </td> <td>${status.index+1 }</td> <td>${_user.urUserName }</td> <td>${_user.urAge }</td> <td>${_user.urStatus }</td> </tr> </c:forEach> </table>7)Jquery-3.2.1.min.js。jQuery 的 JS,CRUD 操作的时候需要实现逻辑 JS 代码,都是基于它来的。该文件放在 JS 目录下,千万不要遗忘。
4. 编译、测试、安装、发布和启动服务器
编译、测试、安装和发布同前面模块项目的操作一样。具体操作都是:右击“工程”,选择 Run As→Maven test→install→deploy 命令。
发布好后,在 Tomcat 的 webapps 发布目录下会有 MvnSSMDemo.war 文件,启动 Tomcat 就可以自动发布 Web 应用。
整合成SSM
前面以分模块的方式实现了每个功能,包括公共 DAO、Service 接口的定义,基于 MyBatis 的 DAO 实现,Service 的独立实现,还有基于 SpringMVC 的 Web 层实现,并且能够集成到 SpringMVC 的 Web 层代码中共同完成测试。但是为了方便管理,有必要创建一个工程,将前面独立实现的各个模块管理起来。这样每次编译、测试、安装和发布的时候都能基于 Maven 实现自动同步。
整合 SSM 模块的具体步骤如下。
1. 创建工程
只需创建一个简单的 Java 工程,按当初的设计输入 groupId 和 artifactId 与版本。这里的 demo 分别是 cn.com.mvn.ssm.demo、MvnSSMDemo 和 0.0.1-SNAPSHOT。2. 配置 pom.xml
打开 pom.xml,在里面添加包含的模块,并且设置 packaging 为 pom。前面介绍的是基于编辑器直接编写 pom.xml,这里介绍基于 MyEclipse 的图形化界面,基于向导界面修改 pom.xml(添加模块)。
通过单击不同标签选择打开方式,如图 4 所示。
图 4 pom.xml
如果选择的是 pom.xml,显示的是 pom.xml 源文件,可以按以前的方式基于源代码修改 pom.xml。现在选择 Overview 标签,显示界面如图 5 所示。
图 5 可视化pom.xml
单击 Modules 范围内的 Add… 按钮就可以通过图形界面选择需要添加的模块。保存后就完成了模块的集成。
3. 编译、测试、安装和发布
这个步骤同前面 SSH 集成后操作的步骤一样,请参考 SSH 集成里面最后的对应步骤。所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算