全栈开发之后端脚手架:SpringBoot集成MybatisPlus代码生成,分页,雪花算法,统一响应,异常拦截(1)

《MySql面试专题》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySql性能优化的21个最佳实践》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

《MySQL高级知识笔记》

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

文中展示的资料包括:**《MySql思维导图》《MySql核心笔记》《MySql调优笔记》《MySql面试专题》《MySql性能优化的21个最佳实践》《MySq高级知识笔记》**如下图

全网火爆MySql 开源笔记,图文并茂易上手,阿里P8都说好

关注我,点赞本文给更多有需要的人

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

public static final CodeMsg SUCCESS =new CodeMsg(HttpStatus.OK.value(), “success”);

public static final CodeMsg BAD_REQUEST = new CodeMsg(HttpStatus.BAD_REQUEST.value(), “请求无效”);

public static final CodeMsg SERVER_ERROR = new CodeMsg(HttpStatus.INTERNAL_SERVER_ERROR.value(), “服务端异常”);

public static final CodeMsg NO_HANDLER_FOUND = new CodeMsg(HttpStatus.NOT_FOUND.value(), “未找到对应资源”);

public static final CodeMsg UNAUTHORIZED = new CodeMsg(HttpStatus.UNAUTHORIZED.value(), “未认证或登录状态过期”);

public static final CodeMsg FORBIDDEN = new CodeMsg(HttpStatus.FORBIDDEN.value(), “未授权”);

// 自定义错误码

public static final CodeMsg PARAMETER_ERROR = new CodeMsg(4000, “参数不正确!”);

/用户相关:验证码/

public static final CodeMsg CAPTCHA_EXPIRED = new CodeMsg(4001, “验证码不存在或已过期”);

public static final CodeMsg CAPTCHA_INVALID = new CodeMsg(4002, “验证码错误”);

/用户相关:认证授权/

public static final CodeMsg BAD_CREDENTIAL = new CodeMsg(4003, “用户名或密码错误”);

public static final CodeMsg ACCOUNT_NOT_FOUND = new CodeMsg(4004, “账号不存在”);

public static final CodeMsg ACCOUNT_NOT_ACTIVATED = new CodeMsg(4005, “账号未激活”);

// 限流

public static final CodeMsg RATE_LIMIT = new CodeMsg(4006,“达到阈值啦!”);

// 熔断

public static final CodeMsg DEGRADE = new CodeMsg(4007,“熔断啦!”);

public static CodeMsg error(String msg){

return new CodeMsg(HttpStatus.BAD_REQUEST.value(),msg);

}

public CodeMsg(int code, String msg) {

this.code = code;

this.msg = msg;

}

}

全局异常拦截

2022-01-22-Exception.jpg

默认拦截所有异常(也可自定义异常进行封装),同样通过 RestControllerAdvice 注解,实现对异常响应的统一封装。

  • RestExceptionHandler.java

@Slf4j

@RestControllerAdvice

public class RestExceptionHandler {

@ExceptionHandler(Exception.class)

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)

public Result exception(Exception e) {

log.error(“Global exception: {}”, null == e.getMessage() ? e.toString() : e.getMessage(), e);

return Result.error(CodeMsg.SERVER_ERROR.getCode(), null == e.getMessage() ? e.toString() : e.getMessage());

}

}

CRUD的Controller

@RestController

@RequestMapping(“book”)

@Api(tags = “测试Controller”)

public class BookController {

@Autowired

IBookService bookService;

@GetMapping(“hello”)

@ApiOperation(“哈喽”)

public String hello() {

return “hello everyone.”;

}

@GetMapping(“list”)

public List list() {

return bookService.list();

}

@PostMapping(“save”)

public boolean save(@RequestBody Book book) {

return bookService.save(book);

}

@GetMapping(“detail/{id}”)

public Result detail(@PathVariable long id) {

return Result.success(bookService.getById(id));

}

@GetMapping(“error”)

public Result error() {

int value = 8 / 0;

return Result.success(value);

}

@GetMapping(“page”)

public Result<IPage> page(@RequestParam(defaultValue = “0”) Integer page, @RequestParam(defaultValue = “10”) Integer size, @RequestParam Map<String, Object> params) {

QueryWrapper queryWrapper = new QueryWrapper<>();

queryWrapper.likeRight(“read_date”, params.get(“readDate”));

IPage list = bookService.page(new Page<>(page, size),queryWrapper);

return Result.success(list);

}

}

Swagger3接口文档

2022-01-22-Swagger3.jpg

  • 引入依赖

io.springfox

springfox-boot-starter

${swagger.version}

  • 配置类

@Configuration

@EnableOpenApi

public class SwaggerConfig {

private static final String VERSION = “1.0.0”;

@Bean

public Docket createRestApi() {

return new Docket(DocumentationType.OAS_30)

.apiInfo(apiInfo())

.select()

.apis(RequestHandlerSelectors.basePackage(“com.heartsuit.readingnotes.controller”))

.paths(PathSelectors.any())

.build();

}

private ApiInfo apiInfo() {

return new ApiInfoBuilder()

.title(“SpringBoot+Swgger3.0后端服务接口文档”)

.contact(new Contact(“Heartsuit”, “https://blog.csdn.net/u013810234”, “454670286@qq.com”))

.description(“基于Swagger3.0生成的接口文档”)

.termsOfServiceUrl(“https://blog.csdn.net/u013810234”)

.license(“The Apache License, Version 2.0”)

.licenseUrl(“http://www.apache.org/licenses/LICENSE-2.0.html”)

.version(VERSION)

.build();

}

}

  • 在控制器以及接口上添加注解

@Api(tags = “测试Controller”)

@RestController

public class HelloController {

@GetMapping(“hello”)

@ApiOperation(“哈喽”)

public String hello() {

return “Hello SpringBoot with Swagger3.0”;

}

}

  • 启动服务,浏览器访问

没错,再没其他额外的注解了,直接启动服务,然后在浏览器访问即可。

Note:

  • Swagger2.x的访问地址:http://localhost:8000/swagger-ui.html

  • Swagger3.0的访问地址:http://localhost:8000/swagger-ui/index.html

  • 控制生成文档的开关

实际中我们的接口文档只会在开发环境下使用,所以一般我们会在生产环境下关闭文档。

  • application.yml

spring:

profiles:

active: dev

  • application-dev.yml

springfox:

documentation:

enabled: true

  • application-prod.yml

springfox:

documentation:

enabled: false

遇到的问题

  • 问题1:控制台打印MyBatisPlusSQL日志

解决方法:

mybatis-plus:

configuration:

log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

  • 问题2:Long类型的雪花算法ID传到前端后精度丢失

解决方法:在后端 JSON 返回前统一将 Long 转为字符串。

@Configuration

public class JacksonConfig {

@Bean

public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {

ObjectMapper objectMapper = builder.createXmlMapper(false).build();

SimpleModule simpleModule = new SimpleModule();

simpleModule.addSerializer(Long.class, ToStringSerializer.instance);

objectMapper.registerModule(simpleModule);

return objectMapper;

}

}

  • 问题3:全局异常处理时多个异常处理器匹配顺序

解决方法:

如下,除了全局拦截的所有异常 Exception 之外,还有一个自定义的异常 CustomException ,那么,当出现 CustomException 时,当前两个异常该如何匹配呢?答案是子类异常处理器优先,即会被 customException 方法拦截,而不会被 exception 方法拦截。

@Slf4j

@RestControllerAdvice

public class RestExceptionHandler {

@ExceptionHandler(Exception.class)

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)

public Result exception(Exception e) {

log.error(“Global exception: {}”, null == e.getMessage() ? e.toString() : e.getMessage(), e);

return Result.error(CodeMsg.SERVER_ERROR.getCode(), null == e.getMessage() ? e.toString() : e.getMessage());

}

@ExceptionHandler(CustomException.class)

@ResponseStatus(HttpStatus.BAD_REQUEST)

public Result customException(CustomException e) {

log.error(“Custom exception: {}”, null == e.getMessage() ? e.toString() : e.getMessage(), e);

return Result.error(e.getCode(), null == e.getMessage() ? e.toString() : e.getMessage());

}

}

@Getter

public class CustomException extends RuntimeException {

private static final long serialVersionUID = 1L;

private Integer code;

public CustomException(CodeMsg codeMsg) {

super(codeMsg.getMsg());

this.code = codeMsg.getCode();

}

public CustomException(Integer code, String msg){

super(msg);

this.code = code;

}

}

  • 问题4:访问Swagger地址时报错:Unable to infer base url. This is common when using dynamic servlet registration or when the API is behind an API Gateway. The base url is the root of where all the swagger resources are served. For e.g. if the api is available at http://example.org/api/v2/api-docs then the base url is http://example.org/api/. Please enter the location manually

解决方法:

原因是我们使用 RestControllerAdvice 统一处理接口响应,导致给Swagger的返回值也包装了一层,最终在浏览器无法解析、渲染页面。

@RestControllerAdvice 改为: @RestControllerAdvice(basePackages = "com.heartsuit.*.controller")

即限制 RestControllerAdvice 的拦截范围,仅处理指定包下的接口响应。

项目依赖

<java.version>11</java.version>

<mybatisplus.version>3.3.1</mybatisplus.version>

<swagger.version>3.0.0</swagger.version>

org.springframework.boot

spring-boot-starter

org.springframework.boot

spring-boot-starter-web

mysql

mysql-connector-java

runtime

com.alibaba

druid-spring-boot-starter

1.1.21

com.baomidou

mybatis-plus-boot-starter

${mybatisplus.version}

io.springfox

springfox-boot-starter

${swagger.version}

org.springframework.boot

spring-boot-devtools

runtime

true

org.projectlombok

lombok

true

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-maven-plugin

org.projectlombok

lombok

配置文件

server:

port: 8000

spring:

datasource:

type: com.alibaba.druid.pool.DruidDataSource

driverClassName: com.mysql.cj.jdbc.Driver

druid:

url: jdbc:mysql://localhost:3306/reading_notes?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false

username: root

password: root

最后

本人也收藏了一份Java面试核心知识点来应付面试,借着这次机会可以送给我的读者朋友们:

目录:

二面蚂蚁金服(交叉面),已拿offer,Java岗定级阿里P6

Java面试核心知识点

一共有30个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!

二面蚂蚁金服(交叉面),已拿offer,Java岗定级阿里P6

Java面试核心知识点

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

配置文件

server:

port: 8000

spring:

datasource:

type: com.alibaba.druid.pool.DruidDataSource

driverClassName: com.mysql.cj.jdbc.Driver

druid:

url: jdbc:mysql://localhost:3306/reading_notes?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useSSL=false

username: root

password: root

最后

本人也收藏了一份Java面试核心知识点来应付面试,借着这次机会可以送给我的读者朋友们:

目录:

[外链图片转存中…(img-gA94gCzM-1715502528707)]

Java面试核心知识点

一共有30个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!

[外链图片转存中…(img-OvYTCHEt-1715502528708)]

Java面试核心知识点

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值