概述
通过半个多月的梳理,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 ,通过该示例了解了配置和基本的数据操作方法。