前言
一.准备工作
1.1注入sql (数据准备)
-- 建表SQL
create database if not exists java_blog_spring charset utf8mb4;
USE java_blog_spring;
-- 用户表
DROP TABLE IF EXISTS java_blog_spring.user;
CREATE TABLE java_blog_spring.user(
`id` INT NOT NULL AUTO_INCREMENT,
`user_name` VARCHAR ( 128 ) NOT NULL,
`password` VARCHAR ( 128 ) NOT NULL,
`github_url` VARCHAR ( 128 ) NULL,
`delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id ),
UNIQUE INDEX user_name_UNIQUE ( user_name ASC )) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '用户表';
-- 博客表
drop table if exists java_blog_spring.blog;
CREATE TABLE java_blog_spring.blog (
`id` INT NOT NULL AUTO_INCREMENT,
`title` VARCHAR(200) NULL,
`content` TEXT NULL,
`user_id` INT(11) NULL,
`delete_flag` TINYINT(4) NULL DEFAULT 0,
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now(),
PRIMARY KEY (id))
ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表';
-- 新增用户信息
insert into java_blog_spring.user (user_name, password,github_url)values("zhangsan","123456","https://gitee.com/bubble-fish666/class-java45");
insert into java_blog_spring.user (user_name, password,github_url)values("lisi","123456","https://gitee.com/bubble-fish666/class-java45");
insert into java_blog_spring.blog (title,content,user_id) values("第一篇博客","111我是博客正文我是博客正文我是博客正文",1);
insert into java_blog_spring.blog (title,content,user_id) values("第二篇博客","222我是博客正文我是博客正文我是博客正文",2);
1.2创建项目
1.3配置文件
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&useSSL=false
username: root
password: weigang527
driver-class-name: com.mysql.cj.jdbc.Driver
mvc:
favicon:
enable: false
profiles: #多平台配置
active: dev
# 设置 Mybatis 的 xml 保存路径
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
configuration: # 配置打印 MyBatis 执行的 SQL
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true #自动驼峰转换
# 配置打印 MyBatis 执行的 SQL
logging:
file:
name: logs/springboot.log
1.4测试
点击启动类看项目是否启动成功
二.项目公共模块
2.1公共层(三层架构)
2.2实体类
在model层写实体类
1.用户实体(User Info)
package com.example.demo.model;
import lombok.Data;
import java.util.Date;
@Data
public class UserInfo {
private Integer id;
private String userName;
private String password;
private String githubUrl;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
2.博客实体(BlogInfo)
package com.example.demo.model;
import lombok.Data;
import java.util.Date;
@Data
public class BlogInfo {
private Integer id;
private String title;
private String content;
private Integer userId;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
3.结果实体(Result)
3.1使用枚举
package com.example.demo.enums;
public enum ResultStatus {
SUCCESS,
FAIL,
NOLOGIN;
}
3.2创建结果实体类
package com.example.demo.model;
import com.example.demo.enums.ResultStatus;
import lombok.Data;
@Data
public class Result<T> {
//业务码 200-成功 -1 失败 -2 未登录
private ResultStatus code;
//错误信息
private String errMsg;
//接口响应的数据
private T data;
public static <T> Result<T> success(T data){
Result result = new Result();
result.setCode(ResultStatus.SUCCESS);
result.setErrMsg("");
result.setData(data);
return result;
}
public static <T> Result<T> fail(String errMsg){
Result result = new Result();
result.setCode(ResultStatus.FAIL);
result.setErrMsg(errMsg);
result.setData(null);
return result;
}
public static <T> Result<T> fail(String errMsg, T data){
Result result = new Result();
result.setCode(ResultStatus.FAIL);
result.setErrMsg(errMsg);
result.setData(data);
return result;
}
}
代码解读:
这个Result<T>
类是一个泛型类,用于封装API接口的响应结果。它包含了三个主要属性:业务码(code
)、错误信息(errMsg
)和接口响应的数据(data
)。这个类使用了Lombok库的@Data
注解来自动生成getter和setter方法,以及equals
、hashCode
和toString
方法,从而简化了代码量。
Result<T>
类定义了一个泛型T
,这意味着它可以携带任何类型的数据作为响应体。这对于构建RESTful API特别有用,因为你可以根据API的不同需求返回不同类型的数据。
类中定义了三个静态方法,用于快速创建Result
实例:
-
success(T data)
:这个方法用于创建表示操作成功的Result
实例。它设置业务码为ResultStatus.SUCCESS
(假设这是一个表示成功的枚举值),错误信息为空字符串,并将传入的数据作为响应数据。 -
fail(String errMsg)
:这个方法用于创建表示操作失败的Result
实例,但不包含任何响应数据。它设置业务码为ResultStatus.FAIL
(假设这是一个表示失败的枚举值),设置传入的错误信息,并将响应数据设置为null
。 -
fail(String errMsg, T data)
:这个方法也是用于创建表示操作失败的Result
实例,但与上一个方法不同,它允许你传入一个额外的数据对象作为响应体。这在你需要向客户端返回一些额外信息(尽管操作失败了)时非常有用。它同样设置业务码为ResultStatus.FAIL
,并设置传入的错误信息和数据。
2.3统一结果返回
创建一个接口来会接收实体类的统一结果返回
1.统一结果返回:
package com.example.demo.config;
import com.example.demo.model.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return false;
}
@SneakyThrows
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof Result){
return body;
}
if (body instanceof String){
return objectMapper.writeValueAsString(Result.success(body));
}
return Result.success(body);
}
}
代码解读:
这段代码定义了一个ResponseAdvice
类,它实现了Spring MVC的ResponseBodyAdvice
接口,用于在控制器方法返回响应体之前对其进行全局处理。具体来说,这个类的作用是在每个控制器方法的响应体被写出之前,检查响应体的类型,如果不是Result
类型(这是一个自定义的封装了响应结果、业务码和错误信息的类),则将其包装成Result
类型,以确保所有对外暴露的API响应都遵循统一的格式。
2.4统一异常处理
2.统一异常处理:
代码:
package com.example.demo.config;
import com.example.demo.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.resource.NoResourceFoundException;
@Slf4j
@ResponseBody
@ControllerAdvice
public class ExceptionHandle {
@ExceptionHandler
public Result handle(Exception e){
log.error("发生异常, e:", e);
return Result.fail("内部错误, 请联系管理员");
}
@ExceptionHandler
public Result handle(NoResourceFoundException e){
log.error("文件不存在:", e.getMessage());
return Result.fail("内部错误, 请联系管理员");
}
}