專案結構
用到的pom.xml配置
(1)springdata-jpa 運算元據庫:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
(2)springmvc
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
(3) 引數效驗
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
(4) 單元測試
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
yaml配置
spring:
application:
name: springboot_xushu
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/t2?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update #自動更新資料庫表的結構
properties:
hibernate:
format_sql: true # 格式化sql(不格式化會導致在控制檯一行列印)
show-sql: true # 顯示sql語句
server:
port: 8088
補充解釋:這是mysql驅動配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/t2?useUnicode=true&characterEncoding=utf-8 這裡資料庫名用t2,問號後面是可以防止亂碼問題
username: root
password: 123456
springdata-jpa動態運算元據庫表
1.匯入依賴
<!--springdata-jpa 運算元據庫-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2.建立一個資料庫:省略
3.透過javabin結構建立資料庫表
package com.huanyu.springboot_xushu.poji;
import jakarta.persistence.*;
/**
* 這些註釋都是透過對映用Java建mysql資料庫表
*/
@Table(name="tb_user")//表名
@Entity
public class User {
@Id //主鍵ID
@GeneratedValue(strategy = GenerationType.IDENTITY) //自增長
@Column(name = "user_id")//欄位名
private Integer userId;
@Column(name = "user_name")
private String userName;
@Column(name = "password")
private String password;
@Column(name = "email")
private String email;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String username) {
this.userName = username;
}
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;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", username='" + userName + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
3.yaml配置
spring:
jpa:
hibernate:
ddl-auto: update #啟用動態資料庫
properties:
hibernate:
format_sql: true #格式化,方便程式設計師檢視問題
show-sql: true #在控制皮膚列印sql語句
使用者傳過來的資料型別一般單獨建立一個類,叫資料傳輸類
package com.huanyu.springboot_xushu.poji.dto;
import jakarta.persistence.Column;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import org.hibernate.validator.constraints.Length;
public class UserDto {
private Integer userId;
//@NotEmpty 不能為雙引號 (這些註解是在pom.xml裡面匯入了引數效驗功能的配置)
@NotBlank(message = "使用者名稱不能為空") //去除空殼
private String userName;
@NotBlank(message = "使用者名稱不能為空") //去除空殼
@Length(min = 6, max = 12) //指定密碼長度,最小值6,最大值12
private String password;
@Email(message = "郵箱格式不正確")
private String email;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
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 Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
@Override
public String toString() {
return "UserDto{" +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
}
請求成功返回的引數
package com.huanyu.springboot_xushu.poji;
import jakarta.servlet.http.HttpServlet;
import org.springframework.http.HttpStatus;
public class ResponseMessage<T> {
private Integer code;
private String message;
private T data;
public ResponseMessage(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
//介面請求成功
public static <T> ResponseMessage<T> success(T data){
/**
* 引數一:請求成功引數:200
* 引數二:請求成功列印
* 引數三:響應的資料
*/
return new ResponseMessage<>(HttpStatus.OK.value(), "success!",data);
}
//介面請求成功
public static <T> ResponseMessage<T> success(){
/**
* 引數一:請求成功引數:200
* 引數二:請求成功列印
* 引數三:響應的資料
*/
return new ResponseMessage<>(HttpStatus.OK.value(), "success!",null);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
一般在業務邏輯類service裡面會建一個介面,面向介面進行程式設計對於以後的擴充套件性,維護下更強
public interface IUserService {
/**
* 插入使用者
*
* @param user
* @return
*/
User add(UserDto user);
/**
* 查詢使用者
* @param userId 使用者Id
* @return
*/
User getUser(Integer userId);
/**
* 修改使用者
* @param user 需要修改的使用者物件
* @return
*/
User edit(UserDto user);
/**
* 刪除使用者
*
* @param userId 使用者Id
*/
void delete(Integer userId);
}
資料訪問類
package com.huanyu.springboot_xushu.repository;
import com.huanyu.springboot_xushu.poji.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
/**
* CrudRepository<User, Integer>
* 第一個引數是操作什麼類,這裡我們在操作User類,所以是User
* 第二個引數是主鍵id是什麼資料型別
*/
@Repository //這個同樣是把當前這個類註冊為spring的bean
// 之所以跟UserService中的這個@Service 註解不一樣是區分業務分類,讓邏輯更清晰
public interface UserRepository extends CrudRepository<User, Integer> {
}
業務邏輯類
package com.huanyu.springboot_xushu.service;
import com.huanyu.springboot_xushu.poji.User;
import com.huanyu.springboot_xushu.poji.dto.UserDto;
import com.huanyu.springboot_xushu.repository.UserRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service //spring的bean //標記成spring的bean後,我們就可以在Controller那裡給他自動裝配進去
public class UserService implements IUserService{
@Autowired
UserRepository userRepository;
@Override
public User add(UserDto user){
User userPojo = new User();
BeanUtils.copyProperties(user, userPojo);//引數一:你要複製那一個物件 引數二:你要複製到那一個物件裡面去
/**
* save()方法
* 增加可以調,修改也可以
* 他會自動判別如果他有id修改,沒有就是刪除
*/
return userRepository.save(userPojo);
// 呼叫資料訪問類
}
/**
* 查詢使用者
*
* @param userId 使用者Id
* @return
*/
@Override
public User getUser(Integer userId) {
/**
* userRepository.findById():返回的型別是Optional,
* Optional是專門用來處理空指標的(因為可能根據id查不出來)
* orElseThrow() 如果是空指標那就丟擲異常
*/
return userRepository.findById(userId).orElseThrow(() -> {
throw new IllegalArgumentException("使用者不存在,引數異常"); //朗姆達表示式
});
}
/**
* 修改使用者
*
* @param user
* @return
*/
@Override
public User edit(UserDto user) {
User userPojo = new User();
BeanUtils.copyProperties(user, userPojo);
return userRepository.save(userPojo);//插入和修改都呼叫save方法
}
/**
* 刪除使用者
*
* @param userId 使用者Id
*/
@Override
public void delete(Integer userId) {
userRepository.deleteById(userId);
}
}
控制器類
伺服器訪問指定路徑容器後呼叫指定方,再從容器方法呼叫邏輯包中的方法
package com.huanyu.springboot_xushu.controller;
import com.huanyu.springboot_xushu.poji.ResponseMessage;
import com.huanyu.springboot_xushu.poji.User;
import com.huanyu.springboot_xushu.poji.dto.UserDto;
import com.huanyu.springboot_xushu.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController //介面方法返回物件 轉化成json文字
@RequestMapping("/user") //URL: localhost:8088/user
public class UserController {
@Autowired //Spring 容器會自動查詢匹配的 bean,並將其注入到該成員變數、方法引數或建構函式中。
IUserService userService;
// REST
// 增加
@PostMapping
/**
* @Validated 引數效驗
* @RequestBody 自動把傳進來的json文字轉換成物件
*/
public ResponseMessage<User> add(@Validated @RequestBody UserDto user){ //這裡可以用User物件當引數,但一般自定義一個使用者傳輸類
User userNew = userService.add(user);
//return "success!";
//這裡可以直接呼叫ResponseMessage裡面的方法,把返回出來的新user響應到客戶端
return ResponseMessage.success(userNew);
}
// 查詢
@GetMapping("/{userId}")
public ResponseMessage<User> query(@PathVariable Integer userId){
User userNew = userService.getUser(userId);
return ResponseMessage.success(userNew);
}
// 修改
@PutMapping
public ResponseMessage<User> edit(@Validated @RequestBody UserDto user){ //這裡可以用User物件當引數,但一般自定義一個使用者傳輸類
User userNew = userService.edit(user);
return ResponseMessage.success(userNew);
}
// 刪除
@DeleteMapping("/{userId}")
public ResponseMessage<User> delete(@PathVariable Integer userId){
userService.delete(userId);
return ResponseMessage.success();
}
}
@GetMapping("{id}"):意思就是在原@RequestMapping("/hello")路徑下,下一個路徑時呼叫對應地址的方法;
@PathVariable:意思就是獲取地址裡面的值
統一異常處理通知
package com.huanyu.springboot_xushu.exception;
import com.huanyu.springboot_xushu.poji.ResponseMessage;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice //統一處理
public class GlobalExceptionHandlerAdvice {
Logger log= LoggerFactory.getLogger(GlobalExceptionHandlerAdvice.class);
@ExceptionHandler({Exception.class}) //因為所有異常父類都是Exception,所以這裡用Exception為所有異常做統一處理
public ResponseMessage handlerException(Exception e, HttpServletRequest request, HttpServletResponse response){
//日誌記錄
log.error("統一異常:",e);
return new ResponseMessage(500,"error",null);
}
}
啟動類
package com.huanyu.springboot_xushu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootXushuApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootXushuApplication.class, args);
}
}