自定义注解的方法及使用
统一token的校验
注解的定义说明
---------@定义注解---------
元注解
@Target({METHOD,TYPE})
表示这个注解可以用用在类/接口上,还可以用在方法上
@Retention(RetentionPolicy.RUNTIME)
表示这是一个运行时注解,即运行起来之后才能获取注解中的相关信息
@Inherited
表示这个注解可以被子类继承
@Documented
表示当执行javadoc的时候,本注解会生成相关文档定义后的使用:
该注解定义好了之后,使用的时候在类的上方加上@JDBCConfig(属性=""…)即可也可以使用这种注解的方法,效果是一样的
@Target(value = { ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@定义注解
/**
* 自定义注解
* @author 陌路
* @date 2022-03-19
* @apiNote
*/
@Inherited // 可继承
@Documented // 标记注解
@Target({METHOD,TYPE}) // 注解类型:方法注解还是类注解
@Retention(RetentionPolicy.RUNTIME) // 注解作用域
public @interface JDBCConfig {
String ip();
int port() default 3306;
String database();
String encoding();
String loginName();
String password();
}
@解析注解@使用注解
@使用注解
相关配置信息本来是以属性的方式存放的,现在改为了以注解的方式
@JDBCConfig(属性 = "值", 属性 = "值", 属性 = "值", 属性 = "值", 属性 = "值")
@解析注解: 通过反射,获取这个类上的注解对象
JDBCConfig jdbc= class.foraName(JDBCConfig .class);
拿到注解对象之后,通过其方法,获取各个注解元素的值:
/**
* @author 陌路
* @date 2022-03-19
* @apiNote
*/
@JDBCConfig(ip = "127.0.0.1", database = "db", encoding = "UTF-8", loginName = "root", password = "root")
public class DBUtil {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 通过反射获取这个注解对象和对应的属性值
public static void /*Connection*/ getConnection() throws SQLException, NoSuchMethodException, SecurityException {
// 拿到注解对象之后,通过其方法,获取各个注解元素的值:
JDBCConfig config = DBUtil.class.getAnnotation(JDBCConfig.class);
// 获取@JDBCConfig注解中的属性和值
String ip = config.ip();
int port = config.port();
String database = config.database();
String encoding = config.encoding();
String loginName = config.loginName();
String password = config.password();
// 查看获取到的属性和值
System.out.println(ip);
System.out.println(port);
System.out.println(database);
System.out.println(encoding);
System.out.println(loginName);
System.out.println(password);
// String url = String.format("jdbc:mysql://%s:%d/%s?characterEncoding=%s", ip, port, database, encoding);
// return DriverManager.getConnection(url, loginName, password);
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException, SQLException {
// Connection c = getConnection();
// System.out.println(c);
getConnection();
}
}
判断方法中是否存在指定注解
@Documented
//标记注解
@Target(ElementType.METHOD)
//指定作用在方法上 对方法拦截
@Retention(RetentionPolicy.RUNTIME)
//作用域 在运行时有效
NoAuthorization.java
import java.lang.annotation.*;
/**
* 包含该注解的方法 不需要校验token 直接放行
* @author 陌路
* @date 2022-03-19
* @apiNote token统一处理
*/
@Documented//标记注解
@Target(ElementType.METHOD) //指定作用在方法上 对方法拦截
@Retention(RetentionPolicy.RUNTIME) //作用域 在运行时有效
public @interface NoAuthorization {
/** ---------@定义注解---------
* 元注解
* @Target({METHOD,TYPE}) 表示这个注解可以用用在类/接口上,还可以用在方法上
* @Retention(RetentionPolicy.RUNTIME) 表示这是一个运行时注解,即运行起来之后,
* 才获取注解中的相关信息,而不像基本注解如@Override 那种。
* @Inherited 表示这个注解可以被子类继承
* @Documented 表示当执行javadoc的时候,本注解会生成相关文档(标记)
*
* 自定义注解的使用:
* 该注解定义好之后,将该注解加在方法上@NoAuthorization即可,
* 若注解中存在属性需要赋值,则直接可以在注解中赋值即可,
* eg:public @interface ZjObj{
* String name();
* Integer sex();
* }
* eg: @ZjObj(属性="值") -> @ZjObj(name="张三",sex=1)
*
* 也可这样定义注解,效果都是一样的
* @Target(value = { ElementType.ANNOTATION_TYPE })
* @Retention(RetentionPolicy.RUNTIME)
* @Inherited
* @Documented
*
* ---------@解析注解@使用注解---------
* * 若注解中有属性,则可以直接通过反射来获取属性值
* * 相关配置信息本来是以属性的方式存放的,现在改为了以注解的方式
* *
* * @解析注解: 通过反射,获取这个类上的注解对象
* * ZjObj zjObj = class.foraName(ZjObj.class);
* * 拿到注解对象之后,通过方法,获取各个注解元素的值:
* * String name = zjObj.name();
* * Integer sex = zjObj.sex ();
*/
}
通过拦截器 判断请求中方法中 是否包含自定义注解
根据自定义注解判断当前用户请求的方法是否需要校验token
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;
/**
* 请求拦截器 统一token校验
* @author 陌路
* @date 2022-03-19
* @apiNote 统一token校验
*/
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 如果 handler 是 HandlerMethod 类型,则把 handler(Object类型)转为HandlerMethod类型
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取将要访问的方法名,根据方法名获取方法上的 NoAuthorization 注解,判断该注解是否存在
NoAuthorization noAuthorization = handlerMethod
.getMethod()
.getAnnotation(NoAuthorization.class);
//若方法中存在该 NoAuthorization 注解,则表示无需校验 返回true
if (noAuthorization != null) {
return true;
}
}
//获取到请求头中的头信息(token)
String token = request.getHeader("Authorization");
//判断token是否存在
if (StringUtils.isNotEmpty(token)) {
//存在则根据token解析user数据
User user = this.userService.queryUserByToken(token);
//判断解析的user数据是否为null
if (null != user) {
//不为空 则将user信息存储到线程中
UserThreadLocal.set(user);
return true;
}
}
//若请求头中不存在Authorization 直接返回false 提示状态码401无权限
response.setStatus(401);
return false;
}
}