日常踩坑系列(一)
记录生活中碰到的大大小小的坑,避免下次犯同样的错误。
1. AOP实现自定义注解
使用过滤器的时候想排除某些路径,但是网上搜了一下,好像没有这个功能,只能手动判断路径。我想更方便的使用,所有就准备自定义一个注解,实现排除路径的功能。
定义注解
@Target(ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ExcludeReqPath {
public String[] path();
}
1.@Target用来修饰注解,是注解的注解,称为元注解,表示当前定义的注解可以用在什么地方,类,方法或字段等。
2. @Retention也是元注解,表示定义的注解的生命周期。RetentionPolicy.SOURCE说明注解只保留在源文件,不会被编译成class文件。RetentionPolicy.CLASS说明注解会被编译成class文件,但运行时不存在。RetentionPolicy.RUNTIME说明注解会一直存在。
3. @Inherited是元注解,表示定义的注解可以被继承,即被定义的注解加在A类上,B类继承A类时会将被@Inherited标识过的注解一起继承。
4. @Documented表示该注解会被javadoc之类的工具记录,默认情况下javadoc不会记录注解。
AOP实现注解的功能
package com.knight.Utils.Annotation;
import com.alibaba.fastjson.JSONObject;
import com.knight.Bean.AjaxResponse;
import com.knight.Utils.MatchUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* Created by forget on 2019/9/8.
* 实现ExcludeReqPath注解
*/
@Aspect
@Component
public class HandleExcludeReqPath {
@Pointcut("@annotation(com.knight.Utils.Annotation.ExcludeReqPath)")
public void handleAnnotation() throws ClassNotFoundException {
}
@Around("handleAnnotation()")
public Object AroundHandler(ProceedingJoinPoint point) throws Throwable {
boolean pass=false;
Object object=null;
HttpServletResponse response=null;
HttpServletRequest request=null;
FilterChain chain=null;
for (Object o:point.getArgs()) {
if(o instanceof ServletRequest)
{
request= (HttpServletRequest) o;
}
else if(o instanceof ServletResponse)
{
response= (HttpServletResponse) o;
}
else if(o instanceof FilterChain)
{
chain= (FilterChain) o;
}
}
String path=request.getServletPath();
Class tag=point.getTarget().getClass();
for (Method m:tag.getMethods()) {
if(m.getName().equals("doFilter"))
{
String[] args=m.getAnnotation(ExcludeReqPath.class).path();
//匹配请求路径的方法
pass = MatchUtil.MatchPath(path,args);
break;
}
}
if(pass)
{
//路径匹配通过,跳过当前过滤器
chain.doFilter(request,response);
}
else
{
object= point.proceed();
}
return object;
}
}
- 使用@Pointcut注解定义切点,参数@annotation用于匹配当前执行方法持有指定注解的方法。
- 通过ProceedingJoinPoint类型的参数获得被注解的对象及执行方法的参数。然后获取注解的参数,校验请求路径是否被排除。如果匹配成功,则不执行目标方法。直接在目标方法的响应参数中,返回处理结果。
2.无法查询到数据
碰到一个很隐蔽的坑,找了一晚上才找到。使用mybatis查询远程数据库的数据,一直查询不到数据。多次检查代码都没有发现问题。并且连接查询本地数据库可以正常查询到数据。最终排查发现只有带有中文的关键词不能查询到数据,初步确定是字符集的问题,查看了两个数据库的编码集,果然发现两个数据库的编码集不一致,远程数据库的编码集并不是UTF8。
解决办法:修改远程数据库的字符集编码。
修改数据库的配置文件
ubuntu环境下Mysql5.7版本可以执行以下命令打开配置文件
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
在[mysqld]下添加一下代码
character-set-server=utf8
最后重启数据库即可。