SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring学习

 

概述

通过半个多月的梳理,MyBatis我们已经能够使用,下面我们来说下SSM的整合。

整合SSM,需要用到MyBatis-Spring。

MyBatis-Spring可以将MyBatis代码无缝整合到Spring中,使用这个类库中的类,Spring将会加载必要的MyBatis工厂类和Session类。 这个类库也提供了一种简单的方式将MyBatis数据映射器和SqlSession注入到业务层的bean中,而且也可以处理事务,翻译MyBatis的异常到Spring的DataAcessException数据访问异常中。

MyBatis-Spring项目地址: https://github.com/mybatis/spring

接下来,我们从新建一个Maven项目开始,逐步集成Spring、Spring MVC 和MyBatis。


Step1.新建Maven web项目

如果不熟悉,请查考之前的博文总结 Maven-EclipseEE使用Maven构建Java web项目从0到1,这里简单说下重点,不赘述细节了。


step1.1 基本结构

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring学习_02


Step1.2 pom.xml

正创建Maven Web项目的时候,输入对应的Group Id 、 Artifact Id 、 Version ,web项目 packing 为 war。

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_03


Step1.3 web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
					http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">

</web-app>

空的web.xml 如上所示,


Step1.4 pom.xml中添加web的支持

添加web的支持

<!--web-->
<!-- servlet -->
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>${servlet.version}</version>
	<scope>provided</scope>
</dependency>
<!--JSP-->
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>${jsp.version}</version>
    <scope>provided</scope>
</dependency>
<!--JSTL-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>${jstl.version}</version>
</dependency>
        

版本信息如下:

<junit.version>3.8.1</junit.version>
<servlet.version>3.1.0</servlet.version>
<jstl.version>1.2</jstl.version>
<jsp.version>2.1</jsp.version>

由于项目中可能会用到Filter和ServletRequest接口,所以在编译项目时,必须听servlet-api和jsp-api依赖。 通常Web容器都会自带servlet-api和jsp-api的jar包,为了避免jar包重复引起错误,需要将servlet-api和jsp-api的scope配置为provided.

配置为provided的jar包在项目打包时,不会将依赖的jar包打包到项目中,项目运行时这些jar包需要欧容器提供,这样避免了重复jar包引起的错误。

一般以JSP作为视图的项目中,jstl是很常见的搭配,使用jstl可以在视图中处理复杂的逻辑,所以都会添加jstl依赖


Step1.5 添加页面用于验证搭建的web项目是否OK

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring学习_04

页面中使用了jstl,用来显示服务器的时间。

/ssm/src/main/webapp下添加个home.jsp

同时在web.xml中添加欢迎页面

<!-- 关于欢迎页面:访问一个网站时,默认看到的第一个页面就叫欢迎页,一般情况下是由首页来充当欢迎页的。
		一般情况下,我们会在web.xml中指定欢迎页。 -->
	<!-- 指定欢迎页面.指定了2个欢迎页面.
		   显示时按顺序从第一个找起,如果第一个存在,就显示第一个,后面的不起作用。
		   如果第一个不存在,就找第二个,以此类推 -->
	<welcome-file-list>
		<welcome-file>home.jsp</welcome-file>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	<!-- web.xml也没指定欢迎页的情况下,它默认先查找index.html文件,
		如果找到了,就把index.html作为欢迎页还回给浏览器。
		如果没找到index.html,tomcat就去找index.jsp。找到index.jsp就把它作为欢迎页面返回。
		而如果index.html和index.jsp都没找到,又没有用web.xml文件指定欢迎页面,那此时tomcat就不知道该返回哪个文件了,
		就显示TThe requested resource is not available. -->

home.jsp

<%@ page import="java.util.Date" %>
<%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF8">
    <title>Home</title>
</head>
<body>
<p>
	    用于验证新建的Maven Web项目是否OK
	 <br>
	 <br>
	   页面以及服务器时间正常展示--->OK
</p>

<p>
	<%
		Date now = new Date();
	%>
   	 服务器时间:<fmt:formatDate value="<%=now%>" pattern="yyyy-MM-dd HH:mm:ss"/>
</p>
</body>
</html>

将项目发布到tomcat8中

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_05

启动成功后,输入
http://localhost:8080/ssm/home.jsp
或者
http://localhost:8080/ssm

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_06


Step2.集成Spring和Spring MVC

Step2.1 添加Spring项目清单用于管理Spring依赖

	<!-- 在dependencyManagement中引入spring-framework-bom来确保所有的spring模块都使用统一的版本.
		添加spring-framework-bom后,就不需要配置每个依赖的版本号了,方便管理与升级 -->
	<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>4.3.9.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

在dependencyManagement中引入spring-framework-bom来确保所有的spring模块都使用统一的版本.添加spring-framework-bom后,就不需要配置每个依赖的版本号了,方便管理与升级


Step2.2 添加Spring依赖

  <!--Spring 上下文,核心依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <!--Spring JDBC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <!--Spring 事务-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
        <!--Spring 面向切面编程-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
        </dependency>
        <!--spring-aop 依赖-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectjweaver.version}</version>
        </dependency>

详见注释内容


Step2.3 添加Spring MVC依赖

 <!--Spring Web 核心-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <!--Spring MVC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <!--spring mvc-json依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.4</version>
        </dependency>

前两个依赖是SpringMVC必备的依赖,后面的jackson-databind是SpringMVC转换为JSON时需要使用的依赖


Step2.4 添加Spring XML配置文件

/src/main/resources目录下 增加 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:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	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
		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自动扫描类,通过base-package指定扫描的包名  使用了Ant通配符 -->
	<context:component-scan base-package="com.artisan.*.service.impl"/>
	
	<!-- 数据源 -->
	<bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/artisan"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
   
</beans>

配置文件中component-scan用于配置Spring自动扫描的类,通过base-package属性设置要扫描的包名, 包名支持Ant通配符,报名中的*匹配0或者任意数量的字符,这里的配置可以匹配com.artisan.web.service.impl 或者 com.artisan.xxx.service.impl这样的包。

dataSource配置了一个数据源连接,最好将其独立到单独的配置文件,前面的博客中有讲,这里先不抽取出来了。


Step2.5 添加Spring MVC配置文件

/src/main/resources目录下新增 springmvcConfig.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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
	
	<!-- 扫描控制层的注解,使其成为Spring管理的Bean -->
    <context:component-scan base-package="com.artisan.*.controller"/>
	
	<!-- 启用Controller注解支持 -->
    <mvc:annotation-driven/>
    <!-- 静态资源文件 -->
    <mvc:resources mapping="/static/**" location="static/"/>
	
	<!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

配置项说明参考注释


Step2.6 配置web.xml

集成Spring和SpringMVC后,要在web.xml中进行相应的配置。

对于Spring来说,需要增加如下配置

<!-- 在web启动时,根据contextConfigLocation配置的路径读取Spring配置文件,启动Spring -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

对于Spring MVC来说,需要增加如下配置

<!-- Spring MVC配置 -->
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvcConfig.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

为了避免编码不一致,通常还需要增加编码过滤器配置

<!-- 为避免编码不一致,一般情况下都需要增加编码过滤器 -->
	<filter>
		<filter-name>SpringEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>SpringEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

Step2.7 验证集成的Spring 以及SpringMVC是否OK

/ssm/src/main/webapp/WEB-INF/jsp目录下增加 index.jsp

<%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF8">
    <title>Index</title>
</head>
<body>
<p>
	    用于验证集成了Spring和SpringMVC是否正常
	 <br>
	 <br>
	    页面以及服务器时间正常展示--->OK
</p>

<p>	
	通过mv传递过来的now视图参数,获取服务器时间
   	 服务器时间:<fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss"/>
</p>
</body>
</html>

/ssm/src/main/java/com/artisan/web/controller包下增加控制层IndexController.java

package com.artisan.web.controller;

import java.util.Date;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * 
 * 
 * @ClassName: IndexController
 * 
 * @Description: 用于验证集成Spring以及SpringMVC是否OK
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年5月1日 下午2:21:11
 */

@Controller
public class IndexController {

	@RequestMapping("/index")
	public ModelAndView testEnv() {
		ModelAndView mv = new ModelAndView();
		// 设置跳转页面
		mv.setViewName("index");
		// 传递参数
		mv.addObject("now", new Date());
		return mv;
	}
}

启动应用,访问 http://localhost:8080/ssm/index

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_07


Step3.集成MyBatis

Step3.1 添加mybatis-spring依赖

<dependency>
     <groupId>org.mybatis</groupId>
     <artifactId>mybatis-spring</artifactId>
     <version>${mybatis-spring}</version>
 </dependency>

这里我们使用 <mybatis-spring>1.3.0</mybatis-spring>版本


Step3.2 配置 SqlSessionFactoryBean

在MyBatis-Spring中,SqlSessionFactoryBean用于创建SqlSessionFactory. 在Spring配置文件applicationContext.xml中配置这个工厂类

    <!-- 配置SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    	<property name="configLocation" value="classpath:mybatisConfig.xml"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations">
            <array>
                <value>classpath:com/artisan/**/mapper/*.xml</value>
            </array>
        </property>
        <property name="typeAliasesPackage" value="com.artisan.web.model"/>
    </bean>

SqlSessionFactoryBean常用属性介绍:

  • configLocation 用于配置MyBatis配置XML的路径

MyBatis配置文件 /ssm/src/main/resources/mybatisConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
        <setting name="logImpl" value="LOG4J"/>
        <setting name="cacheEnabled" value="true"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
	</settings>
</configuration>
  • datasource 用于配置数据源,必选项

  • mapperLocations 配置SqlSessionFactory扫描XML映射文件的路径

  • typeAliasesPackage 配置包中类的别名, 配置后,包中的类在XML映射文件中使用时可以省略包名部分,直接使用类名。 不支持Ant风格的路径,当需要配置多个可以使用分号或者逗号隔开。

其他属性可参考源码,略。


Step3.3 配置MapperScannerConfigurer

推荐使用MapperScannerConfigurer 类自动扫描所有的Mapper接口,使用时可以直接注入接口

/ssm/src/main/resources/applicationContext.xml增加

  <!-- 配置MapperScannerConfigurer -->
	 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="addToConfig" value="true"/>
        <property name="basePackage" value="com.artisan.**.mapper"/>
    </bean>

MapperScannerConfigurer常用属性

  • basePackage 用于配置基本的包路径,可以使用分号或者逗号作为分隔符设置多个包路径,每个映射器会在指定的包路径中递归被搜索到。

  • annotationClass 用于过滤被扫描的接口,如果设置了该属性,那么MyBatis的接口只有包含该注解才会被扫描进去。


3.4applicationContext.xml其他配置AOP和事务

 <aop:aspectj-autoproxy/>

    <aop:config>
        <aop:pointcut id="appService" expression="execution(* com.artisan.*.service..*Service*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="appService"/>
    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="select*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

Step4.示例测试

step4.0数据准备

MySql数据库

-- ----------------------------
-- Table structure for sys_dict
-- ----------------------------
DROP TABLE IF EXISTS `sys_dict`;
CREATE TABLE `sys_dict` (
  `id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `code` varchar(64) NOT NULL COMMENT '类别',
  `name` varchar(64) NOT NULL COMMENT '字典名',
  `value` varchar(64) NOT NULL COMMENT '字典值',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_dict
-- ----------------------------
INSERT INTO `sys_dict` VALUES ('1', '性别', '男', '男');
INSERT INTO `sys_dict` VALUES ('2', '性别', '女', '女');
INSERT INTO `sys_dict` VALUES ('3', '季度', '第一季度', '1');
INSERT INTO `sys_dict` VALUES ('4', '季度', '第二季度', '2');
INSERT INTO `sys_dict` VALUES ('5', '季度', '第三季度', '3');
INSERT INTO `sys_dict` VALUES ('6', '季度', '第四季度', '4');

step4.1 实体类

在 /src/main/java 新建 com.artisan.web.model包,然后新建SysDict.java

package com.artisan.web.model;

import java.io.Serializable;

/**
 * 
 * 
 * @ClassName: SysDict
 * 
 * @Description: SysDict实体类,如果使用缓存,请务必实现java.io.Serializable接口
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年5月11日 下午4:16:37
 */
public class SysDict implements Serializable {

	private static final long serialVersionUID = -2496324675593406906L;

	private Long id;
	private String code;
	private String name;
	private String value;

	public Long getId() {
		return id;
	}

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

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getName() {
		return name;
	}

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

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return "SysDict [id=" + id + ", code=" + code + ", name=" + name + ", value=" + value + "]";
	}

}


step4.2 开发Mapper层(Dao层)

Mapper层也就是常说的数据访问层(Dao层) 。 使用Mapper和XML映射文件结合的方式进行开发。

4.2.1 根据配置文件中的扫描路径新建包(接口用)或目录(xml用)

在/ssm/src/main/resources/applicationContext.xml集成MyBatis中

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_08

MapperScannerConfigurer自动扫描接口的包名为 com.artisan.**.mapper,因此创建Mapper接口也需要参照这个命名规则。

在/src/main/java新建 com.artisan.web.mapper 包,创建DictMapper接口

public interface DictMapper {

}

同样的,SqlSessionFactoryBean中配置了扫描XML映射文件的路径

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_09

classpath:com/artisan/**/mapper/*.xml ,在 /src/main/resources/ 新建com/artisan/web/mapper目录,然后新增DictMapper.xml文件

<?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接口和XML文件关联的时候, namespace的值就需要配置成接口的全限定名称 -->
<mapper namespace="com.artisan.web.mapper.DictMapper">

</mapper>					


4.2.2DictMapper接口

CRUD基本操作

package com.artisan.web.mapper;

import java.util.List;

import org.apache.ibatis.session.RowBounds;

import com.artisan.web.model.SysDict;

/**
 * 
 * 
 * @ClassName: DictMapper
 * 
 * @Description: 操作Sys_Dict的接口
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年5月11日 下午4:24:14
 */

public interface DictMapper {
	/**
	 * 
	 * 
	 * @Title: selectByPrimaryKey
	 * 
	 * @Description: 根据主键查询
	 * 
	 * @param id
	 * @return
	 * 
	 * @return: SysDict
	 */
	SysDict selectByPrimaryKey(Long id);

	/**
	 * 条件查询
	 *
	 * @param sysDict
	 * @return
	 */
	List<SysDict> selectBySysDict(SysDict sysDict, RowBounds rowBounds);

	/**
	 * 新增
	 *
	 * @param sysDict
	 * @return
	 */
	int insert(SysDict sysDict);

	/**
	 * 根据主键更新
	 *
	 * @param sysDict
	 * @return
	 */
	int updateById(SysDict sysDict);

	/**
	 * 根据主键删除
	 *
	 * @param id
	 * @return
	 */
	int deleteById(Long id);
}


4.2.3 DictMapper.xml

<?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接口和XML文件关联的时候, namespace的值就需要配置成接口的全限定名称 -->
<mapper namespace="com.artisan.web.mapper.DictMapper">

	<select id="selectByPrimaryKey" resultType="com.artisan.web.model.SysDict">
		SELECT
		a.id,
		a.`code`,
		a.`name`,
		a.`value`
		FROM
		sys_dict a
		WHERE
		a.id = #{id}
	</select>

	<select id="selectBySysDict" resultType="com.artisan.web.model.SysDict">
		select * from sys_dict
		<where>
			<if test="id != null">
				and id = #{id}
			</if>
			<if test="code != null and code != ''">
				and code = #{code}
			</if>
		</where>
		order by code, `value`
	</select>

	<insert id="insert" useGeneratedKeys="true" keyProperty="id">
		insert
		into sys_dict(code, name, value)
		values (#{code}, #{name}, #{value})
	</insert>

	<update id="updateById">
		update 
		sys_dict
		set code = #{code},
		name = #{name},
		value = #{value}
		where id = #{id}
	</update>

	<delete id="deleteById">
		delete from sys_dict where id = #{id}
	</delete>

</mapper>					

有了上述5个方法,就可以实现对表的基本操作了,下面在这5个接口方法的基础上继续开发Service层的代码。


step4.3开发业务层(Service层)

src/main/java 目录下新建 com.artisan.web.service包 ,添加DictService接口

package com.artisan.web.service;

import java.util.List;

import com.artisan.web.model.SysDict;

/**
 * 
 * 
 * @ClassName: DictService
 * 
 * @Description: Service层
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年5月11日 下午5:37:22
 */
public interface DictService {

	SysDict findById(Long id);

	List<SysDict> findBySysDict(SysDict sysDict, Integer offset, Integer limit);

	boolean saveOrUpdate(SysDict sysDict);

	boolean deleteById(Long id);
}

Servie层的saveOrUpdate方法对应Mapper中的insert和updateById方法,其他3个方法和Mapper层的方法一一对应。

com.artisan.web.service包下新建 impl包,然后新建DictServiceImpl实现类实现该接口

接口实现类

package com.artisan.web.service.impl;

import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.artisan.web.mapper.DictMapper;
import com.artisan.web.model.SysDict;
import com.artisan.web.service.DictService;
/**
 * 

 * @ClassName: DictServiceImpl

 * @Description: @Service标注的Service层

 * @author: Mr.Yang

 * @date: 2018年5月11日 下午5:39:22
 */

@Service
public class DictServiceImpl implements DictService {

	@Autowired
	private DictMapper dictMapper;

	@Override
	public SysDict findById(Long id) {
		return dictMapper.selectByPrimaryKey(id);
	}

	@Override
	public List<SysDict> findBySysDict(SysDict sysDict, Integer offset, Integer limit) {
		RowBounds rowBounds = RowBounds.DEFAULT;
		if (offset != null && limit != null) {
			rowBounds = new RowBounds(offset, limit);
		}
		return dictMapper.selectBySysDict(sysDict, rowBounds);
	}

	@Override
	public boolean saveOrUpdate(SysDict sysDict) {
		if (sysDict.getId() == null) {
			return dictMapper.insert(sysDict) == 1;
		} else {
			return dictMapper.updateById(sysDict) == 1;
		}
	}

	@Override
	public boolean deleteById(Long id) {
		if (id == null) {
			throw new NullPointerException("id");
		}
		return dictMapper.deleteById(id) == 1;
	}

}

Service层的实现类需要添加@Service注解,集成Spring的时候配置过自动扫描包

/ssm/src/main/resources/applicationContext.xml

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring学习_10

包名com.artisan.web.service.impl, DictServiceImpl实现类所在的包就是符合这个包名规则,加上注解后,Spring在初始化扫描到这个类时,然后由Spring管理这个类。

同样的,因为配置了自动扫描Mapper接口,所以在Service层可以注解通过@Autowired自动注入Mapper

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_11

通过自动扫描Mapper和自动注入可以更加方便的使用MyBatis。


step4.4开发控制层(Controller层)

com.artisan.web.controller包下新建DictController类

package com.artisan.web.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.artisan.web.model.SysDict;
import com.artisan.web.service.DictService;

/**
 * 
 * 
 * @ClassName: DictController
 * 
 * @Description: @Controller标注的Dict控制层
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年5月11日 下午5:40:19
 */

@Controller
@RequestMapping("/dicts")
public class DictController {
	@Autowired
	private DictService dictService;

	/**
	 * 显示字典数据列表
	 * 
	 * @param sysDict
	 * @param offset
	 * @param limit
	 * @return
	 */
	@RequestMapping
	public ModelAndView dicts(SysDict sysDict, Integer offset, Integer limit) {
		ModelAndView mv = new ModelAndView("dicts");
		List<SysDict> dicts = dictService.findBySysDict(sysDict, offset, limit);
		mv.addObject("dicts", dicts);
		return mv;
	}

	/**
	 * 新增或修改字典信息页面,使用 get 跳转到页面
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "add", method = RequestMethod.GET)
	public ModelAndView add(Long id) {
		ModelAndView mv = new ModelAndView("dict_add");
		SysDict sysDict;
		if (id == null) {
			// 如果 id 不存在,就是新增数据,创建一个空对象即可
			sysDict = new SysDict();
		} else {
			// 如果 id 存在,就是修改数据,把原有的数据查询出来
			sysDict = dictService.findById(id);
		}
		mv.addObject("model", sysDict);
		return mv;
	}

	/**
	 * 新增或修改字典信息,通过表单 post 提交数据
	 * 
	 * @param sysDict
	 * @return
	 */
	@RequestMapping(value = "add", method = RequestMethod.POST)
	public ModelAndView save(SysDict sysDict) {
		ModelAndView mv = new ModelAndView();
		try {
			dictService.saveOrUpdate(sysDict);
			mv.setViewName("redirect:/dicts");
		} catch (Exception e) {
			mv.setViewName("dict_add");
			mv.addObject("msg", e.getMessage());
			mv.addObject("model", sysDict);
		}
		return mv;
	}

	/**
	 * 通过 id 删除字典信息
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "delete", method = RequestMethod.POST)
	@ResponseBody
	public ModelMap delete(@RequestParam Long id) {
		ModelMap modelMap = new ModelMap();
		try {
			boolean success = dictService.deleteById(id);
			modelMap.put("success", success);
		} catch (Exception e) {
			modelMap.put("success", false);
			modelMap.put("msg", e.getMessage());
		}
		return modelMap;
	}
}

用了两个视图 dicts和 dict_add ,接下来开发View层


step4.5开发视图层(View层)

/ssm/src/main/resources/springmvcConfig.xml中的配置

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring学习_12

/ssm/src/main/webapp/WEB-INF/jsp/dicts.jsp

<%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <c:set var="path" value="${pageContext.request.contextPath}"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF8">
    <title>字典信息</title>
    <script src="${path}/static/jquery-3.1.1.min.js"></script>
</head>
<body>
<table>
    <tr>
        <th colspan="4">字典管理</th>
    </tr>
    <tr>
        <th>类别名</th>
        <th>字典名</th>
        <th>字典值</th>
        <th> 操作  [<a href="${path}/dicts/add">新增</a>]</th>
    </tr>
    <c:forEach items="${dicts}" var="dict">
        <tr id="dict-${dict.id}">
            <td>${dict.code}</td>
            <td>${dict.name}</td>
            <td>${dict.value}</td>
            <td>
                [<a href="${path}/dicts/add?id=${dict.id}">编辑</a>]
                [<a href="javascript:;" onclick="deleteById(${dict.id}, '${dict.name}')">删除</a>]
            </td>
        </tr>
    </c:forEach>
</table>
<script>
    function deleteById(id, label){
        var r = confirm('您确定要删除“' + label + '”吗?');
        if(r){
            $.ajax({
                url: '${path}/dicts/delete',
                data: {
                    id: id
                },
                dataType: 'json',
                type: 'POST',
                success: function(data){
                    if(data.success){
                        $('#dict-' + id).remove();
                    } else {
                        alert(data.msg);
                    }
                }
            })
        }
    }
</script>
</body>
</html>

/ssm/src/main/webapp/WEB-INF/jsp/dict_add.jsp

<%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <c:set var="path" value="${pageContext.request.contextPath}"/>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF8">
    <title>字典维护</title>
</head>
<body>
<form action="${path}/dicts/add" method="post">
    <input type="hidden" name="id" value="${model.id}">
    <table>
        <c:if test="${msg != null}">
            <tr>
                <th colspan="2" style="color:red;max-width:400px;">${msg}</th>
            </tr>
        </c:if>
        <tr>
            <th colspan="2">字典维护</th>
        </tr>
        <tr>
            <th>类别名</th>
            <td><input type="text" name="code" value="${model.code}"></td>
        </tr>
        <tr>
            <th>字典名</th>
            <td><input type="text" name="name" value="${model.name}"></td>
        </tr>
        <tr>
            <th>字典值</th>
            <td><input type="text" name="value" value="${model.value}"></td>
        </tr>
        <tr>
            <th colspan="2">
                <input type="submit" value="保存">
                <input type="button" onclick="backToList()" value="取消">
            </th>
        </tr>
    </table>
</form>
<script>
    function backToList(){
        location.href = '${path}/dicts';
    }
</script>
</body>
</html>

其中dicts.jsp使用了jquery-3.1.1.min.js ,请放在 /ssm/src/main/webapp/static/目录下

step4.6部署运行应用

发布到tomcat8中,访问 http://localhost:8080/ssm/dicts

列表页面:

SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring学习_13

新增
SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring学习_14

编辑
SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_15

删除一条我们新增的数据
SSM-Spring+SpringMVC+MyBatis整合案例从0到1_Spring教程_16


Step5.代码地址及总结

代码已经提交Github https://github.com/yangshangwei/ssm

本篇博客我们按照顺序依次讲解了如何集成Spring + Spring MVC + MyBatis ,通过该示例了解了配置和基本的数据操作方法。