前言
本篇文章主要介紹的是Springboot整合SpringDataJPA基于Restful風(fēng)格實(shí)現(xiàn)增刪改查功能王凑。
Spring Boot介紹
Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架盈匾,其設(shè)計(jì)目的是用來簡化新Spring應(yīng)用的初始搭建以及開發(fā)過程悼尾。該框架使用了特定的方式來進(jìn)行配置,從而使開發(fā)人員不再需要定義樣板化的配置蟀架。通過這種方式寝蹈,我們不必像Spring MVC一樣寫大量的xml配置文件。
GitHub源碼鏈接位于文章底部侄非。
總結(jié)來說蕉汪,springboot是一個(gè)快速開發(fā)的框架,開箱即用逞怨,提供了各種默認(rèn)配置來簡化項(xiàng)目配置者疤,能夠集成第三方框架,這是通過maven依賴實(shí)現(xiàn)的叠赦,它簡化了xml驹马,采用注解的形式,springboot還內(nèi)嵌了tomcat容器除秀,幫助開發(fā)者快速開發(fā)與部署糯累。
添加依賴
新建一個(gè)maven項(xiàng)目,在pom文件中添加以下依賴
這個(gè)依賴引入了mvc框架册踩,開啟了接口訪問的方式泳姐,它也正是以這種maven依賴的方式集成第三方框架的。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
</dependencies>
主程序啟動入口
在controller暂吉、service等同級目錄下仗岸,創(chuàng)建Application.java啟動類
SpringBootApplication注解=Configuration注解+EnableAutoConfiguration注解+ComponentScan注解允耿。
Configuration注解負(fù)責(zé)初始化并啟動spring容器,這個(gè)類內(nèi)部方法上使用Bean注解可以實(shí)現(xiàn)spring容器的注入扒怖。
EnableAutoConfiguration注解負(fù)責(zé)初始化配置较锡,啟動springboot需要啟動的項(xiàng),后邊詳細(xì)解釋此注解的作用盗痒。
ComponentScan注解負(fù)責(zé)掃包蚂蕴,springboot啟動程序后,能夠被外部訪問的只有被SpringBootApplication注解掃描到的包下的類俯邓。
SpringBootApplication注解啟動類默認(rèn)掃包范圍是當(dāng)前包下或者子包下所有的類骡楼。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
控制層
@RestController
public class HelloWordController {
@GetMapping("/hello")
public String index() {
return "Hello World";
}
}
成功啟動主程序之后,瀏覽器輸入 http://localhost:8080/hello 便可以查看信息稽鞭。(因?yàn)闆]有配置端口鸟整,默認(rèn)端口就是8080)
修改默認(rèn)端口
在resource資源目錄下創(chuàng)建application.yml文件
server:
port: 8081
重新啟動后,瀏覽器輸入 http://localhost:8081/hello 可以查看信息朦蕴。
application.yml文件內(nèi)容的格式篮条,以上文中的端口為例:
server+冒號+空格,然后換行吩抓,+一個(gè)tab鍵占位符+port+冒號+空格+8080涉茧,
意為server屬性下的port屬性的值為8080.
基于Restful風(fēng)格實(shí)現(xiàn)增刪改查功能
一、Restful風(fēng)格介紹
是一種網(wǎng)絡(luò)應(yīng)用程序的設(shè)計(jì)風(fēng)格和開發(fā)方式疹娶,REST指的是一組架構(gòu)約束條件和原則伴栓。滿足這些約束條件和原則的應(yīng)用程序或設(shè)計(jì)就是 RESTful。
每一個(gè)URI代表1種資源雨饺;
客戶端使用GET钳垮、POST、PUT额港、DELETE4個(gè)表示操作方式的動詞對服務(wù)端資源進(jìn)行操作:GET用來獲取資源饺窿,POST用來新建資源(也可以用于更新資源),PUT用來更新資源锹安,DELETE用來刪除資源短荐;
二、開發(fā)準(zhǔn)備
1叹哭、新建數(shù)據(jù)庫和表
在MySql中創(chuàng)建一個(gè)名為springboot的數(shù)據(jù)庫和名為一張t_user的表忍宋。
CREATE DATABASE `springboot`;
USE `springboot`;
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(10) DEFAULT NULL COMMENT '姓名',
`age` int(2) DEFAULT NULL COMMENT '年齡',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
2、修改pom文件风罩,添加依賴
<!--父級依賴糠排,它用來提供相關(guān)的 Maven 默認(rèn)依賴。
使用它之后超升,常用的springboot包依賴可以省去version 標(biāo)簽
配置UTF-8編碼入宦,指定JDK8-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath ></relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- MySQL 連接驅(qū)動依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
</dependency>
</dependencies>
<build>
<resources>
<!--允許maven創(chuàng)建xml文件哺徊,否則xml要放在resources里-->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
3.工程結(jié)構(gòu)
com.lxg.springboot.controller - Controller 層
com.lxg.springboot.dao - 數(shù)據(jù)操作層 DAO
com.lxg.springboot.common - 存放公共類
com.lxg.springboot.entity - 實(shí)體類
com.lxg.springboot.service - 業(yè)務(wù)邏輯層
Application - 應(yīng)用啟動類
application.yml - 應(yīng)用配置文件,應(yīng)用啟動會自動讀取配置
4.修改application.yml文件乾闰,添加數(shù)據(jù)庫連接屬性
server:
port: 8080
spring:
datasource:
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8
三落追、編碼
1.在common中創(chuàng)建公共類
1.1 封裝分頁結(jié)果PageResult
@Data
public class PageResult<T> {
/**
* 總記錄數(shù)
*/
private Long total;
/**
* 每頁數(shù)據(jù)
*/
private List<T> rows;
public PageResult(Long total, List<T> rows) {
this.total = total;
this.rows = rows;
}
}
1.2 封裝統(tǒng)一返回結(jié)果
@Data
public class Result {
/**
* 返回結(jié)構(gòu)狀態(tài)
*/
private Boolean flag;
/**
* 返回狀態(tài)碼
*/
private Integer code;
/**
* 返回消息
*/
private String message;
/**
* 返回?cái)?shù)據(jù)內(nèi)容
*/
private Object data;
public Result(Boolean flag, Integer code, String message, Object data) {
this.flag = flag;
this.code = code;
this.message = message;
this.data = data;
}
public Result(Boolean flag, Integer code, String message) {
this.flag = flag;
this.code = code;
this.message = message;
}
public Result() {
}
}
1.3 返回狀態(tài)碼
public class StatusCode {
//成功
public static final Integer OK = 20000;
//失敗
public static final Integer ERROR = 20001;
//用戶名或密碼錯(cuò)誤
public static final Integer USER_PASS_ERROR = 20002;
//權(quán)限不足
public static final Integer ACCESS_ERROR = 20003;
//遠(yuǎn)程調(diào)用失敗
public static final Integer REMOTE_ERROR = 20004;
//重復(fù)操作
public static final Integer REPEATE_ERROR = 20005;
}
2.在entity中新建實(shí)體類
@Data
@Entity
@Table(name="t_user")
public class User implements Serializable {
/** 編號 */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
/** 姓名 */
private String name;
/** 年齡 */
private Integer age;
}
注解:Data:安裝lombok插件再使用該注解可省略getter/setter、無參構(gòu)造等方法涯肩,具體使用見文章https://www.lxgblog.com/article/1572329460
Entity:對實(shí)體注釋轿钠,聲明實(shí)體。
Table:與數(shù)據(jù)庫表綁定病苗。
Id:聲明Id疗垛。
GeneratedValue(strategy = GenerationType.IDENTITY):數(shù)據(jù)庫主鍵自增。
3.在dao中新建UserDao
UserDao需要繼承JpaRepository<實(shí)體類,實(shí)體類ID類型>, JpaSpecificationExecutor<實(shí)體類>硫朦,
JpaRepository<>泛型的第二個(gè)參數(shù)與id有關(guān)贷腕,如findById(id)的id類型
public interface UserDao extends JpaRepository<U實(shí)體類ID類型ser,String>, JpaSpecificationExecutor<User> {
//這里的數(shù)字指的是第幾個(gè)參數(shù)
@Modifying
@Query("update User u set u.age =?2 where u.id =?1")
void update(String id, Integer age);
}
4.service層新建UserService
@Service
public class UserService {
@Autowired
private UserDao userDao;
/**
* 新增或修改,無id為新增咬展,有id為修改
* @param user
*/
// @Transactional
public void saveUser(User user) {
userDao.save(user);
/**
* 這里的save方法會更新所有字段泽裳,如果只傳了age屬性進(jìn)行更新,
* name屬性就會修改為null挚赊,避免這個(gè)問題需要使用下面的原生Sql
* 并且加上方法上的@Transactional注解
* userDao.update(user.getId(),user.getAge());
*/
}
/**
* 根據(jù)id刪除
*
* @param id
*/
public void deleteUser(String id) {
userDao.deleteById(id);
}
/**
* 查詢所有
*/
public List<User> findAll() {
return userDao.findAll();
}
/**
* 根據(jù)id查詢
*
* @param id
*/
public User findUserById(String id) {
return userDao.findById(id).get();
}
/**
* 條件查詢+age排序
* @param searchMap
*/
public List<User> findSearch(Map searchMap) {
Specification<User> specification = createSpecification(searchMap);
Sort sort = new Sort(Sort.Direction.ASC, "age");
return userDao.findAll(specification,sort);
}
/**
* 條件+分頁+age排序
* @param searchMap
* @param page
* @param size
*/
public Page<User> findSearch(Map searchMap, int page, int size) {
Specification<User> specification = createSpecification(searchMap);
Sort sort = new Sort(Sort.Direction.ASC, "age");
PageRequest pageRequest = PageRequest.of(page - 1, size,sort);
return userDao.findAll(specification, pageRequest);
}
/**
* 創(chuàng)建查詢條件
*/
private Specification<User> createSpecification(Map searchMap) {
return new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery,
CriteriaBuilder criteriaBuilder) {
List<Predicate> preList = new ArrayList<Predicate>();
if (searchMap.get("name") != null && !(searchMap.get("name")).equals("")) {
preList.add(
criteriaBuilder.like(root.get("name").as(String.class), "%" + searchMap.get("name") + "%"));
}
if (searchMap.get("age") != null && !(searchMap.get("age")).equals("")) {
preList.add(criteriaBuilder.equal(root.get("age").as(Integer.class), searchMap.get("age")));
}
Predicate[] preArray = new Predicate[preList.size()];
return criteriaBuilder.and(preList.toArray(preArray));
}
};
}
}
5.controller層
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 新增
* @param user
*/
@RequestMapping(method = RequestMethod.POST)
public Result addUser(@RequestBody User user) {
userService.saveUser(user);
return new Result(true, StatusCode.OK,"新增成功");
}
/**
* 修改
* @param user
*/
@RequestMapping(method = RequestMethod.PUT)
public Result updateUser(@RequestBody User user) {
if (user.getId() == null || user.getId().equals("")) {
return new Result(false, StatusCode.ERROR,"無id,更新失敗");
}
userService.saveUser(user);
return new Result(true, StatusCode.OK,"更新成功");
}
/**
* 根據(jù)id刪除
* @param id
* @return
*/
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public Result delete(@PathVariable String id) {
userService.deleteUser(id);
return new Result(true, StatusCode.OK,"刪除成功");
}
/**
* 查詢所有
*/
@RequestMapping(method = RequestMethod.GET)
public List<User> findAllUser() {
return userService.findAll();
}
/**
* 根據(jù)id查詢
* @param id
*/
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Result findByUserId(@PathVariable String id) {
return new Result(true, StatusCode.OK,"查詢成功",userService.findUserById(id));
}
/**
* 條件查詢
*/
@RequestMapping(value="/search",method = RequestMethod.POST)
public Result findSearch(@RequestBody Map searchMap){
return new Result(true,StatusCode.OK,"查詢成功 ",userService.findSearch(searchMap));
}
/**
* 條件+分頁
* @param searchMap
* @param page
* @param size
*/
@RequestMapping(value = "/search/{page}/{size}",method = RequestMethod.POST)
public Result findSearch(@RequestBody Map searchMap,@PathVariable int page,@PathVariable int size){
Page<User> pageBean = userService.findSearch(searchMap, page, size);
return new Result(true,StatusCode.OK,"查詢成功",new PageResult<>(pageBean.getTotalElements(),pageBean.getContent()) );
}
}
@PathVariable注解的參數(shù)與@RequestMapping中value中的{}內(nèi)參數(shù)一致诡壁。
四济瓢、測試
啟動Application 之后荠割,使用postman工具進(jìn)行接口的測試。postman的使用教程查看另一偏博文旺矾。
1.新增
2.根據(jù)id屬性刪除蔑鹦,再次查詢所有,會發(fā)現(xiàn)少了一條
3.根據(jù)id屬性修改箕宙,再次查詢所有嚎朽,會發(fā)現(xiàn)已經(jīng)改變。
4.查詢所有
5.根據(jù)id屬性查詢
6.條件+age排序查詢
6.條件+age排序+分頁查詢
經(jīng)過上面的例子可以發(fā)現(xiàn)柬帕,增刪改查的url都是同一個(gè),即localhost:8080/user, 如果有一些簡單的條件哟忍,則放到它的后面作為條件。作為區(qū)別陷寝,使用了不同的請求方式,如Post,Get,Put,Delete等。
本文GitHub源碼:https://github.com/lixianguo5097/springboot/tree/master/springboot-jpa
CSDN:https://blog.csdn.net/qq_27682773
簡書:http://www.reibang.com/u/e99381e6886e
博客園:https://www.cnblogs.com/lixianguo
個(gè)人博客:https://www.lxgblog.com