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);
}
}