spring boot + vue + element-ui全栈开发入门——spring boot后端开发
前言
本文讲解作为后端的spring boot项目开发流程,如果您还不会配置spring boot环境,就请点击《玩转spring boot——快速开始》,如果您对spring boot还没有入门,就请点击《玩转spring boot——开篇》学习spring boot开发。
一、构建项目
使用STS构建Spring Starter项目
pom.xml中添加依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <!-- 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映射类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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:分页结果承载
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /** * 操作执行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; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | /** * 分页查询参数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; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /** * 分页结果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
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 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,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | 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入口类:
1 2 3 4 5 6 7 | @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App. class , args); } } |
最后配置参数application.properties:
1 2 3 4 5 6 7 | 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
如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。
有可能就是你的一点打赏会让我的博客写的更好:)
作者:刘冬.NET
博客地址:http://www.cnblogs.com/GoodHelper/
欢迎转载,但须保留版权
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?