[ SpringBoot ]
1. 统一异常处理
在util包中添加,在出现异常时,java后端会进行异常处理, 打印异常信息,就不需要在controller层进行try{}catch{}
package com.ffyc.news.util;
import com.ffyc.news.model.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
//基于AOP实现 全局 的统一异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 异常处理通知,当controller中的方法出现异常,执行该方法
*/
@ExceptionHandler(Exception.class)
public Result globalException(Exception e) {
Result commonResult = new Result(500,"服务器忙,请稍后再试",e.getMessage());
//测试期间
e.printStackTrace();
return commonResult;
}
}
2. 日志功能
1. 概述
日志可以对程序运行的过程进行检测,尤其在生产环境中,由于生产环境中没有控制台,需要把程序运行产生的一些数据存储到日志文件中,便于后期排查错误
2. 日志需要记录哪些信息(常问)
1.记录参数数据 例如进入某个方法,需要接受的参数,将参数进行保存
2.记录程序运行轨迹 进入不同的方法,打印不同日志 (先启动啥,然后初始化了啥,接下来干了啥.......)
3.记录异常信息
3. 如何添加日志
(1) 用IO流将异常 参数 步骤信息等输出到指定文件中
(2) 通过市面上的日志组件,实现日志保存功能
市面上常用的日志组件:
slf4j(Simple Logging Facade for Java)
commons-logging 接口
Log4J
Log4J2
Logback
JUL(Java Utils Logging
在applicantion.yml中添加日志配置
logging:
level:
com.ffyc.news: debug # 打印日志的文件 : 级别
file:
name: D:/log/log.log # 日志文件打印地址
日志的级别划分:debug<info<warn<error 日志会打印自身及以上级别的信息
方法一:
其余信息在 logback 配置文件中 在类中使用 ,创建 Logger 对象
private static Logger logger = LoggerFactory.getLogger(当前类名.class);
在需要的位置调用具体的日志级别方法输出
logger.debug("user account:{},user password:{}", user.getAccount(),user.getPassword());
logger.info("user account:{},user password:{}", user.getAccount(),user.getPassword());
logger.warn("user account:{},user password:{}", user.getAccount(),user.getPassword());logger.error("user account:{},user password:{}", user.getAccount(),user.getPassword());
package com.ffyc.news.web;
import com.ffyc.news.model.Admin;
import com.ffyc.news.model.Result;
import com.ffyc.news.service.LoginService;
import com.ffyc.news.util.JWTUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
//服务器
@RestController
@RequestMapping(path = "/api/loginCtl")
public class LoginController {
//日志定义
private static Logger logger = LoggerFactory.getLogger(LoginController.class);
@Autowired
private LoginService loginService;
@PostMapping(path="/login")
public Result login(@RequestBody Admin admin){
//日志打印
logger.info("enter login method");
logger.debug("login account:{},password:{}",admin.getAccount(),admin.getPassword());
logger.error("系统忙,请稍后再试");
//参数保存
admin = loginService.login(admin);
//System.out.println(1/0);
//判断登录是否成功
if(admin==null){
return new Result(201,"登录失败",null);
}else {
//登录成功,为管理员提供token
String token = JWTUtil.getToken(admin);//为当前admin提供一个token
admin.setToken(token);//将提供的token set到 admin对象里面
return new Result(200,"登录成功",admin);
}
}
@GetMapping(path = "/test")
public String test(){
System.out.println("test");
return "success";
}
/*
查询管理员菜单
*/
@GetMapping(path = "/menus")
public Result menus(@RequestHeader("token") String token){
ArrayList menus=loginService.menus(token);
return new Result(200,"查询成功",menus);
}
}
方法二: 使用 AOP 统一打印日志
导入依赖 jar
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
定义切面通知类
package com.ffyc.news.util;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Component
@Aspect
public class LogAspect {
private Logger logger = LoggerFactory.getLogger(LogAspect.class);
// 任意返回值 web包下任意类 任意方法
@Before("execution(public * com.ffyc.news.web.*.*(..))")
public void savelog(JoinPoint joinPoint) {
ServletRequestAttributes attributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Object[] objs = joinPoint.getArgs();//获取方法参数
logger.info("method args:{}", Arrays.toString(objs));
// 记录下请求内容
logger.info("HTTP_METHOD :{} ", request.getMethod());
logger.info("IP : {}", request.getRemoteAddr());//客户端 ip
}
}
3. 集成 Swagger 在线文档
1.概述
(1)api 文档: 目前开发是前后端分离的 ,后端开发人需要为前端开发人员提供一个api说明文档
(2)前提: 当代码修改时,也需要修改api文档 ,频繁修改文档,不方便
(3)Swagger好处:
使用Swagger可以直接通过代码生成文档,不需要自己手动编写接口文档
Swagger 生成的文档支持在线测试
(提供Web页面在线测试API参数和格式都定好了,直接在界面上输入参数的值即可在线测试)
本次使用 knife4j (前身swagger-bootstrap-ui)实现接口文档生成
文档访问地址:http://ip:端口/doc.html
2.导入jar依赖
<dependency>
<groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
3.添加配置类
package com.ffyc.news.config;
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.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
@Configuration//配置类,启动自动扫扫描
@EnableSwagger2WebMvc
public class Knife4jConfiguration {
@Bean(value = "dockerBean")
public Docket dockerBean() {
//指定使用Swagger2规范
Docket docket=new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
//描述字段支持Markdown语法
.description("# Knife4j RESTful APIs")
.termsOfServiceUrl("https://doc.xiaominfo.com/")
.contact("xiaoymin@foxmail.com")
.version("1.0")
.build())
//分组名称
.groupName("用户服务")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.ffyc.news.web"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
4. 注解介绍
Swagger 使用的注解及其说明
@Api:用在类上,说明该类的作用,tags 类的功能进行描述.
@Api(tags="用户登录控制器")
@ApiOperation:用在方法上,用于对方法功能说明。
@ApiOperation(value="方法概述")
@ApiImplicitParam:用来注解来给方法入参增加说明
@ApiModel:描述一个 Model 的信息(参数为实体类时使用)
@ApiModelProperty:描述一个 model 的属性
@ApiResponses:用于表示一组响应
@ApiResponse:用在@ApiResponses 中,一般用于表达响应信息
5. 测试
package com.ffyc.news.web;
//服务器
import com.ffyc.news.model.Admin;
import com.ffyc.news.model.Result;
import com.ffyc.news.service.LoginService;
import com.ffyc.news.util.JWTUtil;
import io.swagger.annotations.*;
import org.aspectj.apache.bcel.classfile.Code;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
@Api("管理登录处理器")
@RestController
@RequestMapping(path = "/api/loginCtl")
public class LoginController {
//日志定义
private static Logger logger = LoggerFactory.getLogger(LoginController.class);
@Autowired
private LoginService loginService;
@ApiOperation("管理员登录接口")
@ApiResponses({
@ApiResponse(code = 200,message = "响应成功"),
@ApiResponse(code = 200,message = "响应成功"),
@ApiResponse(code = 200,message = "响应成功"),
@ApiResponse(code = 200,message = "响应成功"),
})
@PostMapping(path="/login")
public Result login(@RequestBody Admin admin){
//日志打印
logger.info("enter login method");
logger.debug("login account:{},password:{}",admin.getAccount(),admin.getPassword());
logger.error("系统忙,请稍后再试");
//参数保存
admin = loginService.login(admin);
//System.out.println(1/0);
//判断登录是否成功
if(admin==null){
return new Result(201,"登录失败",null);
}else {
//登录成功,为管理员提供token
String token = JWTUtil.getToken(admin);//为当前admin提供一个token
admin.setToken(token);//将提供的token set到 admin对象里面
return new Result(200,"登录成功",admin);
}
}
@GetMapping(path = "/test")
public String test(){
System.out.println("test");
return "success";
}
/**
查询管理员菜单
*/
@ApiOperation("查询管理员权限菜单")
@ApiImplicitParams({
@ApiImplicitParam(name="token",value = "管理员token",required = true,type = "String")
})
@GetMapping(path = "/menus")
public Result menus(@RequestHeader("token") String token){
ArrayList menus=loginService.menus(token);
return new Result(200,"查询成功",menus);
}
}
文档访问地址:http://ip:端口/doc.html
4.定时任务
(1)实现方式:
方式 1: 使用 java 自带的 TimerTask,Timer
public static void main(String[] args) {
// 定义一个任务
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("打印当前时间:" + new Date());
}
};
// 计时器
Timer timer = new Timer();
// 开始执行任务 (延迟 1000 毫秒执行,每 3000 毫秒执行一次)
timer.schedule(timerTask, 1000, 3000);
}
方式 2: 使用 spring 框架中提供的定时任务
a.开启定时任务
在 SpringBoot 的启动类上声明 @EnableScheduling
b.添加定时任务
只需使用@Scheduled 注解标注即可,Spring Boot 启动后会自动加载并执行定时任务,无需手动操作
@Component
public class TestTask {
@Scheduled(cron = "*/6 * * * * ?")//每六秒执行一次
private void process() {
System.out.println("现在时间:" + new Date());
}
}
https://cron.qqe2.com


更多推荐




所有评论(0)