idea整合spring boot+spring mvc+mybatis框架

1. 前言

前面文章整合过了ssm的,是相对spring的,不过在现在微服务流行之际,为了往后面的springcloud发展学习,先学习一下springboot,在学习的过程中用spring boot+spring mvc+mybatis进行搭建接口平台。

2. 简介

spring boot:Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。(来自百度百科)。

2.1 spring boot特点

  1. 创建独立的Spring应用程序
  2. 嵌入的Tomcat,无需部署WAR文件
  3. 开箱即用,提供各种默认配置来简化项目配置
  4. 没有冗余代码生成和XML配置的要求

2.2 个人理解

在我看来,spring boot并不是什么新的框架,它只是默认配置了很多框架的使用方式;类似于maven整合了jar,而spring boot整合了很多的框架。从本质上来讲,spring boot就是spring,它做了那些你需要去做的复杂配置。它使用“习惯优于配置”的理念让你的项目快速运行起来。

2.2 回顾一下spring web项目步骤

  1. 配置web.xml,加载spring和spring mvc
  2. 配置数据库连接、配置spring事务
  3. 配置加载配置文件的读取,开启注解
  4. 配置日志文件
    ......
    配置完成后部署tomcat调试...

2.3 spring boot项目

只需要非常少的几个配置就可以迅速方便的搭建起来一套web项目或者是构建一个微服务!下面就让我们一起来领略spring boot的魅力

3. 项目搭建

整个项目使用maven构建,有关idea集成maven、jdk、tomcat等可翻我上一篇文章。

3.1 在这里使用spring提供的SPRING INITIALIZR工具来产生基础项目。

  1. 访问 :http://start.spring.io/
  2. 选择构建工具maven、语言java、版本1.5.10(支持jdk1.7)
initializr.png
  1. 点击Generate Project下载项目压缩包
  2. 解压项目,导入进idea,说一下简要步骤
  1. File -> New -> Project from Existing Sources
  2. 选择你解压的项目文件夹
  3. 点击OK
  4. 选择Import project from external model并选择Maven,点击Next到底为止。

3.2 编译错误

若在项目编译过程中,遇到[Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8]这个错误,可按照如下更改,这里我统一改为了1.7

1,Project Structure里确认两个地方:Project sdk以及project language level
2,Project Structure->Modules里Sources里的Language level
3,Preferences->java Compiler->Per-module bytecode Version

至此基础项目准备完毕,运行一下项目

image.png

看见Spring Boot这个图案证明基础项目搭建成功。

4. 编写代码

4.1 项目结构

项目结构.png

系统整个架构为springboot+springmvc+mybatis,restful的接口风格。只是一个示例项目,也没有进行模块分包。整个结构的话还是controller、service、dao的三层结构。在这里面dao层多写了一个接口和实现。对于service层没有写接口,因为我觉得简单的业务没必要写接口(包括这里的dao也是)。
我也一直在思考,对于service和dao层,到底需不需要接口和实现。网上查了一些,有些是瞎扯了一堆“接口和实现分离”、“面向接口编程”、“设计模式”、“解耦”等,但是也没说出个所以然;有些是说没必要分离,或者看系统架构。自己也是经历不多,不知道确切的区别或者说有什么效率上的区别。这个待我日后慢慢积累,有机会咨询长者学习,或者评论区静待大神的解答。

4.2 项目配置

springboot 遵循"习惯优于配置"原则,使用Spirng Boot只需很少的配置,大部分时候可以使用默认配置。
使用INITIALIZR工具创建的springboot项目,默认会在resource目录下创建application.properties文件,另外也可以使用yml类型的配置文件代替properties文件。在这里我是使用的是yml文件。

application.yml

spring:
  datasource:
        # 驱动配置信息
        url: jdbc:mysql://localhost:3306/spring_boot?useUnicode=true&characterEncoding=utf8
        username: root
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        
        # 连接池的配置信息
        filters: stat
        maxActive: 20
        initialSize: 1
        maxWait: 60000
        minIdle: 1
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: select 'x'
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxOpenPreparedStatements: 20

这里主要就是配置了阿里的druid连接池信息。上面的就是类型和驱动这些,然后就是mysql数据库的url、用户名和密码,相应改成自己的就行。下面的是druid的参数配置项,这里随便设置了一些,具体可详查Druid。

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <settings>
        <setting name="cacheEnabled" value="true" /><!-- 全局映射器启用缓存 -->
        <setting name="useGeneratedKeys" value="true" /> <!--把新增加的主键赋值到自己定义的keyProperty(id)中-->
        <setting name="defaultExecutorType" value="REUSE" /> <!--配置和设定执行器-->
        <setting name="logImpl" value="STDOUT_LOGGING"/> <!--打印sql语句在控制台-->
    </settings>

    <typeAliases>
        <package name="com.bgy.springboot.model"/> 
    </typeAliases>

</configuration>

这个配置主要就是关于mybatis的配置了,这里就提两点,一个是setting里面的logImpl配置,可以把执行的sql语句打印在控制台,便于排查sql错误;二个是使用typeAliases标签元素来对类型进行别名控制,也就是给具体的实体类一个别名,不用写完整路径。具体使用在后面mapper中会讲到。

以上就是这个项目目前用到的两个配置了,是不是比起spring来说简便多了。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>com.bgy</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.7</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--自己添加的包-->
        <dependency>
            <!-- spring boot 引入Web模块。自动配置:tomcat、springmvc、jackson等 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- log4j2  依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <!-- springboot 依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>1.3.6.RELEASE</version>
        </dependency>
        <!--  阿里druid连接池依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.11</version>
        </dependency>
        <!--  mysql 依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
            <version>1.3.8.RELEASE</version>
        </dependency>
        <!-- fastJson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.1.27</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <!--aop-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>net.minidev</groupId>
            <artifactId>json-smart</artifactId>
            <version>RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

这些就是当前项目中用到的一些maven依赖了。

DbDataSource.class

@Configuration
@MapperScan(basePackages = "com.bgy.springboot.dao",sqlSessionTemplateRef = "dbSqlSessionTemplate")
public class DbDataSource {

    @Bean(name="dbData")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dbDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dbSqlSessionFactory")
    public SqlSessionFactory dbSqlSessionFactory(@Qualifier("dbData") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        sqlSessionFactoryBean.setConfigLocation( new ClassPathResource("mybatis-config.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name="dbSqlSessionTemplate")
    public SqlSessionTemplate dbSqlSessionTemplate(@Qualifier("dbSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception{
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "dbTransactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dbData") DataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }
}

SqlSessionTemplate是MyBatis提供的持久层访问模板化的工具,这个类负责管理MyBatis的SqlSession,用于调用MyBatis的SQL方法。因为SqlSessionTemplate是线程安全的,可以被多个DAO所共享使用,所以项目中只建立了一个SqlSessionTemplate。

在这里使用的是mybatis注解需要的配置。mybatis3开始支持java注解,使用java注解可以替代xml配置文件,简化代码。上面的代码中,使用@MapperScan来扫描注册mybatis数据库接口类,其中basePackages属性表明接口类所在的包,sqlSessionTemplateRef表明接口类使用的SqlSessionTemplate。

@Configuration 申明这是一个配置类相当于xml配置文件,@Bean表示这是一个Spring管理的bean。
@ConfigurationProperties用于装载yml的配置信息

这里面其他关于SqlSessionTemplate的用法和细节就不一一讲了,不明白的可百度学习一下SqlSessionTemplate。提一下setMapperLocations是用于加载以xml结尾的mapper配置文件,这里注意路径就行了,根路径是resources。setConfigLocation是加载mybatis的配置文件mybatis-config.xml。

4.3 数据库文件

这个在上篇文章已经介绍过作用,就是方便对sql语句的查阅和修改。

db_ddl.sql

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` VARCHAR (45) NOT  NULL ,
  `user_name` VARCHAR (100) ,
  `nick_name` VARCHAR (100),
  `password` CHAR (32),
  `email` VARCHAR (50),
  `phone` VARCHAR (50),
  `sex` ENUM('S_MALE','S_FEMALE','S_BM'),
  `status` ENUM('S_OFF','S_NORMAL'),
  `avatar` VARCHAR (100),
  `remarks` VARCHAR (200),
  `add_at` BIGINT,
  `update_at` BIGINT,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

这里表名和字段与上一篇文章相比修改了一些,因为看了《阿里巴巴 Java开发手册》中写道:

表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。 说明:MYSQL在Windows下不区分大小写,但在Linux上默认区分大小写。因此,数据库名、表名、字段名都不允许出现任何大写字母,避免节外生枝。

4.4 实体类

建立一个MUser的实体类

MUser.class

public class MUser {
    private String id;

    private String userName;

    private String nickName;

    private String password;

    private String email;

    private String phone;

    private String sex;

    private String status;

    private String avatar;

    private String remarks;

    private Long addAt;

    public MUser(){}

    public String getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }

    public Long getAddAt() {
        return addAt;
    }

    public void setAddAt(Long addAt) {
        this.addAt = addAt;
    }
}

4.5 Controller

4.5.1 BaseController
public class BaseController {
    private static final long serialVersionUID = 6357869213649815390L;

    /**
     * @param fastJson
     */
    protected JSONObject json = new JSONObject();
    /**
     * fastjson JSONArray
     */
    protected JSONArray jsonArray = new JSONArray();
    /**
     * fastjson用法
     * 对象转json字符串 String json = json.toJSONString(对象);
     * 字符串转json对象 json =json.parseObject(jsonStr);
     * 字符串转java对象 Object object = JSON.parseObject(jsonStr, Object.class);
     * 字符串转list  List<Object> list = JSON.parseArray(jsonStr, Object.class);
     */
}

在这里抽出了一个BaseController的父类,可放置多个Controller都会用到的一些对象或方法,这个父类被子类Controller继承。目前此项目中的BaseController只放置了fastjson的两个对象,正常项目中肯定会有不少共有的对象或方法都可放置这里面。

4.5.2 UserController
@Controller
@RequestMapping("/user")
public class UserController extends BaseController {

    @Resource(name = "userService")
    private UserService userService;

    /**
     * 添加用户
     *
     * @param mUserJson
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "", method = RequestMethod.POST)
    @ResponseBody
    public String addUser(@RequestBody String mUserJson) throws Exception {
        String resultInfo = "";
        try {
            resultInfo = userService.addUser(mUserJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultInfo;
    }

    /**
     * 通过用户名称获取用户
     *
     * @param userName
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/{userName}", method = RequestMethod.GET)
    @ResponseBody
    public String getUserByName(@PathVariable String userName) throws Exception {
        String resultInfo = "";
        try {
            resultInfo = userService.getUserByName(userName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultInfo;
    }

    /**
     * 修改用户
     *
     * @param mUserJson
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    @ResponseBody
    public String updateUser(@PathVariable("id") String id, @RequestBody String mUserJson) throws Exception {
        String resultInfo = "";
        try {
            resultInfo = userService.updateUser(id, mUserJson);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultInfo;
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public String deleteUser(@PathVariable("id") String id) throws Exception {
        String resultInfo = "";
        try {
            resultInfo = userService.deleteUser(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultInfo;
    }
}

这里使用springmvc 相关注解,集成restful风格的接口,具体注解和含义、及restful风格的理解可翻上一篇文章。
与上一篇略有不同的本项目使用的是@Resource注解注入bean。

关于@Resource和@Autowired:

  • 两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。
  • @Autowired默认按类型装配(这个注解属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false)
  • @Resource默认安装名称进行装配(这个注解属于J2EE的),名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找。
  • 在我个人推荐用@Resource,因为这个注解是属于J2EE的,减少了与spring的耦合,并且代码看起更优雅。若有高见,欢迎指教。

这个示例代码实现了增删改查四个基础功能,前后端完全以JSON字符串进行交互。(这里前后端以JSON字符串交互的方式有待商榷,以前认知是用JSON字符串便于统一风格;不过最近一年以来的学习和工作,现在会直接使用实体类进行接收对象,免去JSON转对象的步骤。)

4.6 Service

4.6.1 BaseService
public class BaseService {
    private static final long serialVersionUID = 6357869213649815390L;

    /**
     * 得到32位的uuid
     *
     * @return
     */
    public String get32UUID() {
        String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
        return uuid;
    }

    /**
     * @param fastJson
     */
    protected JSONObject json = new JSONObject();
    /**
     * fastjson JSONArray
     */
    protected JSONArray jsonArray = new JSONArray();
    /**
     * fastjson用法
     * 对象转json字符串 String json = json.toJSONString(对象);
     * 字符串转json对象 json =json.parseObject(jsonStr);
     * 字符串转java对象 Object object = JSON.parseObject(jsonStr, Object.class);
     * 字符串转list  List<Object> list = JSON.parseArray(jsonStr, Object.class);
     */
}

也是抽出了一个父类BaseService,放置共用的对象或方法。这里虽然与BashController内容相似,不过没有与BaseController共用,因为想到如果项目复杂的话,Controller与Service层共用的东西会有较大差别。

4.6.2 UserService
@Service("userService")
public class UserService extends BaseService {

    @Resource(name = "userDaoImpl")
    private IUserDao iUserDao;


    /**
     * 添加用户
     *
     * @param mUserJson
     * @return
     */
    public String addUser(String mUserJson) {
        BgyResult br = new BgyResult();
        MUser mUser = json.parseObject(mUserJson, MUser.class);
        int count = iUserDao.countUserName(mUser);
        if (count > 0) {
            br.setCode("400");
            br.setMsg("用户名已存在");
            return json.toJSONString(br);
        }
        mUser.setId(get32UUID());
        boolean result = iUserDao.addUser(mUser);
        if (result) {
            br.setCode("200");
            br.setMsg("注册成功");
            br.setData(mUser);
        } else {
            br.setCode("400");
            br.setMsg("注册失败");
        }
        return json.toJSONString(br);
    }

    /**
     * 通过用户名获取用户
     *
     * @param userName
     * @return
     */
    public String getUserByName(String userName) {
        BgyResult br = new BgyResult();
        MUser mUser = iUserDao.getUserByName(userName);
        br.setCode("200");
        br.setMsg("Ok");
        br.setData(mUser);
        return json.toJSONString(br);
    }

    /**
     * 编辑用户
     *
     * @param mUserJson
     * @return
     */
    public String updateUser(String id, String mUserJson) {
        BgyResult br = new BgyResult();
        MUser mUser = json.parseObject(mUserJson, MUser.class);
        MUser myMUser = iUserDao.getUserById(id);
        if (myMUser == null) {
            br.setCode("400");
            br.setMsg("用户不存在");
            return json.toJSONString(br);
        }
        boolean result = iUserDao.updateUser(mUser);
        if (result) {
            br.setCode("200");
            br.setMsg("修改成功");
        } else {
            br.setCode("400");
            br.setMsg("修改失败");
        }
        return json.toJSONString(br);
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     */
    public String deleteUser(String id) {
        BgyResult br = new BgyResult();
        MUser myMUser = iUserDao.getUserById(id);
        if (myMUser == null) {
            br.setCode("400");
            br.setMsg("用户不存在");
            return json.toJSONString(br);
        }
        boolean result = iUserDao.deleteUser(id);
        if (result) {
            br.setCode("200");
            br.setMsg("删除成功");
        } else {
            br.setCode("400");
            br.setMsg("删除失败");
        }
        return json.toJSONString(br);
    }
}

这一层主要就是处理业务逻辑了,没什么特别的地方,也是使用@Resource注入Bean。
这里用到了BgyResult类作为返回类。

4.7 BgyResult

public class BgyResult implements Serializable {
    private static final long serialVersionUID = 4832771715671880043L;
    private String code;
    private String msg;
    private Object data;

    public BgyResult(){
        this.code = "200";
        this.msg = "SUCCESS";
        this.data = null;
    }

    public BgyResult(String msg) {
        this.code = "400";
        this.msg = msg;
        this.data = null;
    }

    public BgyResult(String code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public String getCode() {
        return this.code;
    }

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

    public String getMsg() {
        return this.msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return this.data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

为了统一与前端的交互,定义了BgyResult类进行标准返回,统一返回格式code、msg、data的json字符串。

4.8 Dao

4.8.1 IUserDao
public interface IUserDao {

    int countUserName(MUser mUser);

    boolean addUser(MUser mUser);

    MUser getUserByName(String userName);

    MUser getUserById(String id);

    boolean updateUser(MUser mUser);

    boolean deleteUser(String id);
}

这里就是dao的接口层,用于访问数据库,实现数据的持久化。这里提一下,《阿里巴巴Java开发手册》中写道:

接口类中的方法和属性不要加任何修饰符号(public也不要加),保持代码的简洁性。

4.8.2 UserDaoImpl
@Repository("userDaoImpl")
public class UserDaoImpl implements IUserDao {

    @Resource(name = "dbSqlSessionTemplate")
    private SqlSessionTemplate sqlSessionTemplate;

    @Override
    public int countUserName(MUser mUser) {
        return sqlSessionTemplate.selectOne("UserMapper.countUserName", mUser);
    }

    @Override
    public boolean addUser(MUser mUser) {
        int num = sqlSessionTemplate.insert("UserMapper.addUser", mUser);
        boolean result = false;
        if (num > 0) {
            result = true;
        }
        return result;
    }

    @Override
    public MUser getUserByName(String userName) {
        MUser mUser = sqlSessionTemplate.selectOne("UserMapper.getUserByName", userName);
        return mUser;
    }

    @Override
    public MUser getUserById(String id) {
        MUser mUser = sqlSessionTemplate.selectOne("UserMapper.getUserById", id);
        return mUser;
    }

    @Override
    public boolean updateUser(MUser mUser) {
        int num = sqlSessionTemplate.update("UserMapper.updateUser", mUser);
        boolean result = false;
        if (num > 0) {
            result = true;
        }
        return result;
    }

    @Override
    public boolean deleteUser(String id){
        int num = sqlSessionTemplate.update("UserMapper.deleteUser", id);
        boolean result = false;
        if (num > 0) {
            result = true;
        }
        return result;
    }
}

这个类就是dao接口的具体实现类了,没什么特别的。使用的是前面配置的SqlSessionTemplate模板化工具,与mapper.xml结合实现操作数据库。不过这里把所有返回int的操作做了一下boolean转换,便于service层处理。

4.9 UserMapper.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 namespace="UserMapper">
    <resultMap id="userMap" type="MUser">
        <id column="id" property="id"/>
        <result column="user_name" property="userName"/>
        <result column="nick_name" property="nickName"/>
        <result column="password" property="password"/>
        <result column="email" property="email"/>
        <result column="phone" property="phone"/>
        <result column="sex" property="sex"/>
        <result column="status" property="status"/>
        <result column="avatar" property="avatar"/>
        <result column="remarks" property="remarks"/>
        <result column="add_at" property="addAt"/>
    </resultMap>

    <select id="countUserName" parameterType="MUser" resultType="int">
        SELECT COUNT(1) FROM `user` WHERE user_name = #{userName}
    </select>

    <insert id="addUser" parameterType="MUser">
        INSERT INTO `user` (id,user_name,nick_name,password,email,phone,sex,status,avatar,remarks,add_at)
        VALUES (#{id},#{userName},#{nickName},#{password},#{email},#{phone},#{sex},#{status},#{avatar},#{remarks},unix_timestamp(now()),unix_timestamp(now()))
    </insert>

    <select id="getUserByName" resultMap="userMap">
        SELECT * FROM `user` WHERE user_name = #{userName}
    </select>

    <select id="getUserById" resultMap="userMap">
        SELECT * FROM `user` WHERE id = #{id}
    </select>

    <update id="updateUser" parameterType="MUser">
        UPDATE
        `user`
        SET
        <if test="nickName != null and nickName != ''">
            nick_name = #{nickName},
        </if>
        <if test="password != null and password != ''">
            password = #{password},
        </if>
        <if test="email != null and email != ''">
            email = #{email},
        </if>
        <if test="phone != null and phone != ''">
            phone = #{phone},
        </if>
        <if test="sex != null and sex != ''">
            sex = #{sex},
        </if>
        <if test="status != null and status != ''">
            status = #{status},
        </if>
        <if test="avatar != null and avatar != ''">
            avatar = #{avatar},
        </if>
        <if test="remarks != null and remarks != ''">
            remarks = #{remarks},
        </if>
        update_at = unix_timestamp(now())
        WHERE id = #{id}
    </update>

    <delete id="deleteUser" parameterType="string">
        DELETE FROM `user` WHERE
        <if test="_parameter!= null">
            id = #{id} AND
        </if>
        1=1
    </delete>
</mapper>

这个是mybatis中sql的映射文件。命名空间即是sqlSessionTemplate.insert("UserMapper.addUser", mUser)中的UserMapper

上面还提到了使用typeAliases标签元素来对类型进行别名控制,也就是给具体的实体类一个别名,不用写完整路径。在这里的type或者parameterType里写的MUser就是我们的实体类,如果不使用typeAliases,这里则应写完整路径,即
com.bgy.springboot.model.MUser

到此,整个项目的代码已经编写完成。实现了最基础的增删改查四个功能。

运行项目,测试一下试试。由于springboot内置了tomcat,所以不用单独放在tomcat中部署。直接运行SpringbootApplication类,即可运行项目。看见这个即表示运行成功:

run.png

下面以postman测试接口

添加用户

post.png

编辑用户

put.png

查询用户

get.png

删除用户

delete.png

至此,基于springboot+springmvc+mybatis框架的项目已经完全整合与测试通过。这个项目结合上一个项目的一些东西,当然也改进了一些东西。项目中涉及到的技术都没有难点,就算对于新手也很容易搞懂,也有完整的代码,已测试编译通过。

编者水平有限,若有错误或者更优的建议欢迎指出。

目前全部文章列表:
idea整合restful风格的ssm框架(一)
idea整合restful风格的ssm框架(二)
idea整合spring boot+spring mvc+mybatis框架
idea整合springboot+redis
JVM学习之—Java内存区域
JVM学习之—垃圾回收与内存分配策略
专题整理之—不可变对象与String的不可变
专题整理之—String的字符串常量池

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容