springboot簡單的專案

huanyu911發表於2024-10-30

專案結構

用到的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);
    }

}

相關文章