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)
- 創(chuàng)建獨(dú)立的Spring應(yīng)用程序
- 嵌入的Tomcat,無(wú)需部署WAR文件
- 開箱即用,提供各種默認(rèn)配置來(lái)簡(jiǎn)化項(xiàng)目配置
- 沒(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)目步驟
- 配置web.xml,加載spring和spring mvc
- 配置數(shù)據(jù)庫(kù)連接、配置spring事務(wù)
- 配置加載配置文件的讀取,開啟注解
- 配置日志文件
......
配置完成后部署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)目。
- 訪問(wèn) :http://start.spring.io/
- 選擇構(gòu)建工具maven、語(yǔ)言java、版本1.5.10(支持jdk1.7)
initializr.png
- 點(diǎn)擊Generate Project下載項(xiàng)目壓縮包
- 解壓項(xiàng)目,導(dǎo)入進(jìn)idea,說(shuō)一下簡(jiǎn)要步驟
- File -> New -> Project from Existing Sources
- 選擇你解壓的項(xiàng)目文件夾
- 點(diǎn)擊OK
- 選擇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的字符串常量池







