前言
本文講解作為後端的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
如果你覺得我的部落格對你有幫助,可以給我點兒打賞,左側微信,右側支付寶。
有可能就是你的一點打賞會讓我的部落格寫的更好:)