目录
1.1 分层结构
1.2 Result.java
1.3 Mybatis-plus配置
1.4 跨域配置
1.5 异常处理
1.6 Jwt工具类
1.7 Error码的封装
1.8 拦截器
1.9 线程池
2.0 日志
2.1 缓存
1.1 分层结构
dao
vo
service
1.2 Result.java
为返回结果做统一化处理
为返回结果做统一化处理
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Result {
private boolean success;
private int code;
private String msg;
private Object data;
public static Result success(Object data){
return new Result(true,200,"success",data);
}
public static Result fail(int code, String msg){
return new Result(false,code,msg,null);
}
}
1.3 Mybatis-plus配置
application.properies
#mybatis-plus
#打印日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#数据库表名前缀 ms_admin
mybatis-plus.global-config.db-config.table-prefix=ms_
mybatis-plus.mapper-locations=classpath*:mapper
//查询页数
Page page = new Page<>(pageParams.getPage(),pageParams.getPageSize());
//查询条件
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
//是否置顶
//按时间
queryWrapper.orderByDesc(Article::getWeight,Article::getCreateDate);
Page articlePage = articleMapper.selectPage(page, queryWrapper);
List records = articlePage.getRecords();
List articleVoList = copyList(records);
return Result.success(articleVoList);
}
mapper.xml文件位置
防止未build在
src/main/java ***.xml false
1.4 跨域配置
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
//跨域配置
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("
String account = loginParam.getAccount();
String password = loginParam.getPassword();
if(StringUtils.isBlank(account)||StringUtils.isBlank(password)){
return Result.fail(ErrorCode.PARAMS_ERROR.getCode(),ErrorCode.PARAMS_ERROR.getMsg());
}
System.out.println(loginParam);
String pwd = DigestUtils.md5Hex(password+slat);
System.out.println(pwd);
SysUser sysUser = sysUserService.findUser(account,pwd);
if(sysUser == null){
return Result.fail(ErrorCode.ACCOUNT_PWD_NOT_EXIST.getCode(),ErrorCode.ACCOUNT_PWD_NOT_EXIST.getMsg());
}
//登录成功,使用JWT生成token,返回token和redis中
String token = JwtUtils.createToken(sysUser.getId());
//过期时间是一百天
redisTemplate.opsForValue().set("TOKEN_"+token, JSON.toJSonString(sysUser),100, TimeUnit.DAYS);
return Result.success(token);
}
}
1.7 Error码的封装
public enum ErrorCode {
PARAMS_ERROR(10001,"参数有误"),
ACCOUNT_PWD_NOT_EXIST(10002,"用户名或密码不存在"),
TOKEN_ERROR(10003,"token不合法"),
ACCOUNT_EXIST(10004,"账号已存在"),
NO_PERMISSION(70001,"无访问权限"),
SESSION_TIME_OUT(90001,"会话超时"),
NO_LOGIN(90002,"未登录"),;
private int code;
private String msg;
ErrorCode(int code, String msg){
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
1.8 拦截器
WebMvcConfig定义的规则中有些路径可以直接访问,有些必须携带token才能访问,对于需要携带token才能访问的路径,需要在HandlerInterceptor中定义访问规则,return true 执行后边的操作return false执行到false这里停止
WebMvcConfig定义的规则中有些路径可以直接访问,有些必须携带token才能访问,对于需要携带token才能访问的路径,需要在HandlerInterceptor中定义访问规则,return true 执行后边的操作return false执行到false这里停止
新建一个handler包
import com.alibaba.fastjson.JSON;
import com.gzj.dao.pojo.SysUser;
import com.gzj.service.LoginService;
import com.gzj.vo.ErrorCode;
import com.gzj.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
@Slf4j
public class LoginHandler implements HandlerInterceptor {
@Autowired
private LoginService loginService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(!(handler instanceof HandlerMethod)){
return true;
}
String token = request.getHeader("Authorization");
log.info("=================request start===========================");
log.info("=================request start===========================");
String requestURI = request.getRequestURI();
log.info("request uri:{}",requestURI);
log.info("request method:{}",request.getMethod());
log.info("token:{}", token);
log.info("=================request end===========================");
if(StringUtils.isBlank(token)){
Result result = Result.fail(ErrorCode.NO_LOGIN.getCode(), "未登录");
//设置浏览器识别返回的是json
response.setContentType("application/json;charset=utf-8");
//https://www.cnblogs.com/qlqwjy/p/7455706.html response.getWriter().print()
//SON.toJSONString则是将对象转化为Json字符串
response.getWriter().print(JSON.toJSonString(result));
return false;
}
SysUser sysUser = loginService.checkToken(token);
if(sysUser == null){
Result result = Result.fail(ErrorCode.NO_LOGIN.getCode(), "未登录");
response.setContentType("application/json;charset=utf-8");
response.getWriter().print(JSON.toJSonString(result));
return false;
}
return true;
}
}
为了使拦截器生效,写一个配置类。
import com.gzj.handler.LoginHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
//跨域配置
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("
public class HttpContextUtils {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
/utils/IpUtils
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
@Log4j2
public class IpUtils {
public static String getIpAddr(HttpServletRequest request) {
String ip = null, unknown = "unknown", seperator = ",";
int maxLength = 15;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || unknown.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
log.error("IpUtils ERROR ", e);
}
// 使用代理,则获取第一个IP地址
if (StringUtils.isEmpty(ip) && ip.length() > maxLength) {
int idx = ip.indexOf(seperator);
if (idx > 0) {
ip = ip.substring(0, idx);
}
}
return ip;
}
public static String getIpAddr() {
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
return getIpAddr(request);
}
}
/aop/LogAspect
import com.alibaba.fastjson.JSON;
import com.gzj.utils.HttpContextUtils;
import com.gzj.utils.IpUtils;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
@Aspect
@Component
@Log4j2
public class LogAspect {
//定义切面
@Pointcut("execution(* com.gzj.controller.*.*(..))")
public void pointCut(){};
//环绕通知
@Around("pointCut()")
public Object log(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
recordLog(point, time);
return result;
}
private void recordLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
log.info("=====================log start================================");
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
log.info("request method:{}",className + "." + methodName + "()");
// //请求的参数
Object[] args = joinPoint.getArgs();
String params = JSON.toJSonString(args[0]);
log.info("params:{}",params);
//获取request 设置IP地址
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
log.info("ip:{}", IpUtils.getIpAddr(request));
log.info("excute time : {} ms",time);
log.info("=====================log end================================");
}
}
2.1 缓存
通过注解+切面实现
通过注解+切面实现
/cache/Cache.java
package com.mszlu.blog.common.cache;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface Cache {
long expire() default 1 * 60 * 1000;
String name() default "";
}
/cache/CacheAspect.java
package com.mszlu.blog.common.cache;
import com.alibaba.fastjson.JSON;
import com.mszlu.blog.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.time.Duration;
@Aspect
@Component
@Slf4j
public class CacheAspect {
@Autowired
private RedisTemplate redisTemplate;
@Pointcut("@annotation(com.mszlu.blog.common.cache.Cache)")
public void pt(){}
@Around("pt()")
public Object around(ProceedingJoinPoint pjp){
try {
Signature signature = pjp.getSignature();
//类名
String className = pjp.getTarget().getClass().getSimpleName();
//调用的方法名
String methodName = signature.getName();
Class[] parameterTypes = new Class[pjp.getArgs().length];
Object[] args = pjp.getArgs();
//参数
String params = "";
for(int i=0; i
test
@PostMapping("hot")
@Cache(expire = 5 * 60 * 1000,name = "hot_article")
public Result hotArticle(){
int limit = 5;
return articleService.hotArticle(limit);
}



