1.新建SpringBoot項目,在 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.chen</groupId>
<artifactId>chen</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>chen</name>
<description>Demo project for Spring Boot</description>
<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-web</artifactId>
</dependency>
<!--導入jpa依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--MySQL驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- lombok簡化實體類代碼 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.新建項目架構
3.在 application.properties 進行配置
server.port=80
#數據庫配置
spring.datasource.url=jdbc:mysql://localhost:3306/chen?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
# 參數說明 create-運行項目時創建表,update-運行項目時更新表,none-不做操作
spring.jpa.hibernate.ddl-auto=none
# 打印sql語句
spring.jpa.show-sql=true
5.利用aop進行全局異常處理
package com.chen.aop;
import com.chen.domain.AppConstant;
import com.chen.restful.RestResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
/**
* 全局異常處理類
*
* @author chen
*/
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
private static final String logExceptionFormat = "服務器異常: Code: %s Detail: %s";
private static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
//運行時異常
@ExceptionHandler(RuntimeException.class)
public RestResponse runtimeExceptionHandler(RuntimeException ex) {
System.err.println("RuntimeException:");
return resultOut(AppConstant.RunTime, "服務器內部錯誤,運行異常", ex);
}
//空指針異常
@ExceptionHandler(NullPointerException.class)
public RestResponse nullPointerExceptionHandler(NullPointerException ex) {
System.err.println("NullPointerException:");
return resultOut(AppConstant.NullPointer, "空指針異常", ex);
}
//類型轉換異常
@ExceptionHandler(ClassCastException.class)
public RestResponse classCastExceptionHandler(ClassCastException ex) {
System.err.println("ClassCastException:");
return resultOut(AppConstant.ClassCast, "類型轉換異常", ex);
}
//IO異常
@ExceptionHandler(IOException.class)
public RestResponse iOExceptionHandler(IOException ex) {
System.err.println("IOException:");
return resultOut(AppConstant.IO, "IO異常", ex);
}
//未知方法異常
@ExceptionHandler(NoSuchMethodException.class)
public RestResponse noSuchMethodExceptionHandler(NoSuchMethodException ex) {
System.err.println("NoSuchMethodException:");
return resultOut(AppConstant.NoSuchMethod, "未知方法異常", ex);
}
//數組越界異常
@ExceptionHandler(IndexOutOfBoundsException.class)
public RestResponse indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
System.err.println("IndexOutOfBoundsException:");
return resultOut(AppConstant.IndexOutOfBounds, "數組越界異常", ex);
}
//400錯誤
@ExceptionHandler({HttpMessageNotReadableException.class})
public RestResponse requestNotReadable(HttpMessageNotReadableException ex) {
System.err.println("HttpMessageNotReadableException");
return resultOut(AppConstant.HttpMessageNotReadable, "400 bad request", ex);
}
//400錯誤
@ExceptionHandler({TypeMismatchException.class})
public RestResponse requestTypeMismatch(TypeMismatchException ex) {
System.err.println("TypeMismatchException:");
return resultOut(AppConstant.TypeMismatch, "400 bad request", ex);
}
//400錯誤
@ExceptionHandler({MissingServletRequestParameterException.class})
public RestResponse requestMissingServletRequest(MissingServletRequestParameterException ex) {
System.err.println("MissingServletRequestParameterException:");
return resultOut(AppConstant.MissingServletRequestParameter, "400 bad request", ex);
}
//405錯誤
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
public RestResponse request405(HttpRequestMethodNotSupportedException ex) {
System.err.println("HttpRequestMethodNotSupportedException:");
return resultOut(AppConstant.HttpRequestMethodNotSupported, "405 Method not allowed", ex);
}
//406錯誤
@ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
public RestResponse request406(HttpMediaTypeNotAcceptableException ex) {
System.err.println("HttpMediaTypeNotAcceptableException:");
return resultOut(AppConstant.HttpMediaTypeNotAcceptable, "406 Not Acceptable", ex);
}
//500錯誤
@ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
public RestResponse server500(RuntimeException ex) {
System.err.println("RuntimeException:");
return resultOut(AppConstant.HttpMediaTypeNotAcceptable, "500 error", ex);
}
//棧溢出
@ExceptionHandler({StackOverflowError.class})
public RestResponse requestStackOverflow(StackOverflowError ex) {
System.err.println("StackOverflowError:");
return resultOut(AppConstant.StackOverflow, "棧溢出異常", ex);
}
//除數不能爲0
@ExceptionHandler({ArithmeticException.class})
public RestResponse arithmeticException(ArithmeticException ex) {
System.err.println("ArithmeticException:");
return resultOut(AppConstant.Arithmetic, "除數不能爲0", ex);
}
//其他錯誤
@ExceptionHandler({Exception.class})
public RestResponse exception(Exception ex) {
System.err.println("Exception:");
return resultOut(AppConstant.other, "其他異常", ex);
}
/**
* 對返回數據集中處理
*
* @param code
* @param msg
* @param ex
* @param <T>
* @return
*/
private <T extends Throwable> RestResponse resultOut(int code, String msg, T ex) {
ex.printStackTrace();
log.error(String.format(logExceptionFormat, code, ex.getMessage()));
return RestResponse.fail(code).msg(msg);
}
}
6.封裝常量類
package com.chen.domain;
/**
* 對常量進行封裝,利於後期代碼的維護
*
* @author chen
*/
public class AppConstant {
// 文本消息
public static final String MESSAGE = "message";
// 單個對象
public static final String ITEM = "item";
// 返回的對象列表
public static final String LIST = "list";
// 狀態碼
public static final String CODE = "code";
// 代表執行成功
public static int OK = 0;
// 代表執行失敗
public static int FAIL = 1;
// 代表服務器運行異常
public static int RunTime = 2;
// 代表空指針異常
public static int NullPointer = 3;
// 類型轉換異常
public static int ClassCast = 4;
// IO異常
public static int IO = 5;
// 未知方法異常
public static int NoSuchMethod = 6;
// 數組越界異常
public static int IndexOutOfBounds = 7;
// 400錯誤
public static int HttpMessageNotReadable=8;
// 400錯誤
public static int TypeMismatch=9;
// 400錯誤
public static int MissingServletRequestParameter=10;
// 405錯誤
public static int HttpRequestMethodNotSupported=11;
// 406錯誤
public static int HttpMediaTypeNotAcceptable=12;
// 500錯誤
public static int Run500=13;
// 棧溢出
public static int StackOverflow=14;
// 除數爲0異常
public static int Arithmetic=15;
// 其他異常
public static int other=16;
}
7.封裝rest數據
package com.chen.restful;
import com.chen.domain.AppConstant;
import java.util.HashMap;
import java.util.List;
/**
* REST 接口返回數據
*
* @author chen
*/
public class RestResponse extends HashMap<String, Object> {
/**
* 禁止通過構造函數構造對象,只能通過靜態方法獲取實例。
*
* @see #ok()
* @see #ok(String)
* @see #fail()
* @see #fail(String)
*/
private RestResponse() {
}
/**
* 設置接口返回的文本消息,屬性 key: message
*
* @param msg
* @return
*/
public RestResponse msg(String msg) {
this.put(AppConstant.MESSAGE, msg);
return this;
}
/**
* 設置接口返回的數據對象,屬性 key: item
*
* @param item
* @return
*/
public RestResponse item(Object item) {
this.put(AppConstant.ITEM, item);
return this;
}
/**
* 設置接口返回的數據對象列表,屬性 key: list
*
* @param list
* @return
*/
public RestResponse list(List<?> list) {
this.put(AppConstant.LIST, list);
return this;
}
/**
* 設置接口返回的數據項,並指定數據項的屬性 key
*
* @param key
* @param value
* @return
*/
public RestResponse put(String key, Object value) {
super.put(key, value);
return this;
}
/**
* 接口執行成功的返回數據,其中屬性 CODE = 0
*
* @return
*/
public static RestResponse ok() {
RestResponse result = new RestResponse();
result.put(AppConstant.CODE, AppConstant.OK);
return result;
}
/**
* 接口執行成功的返回數據,並設置文本消息
*
* @param msg
* @return
*/
public static RestResponse ok(String msg) {
RestResponse result = new RestResponse();
result.put(AppConstant.CODE, AppConstant.OK).msg(msg);
return result;
}
/**
* 接口執行成功的返回數據,並設置對象數據
*
* @param item
* @return
*/
public static RestResponse ok(Object item) {
RestResponse result = new RestResponse();
result.put(AppConstant.CODE, AppConstant.OK).item(item);
return result;
}
/**
* 接口執行成功的返回數據,並設置列表對象數據
*
* @param list
* @return
*/
public static RestResponse ok(List<?> list) {
RestResponse result = new RestResponse();
result.put(AppConstant.CODE, AppConstant.OK).list(list);
return result;
}
/**
* 接口執行失敗的返回數據,其中屬性 CODE = 1
*
* @return
*/
public static RestResponse fail() {
RestResponse result = new RestResponse();
result.put(AppConstant.CODE, AppConstant.FAIL);
return result;
}
/**
* 接口執行失敗的返回數據,並設置文本消息,其中屬性 CODE = 1, message = {msg}
*
* @param msg
* @return
*/
public static RestResponse fail(String msg) {
RestResponse result = new RestResponse();
result.put(AppConstant.CODE, AppConstant.FAIL).msg(msg);
return result;
}
/**
* 接口執行失敗的返回數據,自定義狀態碼,其中屬性 CODE = {errcode}
*
* @param errcode
* @return
*/
public static RestResponse fail(int errcode) {
RestResponse result = new RestResponse();
result.put(AppConstant.CODE, errcode);
return result;
}
}
8.編寫測試實體類
package com.chen.domain.entity;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "test_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long userId;
@Column(name = "user_name")
private String userName;
@Column(name = "age")
private Integer age;
}
註解說明:
@Entity //聲明實體類
@Table(name="") //建立實體類和表的映射關係
@Id//聲明當前私有屬性爲主鍵
@GeneratedValue(strategy=GenerationType.IDENTITY) //配置主鍵的生成策略
@Column(name="") //指定和表中字段的映射關係
9.編寫dao層接口,需要繼承 JpaRepository
package com.chen.dao;
import com.chen.domain.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@Repository
public interface UserDao extends JpaRepository<User,Long>, JpaSpecificationExecutor<User> {
}
說明:利用JPA規範,實現不用編寫數據庫代碼進行簡單的數據庫單表操作
10.編寫service業務層,調用dao層接口
package com.chen.service;
import com.chen.dao.UserDao;
import com.chen.domain.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
@Service
@Transactional
public class UserService {
@Autowired
private UserDao userDao;
/**
* 查詢所有數據
* @return
*/
public List<User> findAll(){
return userDao.findAll();
}
}
11.實現controller接口調用層
package com.chen.controller;
import com.chen.domain.entity.User;
import com.chen.restful.RestResponse;
import com.chen.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
/**
* 查詢所有用戶
* @return
*/
@RequestMapping("findAll")
public RestResponse findAll(){
List<User> all = userService.findAll();
return RestResponse.ok().msg("處理成功").item(all);
}
}
12.配置啓動類
package com.chen;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EntityScan(basePackages = "com.chen.domain.entity")
@EnableJpaRepositories(basePackages = "com.chen.dao")
public class ChenApplication {
public static void main(String[] args) {
SpringApplication.run(ChenApplication.class, args);
}
}