目录
全局监听请求:HandlerInterceptor
创建拦截器类
public class RequestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
...
TrackUtil.report(info); // 通过工具类调用服务
}
}
添加拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry interceptorRegistry) {
interceptorRegistry.addInterceptor(...); // 其他拦截器
interceptorRegistry.addInterceptor(new RequestInterceptor()); // 添加本拦截器
}
}
拦截器类调用Service服务
借助工具类
@Component
public class TrackUtil {
public static TrackUtil trackUtil; //声明对象
@Autowired //注入
TrackService trackService;
@PostConstruct //初始化
public void init() {
trackUtil = this;
trackUtil.trackService = this.trackService;
}
public static void report(Object info){
trackUtil.trackService.report(info);
}
}
全局异常处理:@ExceptionHandler
统一处理业务异常
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({ServletException.class})
@ResponseBody
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public JsonResult errorHandler1(HttpServletRequest request,
HttpServletResponse response,
Exception e) {
e.printStackTrace();
response.setCharacterEncoding("UTF-8");//防止返回中文乱码
return JsonResult.build(400, e.getMessage());
}
@ExceptionHandler({Exception.class})
@ResponseBody
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public JsonResult errorHandler(HttpServletRequest request,
HttpServletResponse response,
Exception e) {
e.printStackTrace();
response.setCharacterEncoding("UTF-8");//防止返回中文乱码
return JsonResult.build(500, e.getMessage());
}
}
自定义JsonResult
@Data
public class JsonResult {
private Integer code; //响应状态码
private String msg; //响应消息
private Object data; //响应数据
public JsonResult(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public JsonResult(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public static JsonResult build(Integer status, String msg, Object data) {
JsonResult jsonResult = new JsonResult(status, msg, data);
return jsonResult;
}
public static JsonResult build(Integer status, String msg) {
JsonResult jsonResult = new JsonResult(status, msg);
return jsonResult;
}
public static JsonResult ok( Object data) {
JsonResult jsonResult = new JsonResult(200, "success", data);
return jsonResult;
}
@Override
public String toString() {
JSONObject jsonObject=new JSONObject();
jsonObject.put("code",code);
jsonObject.put("msg",msg);
jsonObject.put("data",data);
return JSON.toJSONString(jsonObject);
}
}
全局跨域配置:WebMvcConfigurer
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
静态(static)方法中调用接口(Service层)
@Component
public class JwtUtil {
/**
* 静态方法调用非静态接口层(Service层)
*/
public static JwtUtil jwtUtil; //声明对象
@PostConstruct //初始化
public void init() {
jwtUtil = this;
jwtUtil.userService = this.userService;
}
@Autowired //注入
UserService userService;
public static boolean checkSign(String token) {
...
String username= jwtUtil.userService.getUsernameById(userId);
...
}
定时任务
package com.example.demo.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
@EnableScheduling //开启定时任务
@EnableAsync //开启多线程
@Slf4j
public class ScheduleAsync {
/** cron
* [秒] [分] [小时] [日] [月] [周] [年]
* 年非必须
* *每秒/分/小时/日...都会触发
* ?不指定值,只可用于日和周
* 1-3表示区间,1、2、3都会触发
* 5/15表示递增触发,从5开始,每15秒触发
* L表示最后一天或周六
*/
@Async
@Scheduled(cron = "0/10 * * * * ?")//从00开始每十秒
public void first(){
log.info(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
@Async
@Scheduled(cron = "0 0 2 * * ?")//每天半夜两点
public void second(){
log.info(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}
controller获取HttpServletRequest
在参数前增加HttpServletRequest request
public JsonResult updateFileds(HttpServletRequest request, @RequestParam String date...
获取用户真实IP
情况描述:前端使用容器借助nginx部署,request.getRemoteAddr()
无法获取真实ip。
nginx.conf反向代理增加header
设置
proxy_pass http://XXX;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
springboot获取X-Real-IP
,其中参数HttpServletRequest 可通过拦截器获取。
public static String getIpAddress(HttpServletRequest request) {
try {
String ip = request.getHeader("X-Real-IP");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
} catch (Exception e) {
return null;
}
}
异步处理
1、在启动类或实现类上增加@EnableAsync
注解
2、如果是简单实现:在需要的函数上增加@Async
注解,
@Async
public void func(
3、如果需要自定义配置:
@Configuration
@EnableAsync
@Slf4j
public class SyncConfiguration implements AsyncConfigurer {
@Bean(name = "asyncPoolTaskExecutor")
public ThreadPoolTaskExecutor executor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//核心线程数
taskExecutor.setCorePoolSize(12);
//线程池维护线程的最大数量,只有在缓冲队列满了之后才会申请超过核心线程数的线程
taskExecutor.setMaxPoolSize(24);
//缓存队列
taskExecutor.setQueueCapacity(50);
//许的空闲时间,当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
taskExecutor.setKeepAliveSeconds(60);
//异步方法内部线程名称
taskExecutor.setThreadNamePrefix("async-");
/**
* 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略
* 通常有以下四种策略:
* ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
* ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
* ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
* ThreadPoolExecutor.CallerRunsPolicy:重试添加当前的任务,自动重复调用 execute() 方法,直到成功
*/
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.initialize();
return taskExecutor;
}
@Override
public Executor getAsyncExecutor() {
return executor();
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) ->
log.error("线程池执行任务发送未知错误,执行方法:{}",method.getName(),ex);
}
}
4、自定义使用
@Async("asyncPoolTaskExecutor")
public void func(
并行处理
ExecutorService executor = Executors.newFixedThreadPool(2);
Callable<JSONObject> task1 = () -> {
...
return jsonObject;
};
Callable<JSONObject> task2 = () -> {{
...
return jsonObject;
};
Future<JSONObject> future1 = executor.submit(task1);
Future<JSONObject> future2 = executor.submit(task2);
arrayList.add(future1.get());
arrayList.add(future2.get());
executor.shutdown();
return arrayList;