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

1. 前言

前面文章整合過(guò)了ssm的,是相對(duì)spring的,不過(guò)在現(xiàn)在微服務(wù)流行之際,為了往后面的springcloud發(fā)展學(xué)習(xí),先學(xué)習(xí)一下springboot,在學(xué)習(xí)的過(guò)程中用spring boot+spring mvc+mybatis進(jìn)行搭建接口平臺(tái)。

2. 簡(jiǎn)介

spring boot:Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開發(fā)過(guò)程。該框架使用了特定的方式來(lái)進(jìn)行配置,從而使開發(fā)人員不再需要定義樣板化的配置。通過(guò)這種方式,Spring Boot致力于在蓬勃發(fā)展的快速應(yīng)用開發(fā)領(lǐng)域(rapid application development)成為領(lǐng)導(dǎo)者。(來(lái)自百度百科)。

2.1 spring boot特點(diǎn)

  1. 創(chuàng)建獨(dú)立的Spring應(yīng)用程序
  2. 嵌入的Tomcat,無(wú)需部署WAR文件
  3. 開箱即用,提供各種默認(rèn)配置來(lái)簡(jiǎn)化項(xiàng)目配置
  4. 沒(méi)有冗余代碼生成和XML配置的要求

2.2 個(gè)人理解

在我看來(lái),spring boot并不是什么新的框架,它只是默認(rèn)配置了很多框架的使用方式;類似于maven整合了jar,而spring boot整合了很多的框架。從本質(zhì)上來(lái)講,spring boot就是spring,它做了那些你需要去做的復(fù)雜配置。它使用“習(xí)慣優(yōu)于配置”的理念讓你的項(xiàng)目快速運(yùn)行起來(lái)。

2.2 回顧一下spring web項(xiàng)目步驟

  1. 配置web.xml,加載spring和spring mvc
  2. 配置數(shù)據(jù)庫(kù)連接、配置spring事務(wù)
  3. 配置加載配置文件的讀取,開啟注解
  4. 配置日志文件
    ......
    配置完成后部署tomcat調(diào)試...

2.3 spring boot項(xiàng)目

只需要非常少的幾個(gè)配置就可以迅速方便的搭建起來(lái)一套web項(xiàng)目或者是構(gòu)建一個(gè)微服務(wù)!下面就讓我們一起來(lái)領(lǐng)略spring boot的魅力

3. 項(xiàng)目搭建

整個(gè)項(xiàng)目使用maven構(gòu)建,有關(guān)idea集成maven、jdk、tomcat等可翻我上一篇文章。

3.1 在這里使用spring提供的SPRING INITIALIZR工具來(lái)產(chǎn)生基礎(chǔ)項(xiàng)目。

  1. 訪問(wèn) :http://start.spring.io/
  2. 選擇構(gòu)建工具maven、語(yǔ)言java、版本1.5.10(支持jdk1.7)
initializr.png
  1. 點(diǎn)擊Generate Project下載項(xiàng)目壓縮包
  2. 解壓項(xiàng)目,導(dǎo)入進(jìn)idea,說(shuō)一下簡(jiǎn)要步驟
  1. File -> New -> Project from Existing Sources
  2. 選擇你解壓的項(xiàng)目文件夾
  3. 點(diǎn)擊OK
  4. 選擇Import project from external model并選擇Maven,點(diǎn)擊Next到底為止。

3.2 編譯錯(cuò)誤

若在項(xiàng)目編譯過(guò)程中,遇到[Information:java: javacTask: 源發(fā)行版 1.8 需要目標(biāo)發(fā)行版 1.8]這個(gè)錯(cuò)誤,可按照如下更改,這里我統(tǒng)一改為了1.7

1,Project Structure里確認(rèn)兩個(gè)地方:Project sdk以及project language level
2,Project Structure->Modules里Sources里的Language level
3,Preferences->java Compiler->Per-module bytecode Version

至此基礎(chǔ)項(xiàng)目準(zhǔn)備完畢,運(yùn)行一下項(xiàng)目

image.png

看見Spring Boot這個(gè)圖案證明基礎(chǔ)項(xiàng)目搭建成功。

4. 編寫代碼

4.1 項(xiàng)目結(jié)構(gòu)

項(xiàng)目結(jié)構(gòu).png

系統(tǒng)整個(gè)架構(gòu)為springboot+springmvc+mybatis,restful的接口風(fēng)格。只是一個(gè)示例項(xiàng)目,也沒(méi)有進(jìn)行模塊分包。整個(gè)結(jié)構(gòu)的話還是controller、service、dao的三層結(jié)構(gòu)。在這里面dao層多寫了一個(gè)接口和實(shí)現(xiàn)。對(duì)于service層沒(méi)有寫接口,因?yàn)槲矣X(jué)得簡(jiǎn)單的業(yè)務(wù)沒(méi)必要寫接口(包括這里的dao也是)。
我也一直在思考,對(duì)于service和dao層,到底需不需要接口和實(shí)現(xiàn)。網(wǎng)上查了一些,有些是瞎扯了一堆“接口和實(shí)現(xiàn)分離”、“面向接口編程”、“設(shè)計(jì)模式”、“解耦”等,但是也沒(méi)說(shuō)出個(gè)所以然;有些是說(shuō)沒(méi)必要分離,或者看系統(tǒng)架構(gòu)。自己也是經(jīng)歷不多,不知道確切的區(qū)別或者說(shuō)有什么效率上的區(qū)別。這個(gè)待我日后慢慢積累,有機(jī)會(huì)咨詢長(zhǎng)者學(xué)習(xí),或者評(píng)論區(qū)靜待大神的解答。

4.2 項(xiàng)目配置

springboot 遵循"習(xí)慣優(yōu)于配置"原則,使用Spirng Boot只需很少的配置,大部分時(shí)候可以使用默認(rèn)配置。
使用INITIALIZR工具創(chuàng)建的springboot項(xiàng)目,默認(rèn)會(huì)在resource目錄下創(chuàng)建application.properties文件,另外也可以使用yml類型的配置文件代替properties文件。在這里我是使用的是yml文件。

application.yml

spring:
  datasource:
        # 驅(qū)動(dòng)配置信息
        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連接池信息。上面的就是類型和驅(qū)動(dòng)這些,然后就是mysql數(shù)據(jù)庫(kù)的url、用戶名和密碼,相應(yīng)改成自己的就行。下面的是druid的參數(shù)配置項(xiàng),這里隨便設(shè)置了一些,具體可詳查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" /> <!--配置和設(shè)定執(zhí)行器-->
        <setting name="logImpl" value="STDOUT_LOGGING"/> <!--打印sql語(yǔ)句在控制臺(tái)-->
    </settings>

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

</configuration>

這個(gè)配置主要就是關(guān)于mybatis的配置了,這里就提兩點(diǎn),一個(gè)是setting里面的logImpl配置,可以把執(zhí)行的sql語(yǔ)句打印在控制臺(tái),便于排查sql錯(cuò)誤;二個(gè)是使用typeAliases標(biāo)簽元素來(lái)對(duì)類型進(jìn)行別名控制,也就是給具體的實(shí)體類一個(gè)別名,不用寫完整路徑。具體使用在后面mapper中會(huì)講到。

以上就是這個(gè)項(xiàng)目目前用到的兩個(gè)配置了,是不是比起spring來(lái)說(shuō)簡(jiǎn)便多了。

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模塊。自動(dòng)配置: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>

這些就是當(dāng)前項(xiàng)目中用到的一些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提供的持久層訪問(wèn)模板化的工具,這個(gè)類負(fù)責(zé)管理MyBatis的SqlSession,用于調(diào)用MyBatis的SQL方法。因?yàn)镾qlSessionTemplate是線程安全的,可以被多個(gè)DAO所共享使用,所以項(xiàng)目中只建立了一個(gè)SqlSessionTemplate。

在這里使用的是mybatis注解需要的配置。mybatis3開始支持java注解,使用java注解可以替代xml配置文件,簡(jiǎn)化代碼。上面的代碼中,使用@MapperScan來(lái)掃描注冊(cè)mybatis數(shù)據(jù)庫(kù)接口類,其中basePackages屬性表明接口類所在的包,sqlSessionTemplateRef表明接口類使用的SqlSessionTemplate。

@Configuration 申明這是一個(gè)配置類相當(dāng)于xml配置文件,@Bean表示這是一個(gè)Spring管理的bean。
@ConfigurationProperties用于裝載yml的配置信息

這里面其他關(guān)于SqlSessionTemplate的用法和細(xì)節(jié)就不一一講了,不明白的可百度學(xué)習(xí)一下SqlSessionTemplate。提一下setMapperLocations是用于加載以xml結(jié)尾的mapper配置文件,這里注意路徑就行了,根路徑是resources。setConfigLocation是加載mybatis的配置文件mybatis-config.xml。

4.3 數(shù)據(jù)庫(kù)文件

這個(gè)在上篇文章已經(jīng)介紹過(guò)作用,就是方便對(duì)sql語(yǔ)句的查閱和修改。

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;

這里表名和字段與上一篇文章相比修改了一些,因?yàn)榭戳恕栋⒗锇桶?Java開發(fā)手冊(cè)》中寫道:

表名、字段名必須使用小寫字母或數(shù)字,禁止出現(xiàn)數(shù)字開頭,禁止兩個(gè)下劃線中間只出現(xiàn)數(shù)字。數(shù)據(jù)庫(kù)字段名的修改代價(jià)很大,因?yàn)闊o(wú)法進(jìn)行預(yù)發(fā)布,所以字段名稱需要慎重考慮。 說(shuō)明:MYSQL在Windows下不區(qū)分大小寫,但在Linux上默認(rèn)區(qū)分大小寫。因此,數(shù)據(jù)庫(kù)名、表名、字段名都不允許出現(xiàn)任何大寫字母,避免節(jié)外生枝。

4.4 實(shí)體類

建立一個(gè)MUser的實(shí)體類

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用法
     * 對(duì)象轉(zhuǎn)json字符串 String json = json.toJSONString(對(duì)象);
     * 字符串轉(zhuǎn)json對(duì)象 json =json.parseObject(jsonStr);
     * 字符串轉(zhuǎn)java對(duì)象 Object object = JSON.parseObject(jsonStr, Object.class);
     * 字符串轉(zhuǎn)list  List<Object> list = JSON.parseArray(jsonStr, Object.class);
     */
}

在這里抽出了一個(gè)BaseController的父類,可放置多個(gè)Controller都會(huì)用到的一些對(duì)象或方法,這個(gè)父類被子類Controller繼承。目前此項(xiàng)目中的BaseController只放置了fastjson的兩個(gè)對(duì)象,正常項(xiàng)目中肯定會(huì)有不少共有的對(duì)象或方法都可放置這里面。

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;
    }

    /**
     * 通過(guò)用戶名稱獲取用戶
     *
     * @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 相關(guān)注解,集成restful風(fēng)格的接口,具體注解和含義、及restful風(fēng)格的理解可翻上一篇文章。
與上一篇略有不同的本項(xiàng)目使用的是@Resource注解注入bean。

關(guān)于@Resource和@Autowired:

  • 兩者都可以寫在字段和setter方法上。兩者如果都寫在字段上,那么就不需要再寫setter方法。
  • @Autowired默認(rèn)按類型裝配(這個(gè)注解屬于spring的),默認(rèn)情況下必須要求依賴對(duì)象必須存在,如果要允許null值,可以設(shè)置它的required屬性為false,如:@Autowired(required=false)
  • @Resource默認(rèn)安裝名稱進(jìn)行裝配(這個(gè)注解屬于J2EE的),名稱可以通過(guò)name屬性進(jìn)行指定,如果沒(méi)有指定name屬性,當(dāng)注解寫在字段上時(shí),默認(rèn)取字段名進(jìn)行安裝名稱查找。
  • 在我個(gè)人推薦用@Resource,因?yàn)檫@個(gè)注解是屬于J2EE的,減少了與spring的耦合,并且代碼看起更優(yōu)雅。若有高見,歡迎指教。

這個(gè)示例代碼實(shí)現(xiàn)了增刪改查四個(gè)基礎(chǔ)功能,前后端完全以JSON字符串進(jìn)行交互。(這里前后端以JSON字符串交互的方式有待商榷,以前認(rèn)知是用JSON字符串便于統(tǒng)一風(fēng)格;不過(guò)最近一年以來(lái)的學(xué)習(xí)和工作,現(xiàn)在會(huì)直接使用實(shí)體類進(jìn)行接收對(duì)象,免去JSON轉(zhuǎn)對(duì)象的步驟。)

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用法
     * 對(duì)象轉(zhuǎn)json字符串 String json = json.toJSONString(對(duì)象);
     * 字符串轉(zhuǎn)json對(duì)象 json =json.parseObject(jsonStr);
     * 字符串轉(zhuǎn)java對(duì)象 Object object = JSON.parseObject(jsonStr, Object.class);
     * 字符串轉(zhuǎn)list  List<Object> list = JSON.parseArray(jsonStr, Object.class);
     */
}

也是抽出了一個(gè)父類BaseService,放置共用的對(duì)象或方法。這里雖然與BashController內(nèi)容相似,不過(guò)沒(méi)有與BaseController共用,因?yàn)橄氲饺绻?xiàng)目復(fù)雜的話,Controller與Service層共用的東西會(huì)有較大差別。

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("注冊(cè)成功");
            br.setData(mUser);
        } else {
            br.setCode("400");
            br.setMsg("注冊(cè)失敗");
        }
        return json.toJSONString(br);
    }

    /**
     * 通過(guò)用戶名獲取用戶
     *
     * @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);
    }
}

這一層主要就是處理業(yè)務(wù)邏輯了,沒(méi)什么特別的地方,也是使用@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;
    }
}

為了統(tǒng)一與前端的交互,定義了BgyResult類進(jìn)行標(biāo)準(zhǔn)返回,統(tǒng)一返回格式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的接口層,用于訪問(wèn)數(shù)據(jù)庫(kù),實(shí)現(xiàn)數(shù)據(jù)的持久化。這里提一下,《阿里巴巴Java開發(fā)手冊(cè)》中寫道:

接口類中的方法和屬性不要加任何修飾符號(hào)(public也不要加),保持代碼的簡(jiǎn)潔性。

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;
    }
}

這個(gè)類就是dao接口的具體實(shí)現(xiàn)類了,沒(méi)什么特別的。使用的是前面配置的SqlSessionTemplate模板化工具,與mapper.xml結(jié)合實(shí)現(xiàn)操作數(shù)據(jù)庫(kù)。不過(guò)這里把所有返回int的操作做了一下boolean轉(zhuǎn)換,便于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>

這個(gè)是mybatis中sql的映射文件。命名空間即是sqlSessionTemplate.insert("UserMapper.addUser", mUser)中的UserMapper。

上面還提到了使用typeAliases標(biāo)簽元素來(lái)對(duì)類型進(jìn)行別名控制,也就是給具體的實(shí)體類一個(gè)別名,不用寫完整路徑。在這里的type或者parameterType里寫的MUser就是我們的實(shí)體類,如果不使用typeAliases,這里則應(yīng)寫完整路徑,即
com.bgy.springboot.model.MUser

到此,整個(gè)項(xiàng)目的代碼已經(jīng)編寫完成。實(shí)現(xiàn)了最基礎(chǔ)的增刪改查四個(gè)功能。

運(yùn)行項(xiàng)目,測(cè)試一下試試。由于springboot內(nèi)置了tomcat,所以不用單獨(dú)放在tomcat中部署。直接運(yùn)行SpringbootApplication類,即可運(yùn)行項(xiàng)目??匆娺@個(gè)即表示運(yùn)行成功:

run.png

下面以postman測(cè)試接口

添加用戶

post.png

編輯用戶

put.png

查詢用戶

get.png

刪除用戶

delete.png

至此,基于springboot+springmvc+mybatis框架的項(xiàng)目已經(jīng)完全整合與測(cè)試通過(guò)。這個(gè)項(xiàng)目結(jié)合上一個(gè)項(xiàng)目的一些東西,當(dāng)然也改進(jìn)了一些東西。項(xiàng)目中涉及到的技術(shù)都沒(méi)有難點(diǎn),就算對(duì)于新手也很容易搞懂,也有完整的代碼,已測(cè)試編譯通過(guò)。

編者水平有限,若有錯(cuò)誤或者更優(yōu)的建議歡迎指出。

目前全部文章列表:
idea整合restful風(fēng)格的ssm框架(一)
idea整合restful風(fēng)格的ssm框架(二)
idea整合spring boot+spring mvc+mybatis框架
idea整合springboot+redis
JVM學(xué)習(xí)之—Java內(nèi)存區(qū)域
JVM學(xué)習(xí)之—垃圾回收與內(nèi)存分配策略
專題整理之—不可變對(duì)象與String的不可變
專題整理之—String的字符串常量池

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容