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閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容