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

简介: SSM-Spring+SpringMVC+MyBatis整合案例从0到1



概述

通过半个多月的梳理,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 基本结构


Step1.2 pom.xml

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


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

页面中使用了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中

启动成功后,输入

http://localhost:8080/ssm/home.jsp

或者

http://localhost:8080/ssm


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


Step3.集成MyBatis

Step3.1 添加mybatis-spring依赖

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

这里我们使用 1.3.0版本


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中

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

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

public interface DictMapper {
}

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

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

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

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

通过自动扫描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/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

列表页面:

新增

编辑

删除一条我们新增的数据


Step5.代码地址及总结

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

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


相关文章
|
5天前
|
SQL Java 数据库连接
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本文讲解了最新版MP的使用教程,包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段等核心功能。
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
|
1月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
300 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
1月前
|
缓存 Java 数据库连接
使用MyBatis缓存的简单案例
MyBatis 是一种流行的持久层框架,支持自定义 SQL 执行、映射及复杂查询。本文介绍了如何在 Spring Boot 项目中集成 MyBatis 并实现一级和二级缓存,以提高查询性能,减少数据库访问。通过具体的电商系统案例,详细讲解了项目搭建、缓存配置、实体类创建、Mapper 编写、Service 层实现及缓存测试等步骤。
|
1月前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
75 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
1月前
|
Java 数据库连接 API
springBoot:后端解决跨域&Mybatis-Plus&SwaggerUI&代码生成器 (四)
本文介绍了后端解决跨域问题的方法及Mybatis-Plus的配置与使用。首先通过创建`CorsConfig`类并设置相关参数来实现跨域请求处理。接着,详细描述了如何引入Mybatis-Plus插件,包括配置`MybatisPlusConfig`类、定义Mapper接口以及Service层。此外,还展示了如何配置分页查询功能,并引入SwaggerUI进行API文档生成。最后,提供了代码生成器的配置示例,帮助快速生成项目所需的基础代码。
|
1月前
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
45 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
1月前
|
Java 数据库连接 Maven
Spring整合Mybatis
Spring整合Mybatis
|
6月前
|
设计模式 前端开发 Java
了解 Spring MVC 架构、Dispatcher Servlet 和 JSP 文件的关键作用
Spring MVC 是 Spring 框架的一部分,是一个 Web 应用程序框架。它旨在使用 Model-View-Controller(MVC) 设计模式轻松构建Web应用程序。
104 0
|
1月前
|
存储 设计模式 前端开发
什么是SpringMVC?简单好理解!什么是应用分层?SpringMVC与应用分层的关系? 什么是三层架构?SpringMVC与三层架构的关系?
文章解释了SpringMVC的概念和各部分功能,探讨了应用分层的原因和具体实施的三层架构,以及SpringMVC与三层架构之间的关系和联系。
22 1
什么是SpringMVC?简单好理解!什么是应用分层?SpringMVC与应用分层的关系? 什么是三层架构?SpringMVC与三层架构的关系?
|
5月前
|
安全 前端开发 Java
挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构
挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构
52 1