package com.atguigu.srb.core.controller.admin;
import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.R;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.core.pojo.entity.IntegralGrade;
import com.atguigu.srb.core.service.IntegralGradeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
*
* 积分等级表 前端控制器
*
*
* @author Likejin
* @since 2023-04-09
*/
@Api(tags="积分等级管理")
@CrossOrigin
@RestController
@RequestMapping("/admin/core/integralGrade")
public class AdminIntegralGradeController {
@Resource
private IntegralGradeService integralGradeService;
@ApiOperation("积分等级列表")
@GetMapping("/list")
public R listAll(){
List<IntegralGrade> list = integralGradeService.list();
return R.ok().data("list",list).message("获取列表成功");
}
@ApiOperation("根据ID删除数据记录")
@DeleteMapping("/remove/{id}")
public R removeById(
@ApiParam("数据id")
@PathVariable Long id){
boolean result = integralGradeService.removeById(id);
if(result){
return R.ok().message("删除成功");
}
return R.error().message("删除失败");
}
@ApiOperation("新增积分等级")
@PostMapping("/save")
public R save(
@ApiParam(value = "积分等级对象",required = true)
@RequestBody IntegralGrade integralGrade){
// if(integralGrade.getBorrowAmount()==null){
// throw new BusinessException(ResponseEnum.BORROW_AMOUNT_NULL_ERROR);
// }
Assert.notNull(integralGrade.getBorrowAmount(), ResponseEnum.BORROW_AMOUNT_NULL_ERROR);
boolean result = integralGradeService.save(integralGrade);
if(result){
return R.ok().message("保存成功");
}
return R.error().message("保存失败");
}
@ApiOperation("根据id获取积分等级")
@GetMapping("/get/{id}")
public R getById(
@ApiParam(value = "数据id",required = true)
@PathVariable Long id){
IntegralGrade integralGrade = integralGradeService.getById(id);
if(integralGrade != null){
return R.ok().data("record",integralGrade);
}
return R.error().message("数据获取失败");
}
@ApiOperation("修改积分等级")
@PutMapping("/update")
public R updateById(
@ApiParam(value = "积分等级对象",required = true)
@RequestBody IntegralGrade integralGrade){
boolean result = integralGradeService.updateById(integralGrade);
if(result){
return R.ok().message("更新成功");
}
return R.error().message("更新失败");
}
}
package com.atguigu.srb.core.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*
* 积分等级表 前端控制器
*
*
* @author Likejin
* @since 2023-04-09
*/
@Api(tags = "网站积分接口")
@RestController
@RequestMapping("/api/core/integralGrade")
public class IntegralGradeController {
@ApiOperation("测试接口")
@GetMapping("/test")
public void test(){
return;
}
}
package com.atguigu.srb.base.config;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Swagger2Config {
//生成admin分组
@Bean
public Docket adminApiConfig() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("adminApi")//增加分组
//增加分组的描述
.apiInfo(adminApiInfo())
.select()
//对路径为/admin的接口分到一组
.paths(Predicates.and(PathSelectors.regex("/admin/.*")))
.build();
}
private ApiInfo adminApiInfo(){
return new ApiInfoBuilder()
.title("尚融宝后台管理系统API文档")
.description("本文档描述了尚融宝管理系统各个接口的调用方式")
.contact(new Contact("like","www.baidu.com","[email protected]"))
.build();
}
//生成web分组
@Bean
public Docket webApiConfig() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("webApiInfo")
.apiInfo(adminApiInfo())
.select()
.paths(Predicates.and(PathSelectors.regex("/api/.*")))
.build();
}
private ApiInfo webApiInfo(){
return new ApiInfoBuilder()
.title("尚融宝网站API文档")
.description("本文档描述了尚融宝网站各个接口的调用方式")
.contact(new Contact("like","www.baidu.com","[email protected]"))
.build();
}
}
package com.atguigu.common.result;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
@Getter
@AllArgsConstructor
@ToString
public enum ResponseEnum {
SUCCESS(0, "成功"),
ERROR(-1, "服务器内部错误"),
//-1xx 服务器错误
BAD_SQL_GRAMMAR_ERROR(-101, "sql语法错误"),
SERVLET_ERROR(-102, "servlet请求异常"), //-2xx 参数校验
UPLOAD_ERROR(-103, "文件上传错误"),
EXPORT_DATA_ERROR(104, "数据导出失败"),
//-2xx 参数校验
BORROW_AMOUNT_NULL_ERROR(-201, "借款额度不能为空"),
MOBILE_NULL_ERROR(-202, "手机号码不能为空"),
MOBILE_ERROR(-203, "手机号码不正确"),
PASSWORD_NULL_ERROR(204, "密码不能为空"),
CODE_NULL_ERROR(205, "验证码不能为空"),
CODE_ERROR(206, "验证码错误"),
MOBILE_EXIST_ERROR(207, "手机号已被注册"),
LOGIN_MOBILE_ERROR(208, "用户不存在"),
LOGIN_PASSWORD_ERROR(209, "密码错误"),
LOGIN_LOKED_ERROR(210, "用户被锁定"),
LOGIN_AUTH_ERROR(-211, "未登录"),
USER_BIND_IDCARD_EXIST_ERROR(-301, "身份证号码已绑定"),
USER_NO_BIND_ERROR(302, "用户未绑定"),
USER_NO_AMOUNT_ERROR(303, "用户信息未审核"),
USER_AMOUNT_LESS_ERROR(304, "您的借款额度不足"),
LEND_INVEST_ERROR(305, "当前状态无法投标"),
LEND_FULL_SCALE_ERROR(306, "已满标,无法投标"),
NOT_SUFFICIENT_FUNDS_ERROR(307, "余额不足,请充值"),
PAY_UNIFIEDORDER_ERROR(401, "统一下单错误"),
ALIYUN_SMS_LIMIT_CONTROL_ERROR(-502, "短信发送过于频繁"),//业务限流
ALIYUN_SMS_ERROR(-503, "短信发送失败"),//其他失败
WEIXIN_CALLBACK_PARAM_ERROR(-601, "回调参数不正确"),
WEIXIN_FETCH_ACCESSTOKEN_ERROR(-602, "获取access_token失败"),
WEIXIN_FETCH_USERINFO_ERROR(-603, "获取用户信息失败"),
;
// 响应状态码
private Integer code;
// 响应信息
private String message;
}
package com.atguigu.common.result;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
@Data
public class R {
private Integer code;
private String message;
private Map<String, Object> data = new HashMap();
//全都返回R对象方便连续赋值
/**
* 构造器私有
*/
private R(){}
/**
* 返回成功
*/
public static R ok(){
R r = new R();
r.setCode(ResponseEnum.SUCCESS.getCode());
r.setMessage(ResponseEnum.SUCCESS.getMessage());
return r;
}
/**
* 返回失败
*/
public static R error(){
R r = new R();
r.setCode(ResponseEnum.ERROR.getCode());
r.setMessage(ResponseEnum.ERROR.getMessage());
return r;
}
/**
* @param responseEnum:
* @return R
* @author Likejin
* @description 设置特定的ResponseEnum
* @date 2023/4/9 13:35
*/
public static R setResult(ResponseEnum responseEnum){
R r = new R();
r.setCode(responseEnum.getCode());
r.setMessage(responseEnum.getMessage());
return r;
}
/**
* @param message:
* @return R
* @author Likejin
* @description 设置特定的message
* @date 2023/4/9 13:42
*/
public R message(String message){
this.setMessage(message);
return this;
}
/**
* @param code:
* @return R
* @author Likejin
* @description 设置特定的code
* @date 2023/4/9 13:42
*/
public R code(Integer code){
this.setCode(code);
return this;
}
/**
* @param key:
* @param value:
* @return R
* @author Likejin
* @description 给R的data赋值(key,value)
* @date 2023/4/9 13:37
*/
public R data(String key, Object value){
this.data.put(key, value);
return this;
}
/**
* @param map:
* @return R
* @author Likejin
* @description 给R的data赋值(map)
* @date 2023/4/9 13:46
*/
public R data(Map<String, Object> map){
this.setData(map);
return this;
}
}
分层异常
controller前异常,可能是参数封装异常等
controller后异常,可能是业务异常
异常可能出现
手动抛出异常
JVM抛出异常
解决方案
设置自定义异常(code+message匹配返回结果的枚举类)+断言类用于解决手动抛出异常。
异常处理
让异常出现的位置都跳转到统一异常处理器,打印日志让后台管理员维护,返回R对象
package com.atguigu.common.exception;
import com.atguigu.common.result.ResponseEnum;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class BusinessException extends RuntimeException {
//状态码
private Integer code;
//错误消息
private String message;
/**
*
* @param message 错误消息
*/
public BusinessException(String message) {
this.message = message;
}
/**
*
* @param message 错误消息
* @param code 错误码
*/
public BusinessException(String message, Integer code) {
this.message = message;
this.code = code;
}
/**
*
* @param message 错误消息
* @param code 错误码
* @param cause 原始异常对象
*/
public BusinessException(String message, Integer code, Throwable cause) {
super(cause);
this.message = message;
this.code = code;
}
/**
*
* @param resultCodeEnum 接收枚举类型
*/
public BusinessException(ResponseEnum resultCodeEnum) {
this.message = resultCodeEnum.getMessage();
this.code = resultCodeEnum.getCode();
}
/**
*
* @param resultCodeEnum 接收枚举类型
* @param cause 原始异常对象
*/
public BusinessException(ResponseEnum resultCodeEnum, Throwable cause) {
super(cause);
this.message = resultCodeEnum.getMessage();
this.code = resultCodeEnum.getCode();
}
}
package com.atguigu.common.exception;
import com.atguigu.common.result.ResponseEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
@Slf4j
public abstract class Assert {
/**
* 断言对象不为空
* 如果对象obj为空,则抛出异常
* @param obj 待判断对象
*/
public static void notNull(Object obj, ResponseEnum responseEnum) {
if (obj == null) {
log.info("obj is null...............");
throw new BusinessException(responseEnum);
}
}
/**
* 断言对象为空
* 如果对象obj不为空,则抛出异常
* @param object
* @param responseEnum
*/
public static void isNull(Object object, ResponseEnum responseEnum) {
if (object != null) {
log.info("obj is not null......");
throw new BusinessException(responseEnum);
}
}
/**
* 断言表达式为真
* 如果不为真,则抛出异常
*
* @param expression 是否成功
*/
public static void isTrue(boolean expression, ResponseEnum responseEnum) {
if (!expression) {
log.info("fail...............");
throw new BusinessException(responseEnum);
}
}
/**
* 断言两个对象不相等
* 如果相等,则抛出异常
* @param m1
* @param m2
* @param responseEnum
*/
public static void notEquals(Object m1, Object m2, ResponseEnum responseEnum) {
if (m1.equals(m2)) {
log.info("equals...............");
throw new BusinessException(responseEnum);
}
}
/**
* 断言两个对象相等
* 如果不相等,则抛出异常
* @param m1
* @param m2
* @param responseEnum
*/
public static void equals(Object m1, Object m2, ResponseEnum responseEnum) {
if (!m1.equals(m2)) {
log.info("not equals...............");
throw new BusinessException(responseEnum);
}
}
/**
* 断言参数不为空
* 如果为空,则抛出异常
* @param s
* @param responseEnum
*/
public static void notEmpty(String s, ResponseEnum responseEnum) {
if (StringUtils.isEmpty(s)) {
log.info("is empty...............");
throw new BusinessException(responseEnum);
}
}
}
具体controller中的断言+自定义异常
Assert.notNull(integralGrade.getBorrowAmount(), ResponseEnum.BORROW_AMOUNT_NULL_ERROR);
package com.atguigu.common.exception;
import com.atguigu.common.result.R;
import com.atguigu.common.result.ResponseEnum;
import lombok.extern.slf4j.Slf4j;
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.jdbc.BadSqlGrammarException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;
//执行方法的异常切面,所有方法自动调用,自动捕获所有异常
@Slf4j
@RestControllerAdvice
public class UnifielExceptionhandler {
//不灵活
@ExceptionHandler(value = Exception.class)
public R handleException(Exception e){
log.error(e.getMessage());
return R.error();
}
//定义特定的异常处理方式,繁琐
@ExceptionHandler(BadSqlGrammarException.class)
public R handleException(BadSqlGrammarException e){
log.error(e.getMessage(),e);
return R.setResult(ResponseEnum.BAD_SQL_GRAMMAR_ERROR);
}
/**
* @param e:
* @return R
* @author Likejin
* @description 自定义处理异常(利用状态码)
* @date 2023/4/9 14:41
*/
//返回R对象 code和message
@ExceptionHandler(BusinessException.class)
public R handleException(BusinessException e){
log.error(e.getMessage(),e);
return R.error().message(e.getMessage()).code(e.getCode());
}
/**
* Controller上一层相关异常,HTTP请求参数封装异常等
*/
@ExceptionHandler({
NoHandlerFoundException.class,
HttpRequestMethodNotSupportedException.class,
HttpMediaTypeNotSupportedException.class,
MissingPathVariableException.class,
MissingServletRequestParameterException.class,
TypeMismatchException.class,
HttpMessageNotReadableException.class,
HttpMessageNotWritableException.class,
MethodArgumentNotValidException.class,
HttpMediaTypeNotAcceptableException.class,
ServletRequestBindingException.class,
ConversionNotSupportedException.class,
MissingServletRequestPartException.class,
AsyncRequestTimeoutException.class
})
public R handleServletException(Exception e) {
log.error(e.getMessage(), e);
//SERVLET_ERROR(-102, "servlet请求异常"),
return R.error().message(ResponseEnum.SERVLET_ERROR.getMessage()).code(ResponseEnum.SERVLET_ERROR.getCode());
}
}
# 设置日志级别
logging:
level:
root: ERROR
<configuration>
<contextName>atguiguSrbcontextName>
<property name="log.path" value="F:/Project_shangrongbao/java/srb/srb-log" />
<property name="CONSOLE_LOG_PATTERN"
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) %highlight([%-5level]) %green(%logger) %msg%n"/>
<property name="FILE_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n" />
<property name="ENCODING"
value="UTF-8" />
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}pattern>
<charset>${ENCODING}charset>
encoder>
appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${log.path}/log.logfile>
<append>trueappend>
<encoder>
<pattern>${FILE_LOG_PATTERN}pattern>
<charset>${ENCODING}charset>
encoder>
appender>
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log-rolling.logfile>
<encoder>
<pattern>${FILE_LOG_PATTERN}pattern>
<charset>${ENCODING}charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/info/log-rolling-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<maxHistory>15maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1kbmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
rollingPolicy>
appender>
<springProfile name="dev,test">
<logger name="com.atguigu" level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING_FILE" />
logger>
springProfile>
<springProfile name="prod">
<logger name="com.atguigu" level="ERROR">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING_FILE" />
logger>
springProfile>
configuration>
spring:
profiles:
active: dev # 环境设置