前言
本文講解作為后端的spring boot項目開發流程,如果您還不會配置spring boot環境,就請點擊《玩轉spring boot——快速開始》,如果您對spring boot還沒有入門,就請點擊《玩轉spring boot——開篇》學習spring boot開發。
一、構建項目
使用STS構建Spring Starter項目

pom.xml中添加依賴:
<!-- web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- jpa --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
完整的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.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo</name> <description>spring boot 全棧開發入門系列(www.cnblogs.com/goodhelper)</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.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.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- jpa --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- commons --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skip>true</skip> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> </plugins> <finalName>demo</finalName> </build> </project>
二、代碼編寫
JPA映射類:
package com.example;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.GenericGenerator;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 會員
*
* @author 劉冬 博客出處:http://www.cnblogs.com/GoodHelper/
*
*/
@Entity
@Table(name = "t_member")
public class Member {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(name = "member_id", length = 36)
public String id;
/**
* 注冊日期
*/
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Temporal(TemporalType.DATE)
@Column(name = "`date`")
public Date date;
/**
* 姓名
*/
@Column(name = "`name`", length = 50)
public String name;
/**
* 性別
*/
@Column(name = "sex")
public Integer sex;
// 省略 get set
}
新建Repository類:
package com.example;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* 會員Repository類
*
* @author 劉冬 博客出處:http://www.cnblogs.com/GoodHelper/
*
*/
public interface MemberRepository extends JpaRepository<Member, String>, JpaSpecificationExecutor<Member> {
}
新建三個DTO類,分別是:
ExecuteDTO:操作執行的反饋
PageQueryParamDTO:分頁查詢參數
PageResultDTO:分頁結果承載
代碼如下:
/**
* 操作執行DTO
*
* @author 劉冬 博客出處:http://www.cnblogs.com/GoodHelper/
*
*/
public class ExecuteDTO {
private boolean success;
private String message;
private Object value;
public ExecuteDTO() {
}
public ExecuteDTO(boolean success, String message, Object value) {
this.success = success;
this.message = message;
this.value = value;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
/**
* 分頁查詢參數DTO
*
* @author 劉冬 博客出處:http://www.cnblogs.com/GoodHelper/
*
*/
public class PageQueryParamDTO {
/**
* 頁碼
*/
private int page;
/**
* 每頁數量
*/
private int size;
/**
* 查詢條件
*/
private Object query;
public PageQueryParamDTO() {
}
public PageQueryParamDTO(int page, int size, Object query) {
this.page = page;
this.size = size;
this.query = query;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public Object getQuery() {
return query;
}
public void setQuery(Object query) {
this.query = query;
}
}
/**
* 分頁結果DTO
*
* @author 劉冬 博客出處:http://www.cnblogs.com/GoodHelper/
*
*/
public class PageResultDTO {
private long total;
private List<?> rows;
public PageResultDTO() {
}
public PageResultDTO(long total, List<?> rows) {
this.total = total;
this.rows = rows;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public List<?> getRows() {
return rows;
}
public void setRows(List<?> rows) {
this.rows = rows;
}
}
控制器:MemberController
代碼如下:
package com.example;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 會員控制器
*
* @author 劉冬 博客出處:http://www.cnblogs.com/GoodHelper/
*
*/
@RestController
@RequestMapping("member")
public class MemberController {
@Autowired
private MemberRepository repository;
@GetMapping("get/{id}")
public Member get(@PathVariable String id) {
return repository.findOne(id);
}
@PostMapping("save")
public ExecuteDTO save(@RequestBody Member entity) {
if (entity.date == null) {
entity.date = new Date();
}
repository.save(entity);
return new ExecuteDTO(true, "保存成功", entity.id);
}
@PostMapping("loadPage")
public PageResultDTO loadPage(@RequestBody PageQueryParamDTO params) {
// 動態查詢條件
Specification<Member> spec = (root, query, cb) -> {
if (params.getQuery() != null) {
// 篩選 會員姓名
query.where(cb.equal(root.get("name"), params.getQuery().toString()));
}
return null;
};
Pageable pageable = new PageRequest(params.getPage() - 1, params.getSize());
Page<Member> pageResult = repository.findAll(spec, pageable);
// 返回分頁數據
return new PageResultDTO(pageResult.getTotalElements(), pageResult.getContent());
}
@GetMapping("remove/{id}")
public ExecuteDTO remove(@PathVariable String id) {
repository.delete(id);
return new ExecuteDTO(true, "刪除成功", id);
}
}
單元測試類MemberTests,代碼如下:
package com.example;
import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 單元測試
*
* @author 劉冬 博客出處:http://www.cnblogs.com/GoodHelper/
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class MemberTests {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void test() {
String baseUrl = "http://localhost:" + port;
String name = "劉冬";
// 測試添加
Member entity = new Member();
entity.name = name;
entity.sex = 1;
ExecuteDTO execute = this.restTemplate.postForObject(baseUrl + "/member/save", entity, ExecuteDTO.class);
assertThat(execute).isNotNull();
assertThat(execute.isSuccess()).isTrue();
assertThat(execute.getValue()).isNotNull();
// 測試獲取
entity = this.restTemplate.getForObject(baseUrl + "/member/get/" + execute.getValue(), Member.class);
assertThat(entity).isNotNull();
assertThat(entity.id).isNotNull();
assertThat(entity.name).isEqualTo(name);
// 測試修改
entity.name = "劉冬的博客";
execute = this.restTemplate.postForObject(baseUrl + "/member/save", entity, ExecuteDTO.class);
assertThat(execute).isNotNull();
assertThat(execute.isSuccess()).isTrue();
// 測試修改成功
entity = this.restTemplate.getForObject(baseUrl + "/member/get/" + entity.id, Member.class);
assertThat(entity).isNotNull();
assertThat(entity.id).isNotNull();
assertThat(entity.name).isNotEqualTo(name);
// 測試查詢分頁
PageQueryParamDTO param = new PageQueryParamDTO(1, 20, null);
PageResultDTO pageResult = this.restTemplate.postForObject(baseUrl + "/member/loadPage", param,
PageResultDTO.class);
assertThat(pageResult).isNotNull();
assertThat(pageResult.getRows()).isNotEmpty();
assertThat(pageResult.getTotal()).isGreaterThan(0);
// 測試刪除
execute = this.restTemplate.getForObject(baseUrl + "/member/remove/" + entity.id, ExecuteDTO.class);
assertThat(execute).isNotNull();
assertThat(execute.isSuccess()).isTrue();
// 測試是否已刪除
entity = this.restTemplate.getForObject(baseUrl + "/member/get/" + entity.id, Member.class);
assertThat(entity).isNull();
}
}
App.class入口類:
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
最后配置參數application.properties:
server.port=18080 spring.datasource.url=jdbc:mysql://localhost:3306/example spring.datasource.username=root spring.datasource.password= spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true
把8080默認端口修改為18080,因為之前我們的前端項目的端口是8080,如果同一台電腦運行會出現端口沖突。
完整的項目結構如圖所示:

運行單元測試的效果:

單元測試順利通過
git代碼地址:https://github.com/carter659/spring-boot-vue-element.git

如果你覺得我的博客對你有幫助,可以給我點兒打賞,左側微信,右側支付寶。
有可能就是你的一點打賞會讓我的博客寫的更好:)
