SpringBoot自定义注解(AOP切片)
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.0</version>
</dependency>
自定义注解
package com.licai.web.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @ClassName: IsBuyGood
* @Description:TODO(判断当前用户是否购买指定商品)
* @param url 未购买,跳转页面的相对路径
* @param request中需有goodsId
* @author: wd
* @date: 2020年3月20日 上午11:28:45
* 自定义注解
* 注解的声明:public @interface 注解名称
*
* 元注解:标记注解的注解
* @Documented:表示该注解会被javadoc命令写入api文档中
* @Target:注解的标记位置
* ElementType.ANNOTATION_TYPE:该注解可以标记别的注解
* ElementType.CONSTRUCTOR:标注到构造方法
* ElementType.FIELD:标注到成员属性
* ElementType.LOCAL_VARIABLE:标注到局部变量
* ElementType.METHOD:标注到方法上
* ElementType.PACKAGE:标注到包上
* ElementType.PARAMETER:标注到方法形参上
* ElementType.TYPE:标注到类、接口、枚举类上
* @Retention:注解的作用范围
* RetentionPolicy.SOURCE:注解的有效范围只在源码中,编译后就被丢弃
* RetentionPolicy.CLASS:注解有效范围在编译文件中,运行时丢弃
* RetentionPolicy.RUNTIME:注解在运行时仍然有效,这个范围的注解可以通过反射获取
*
* 注解内的方法声明:
* 类型 方法名() [defualt 默认值];
*
* 注意:
* 如果一个属性没有设置default默认值,在标记这个注解时,必须给定该属性值
* 如果一个属性的名字为value,则在赋值时可以省略属性名。当如果需要赋值两个以上的属性,则value不能省略
* 如果一个属性的类型是数组类型,则应该用{}赋值,如果只要给一个值,{}可以省略
*/
@Target(ElementType.METHOD)//作用范围,方法上
@Retention(RetentionPolicy.RUNTIME)//运行时
@Documented
public @interface IsBuyGood {
String url();
}
切面类
package com.licai.web.annotations.aspect;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.dubbo.config.annotation.Reference;
import com.app.dubboservice.order.service.DubboOrderService;
import com.app.order.model.Order;
import com.app.user.model.UserInfo;
import com.licai.web.annotations.IsBuyGood;
@Aspect
@Component
public class IsBuyGoodAspect {
@Reference(check = false)
private DubboOrderService dubboOrderService;
@Value("${spring.profiles.active}")
private String profile;
/**
* 环绕增强
* 判断controller的方法上有没有@IsLogin注解
* 如果有就对其进行增强
* 增强效果
* 1/给方法的形参列表User user 注入值
* 如果登录了就注入user
* 如果没登录就注入null
* 2.如果IsLogin的value=false表示不强制跳转到登录页面
* 3.如果IsLogin的value=true表示强制跳转到登录页面,一旦发现cookie中没有值直接跳转不允许执行目标方法
*/
@Around("@annotation(isBuyGood)")
//表达式代表所有路径下面的xxxController类中的方法带@IsLogin注解的
public Object isBuyGood(ProceedingJoinPoint proceedingJoinPoint,IsBuyGood isBuyGood) throws Throwable {
//获得request请求
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
HttpSession seesion = request.getSession();
Integer userId=null;
if(seesion!=null){
UserInfo userInfo = (UserInfo) seesion.getAttribute("loginUser");
if(userInfo!=null){
userId=userInfo.getUserId();
}
}
//表示已经登录或者不需要登录就可以继续操作
//获得形参列表
Object[] args = proceedingJoinPoint.getArgs();
boolean isBuy = false;
//因为登录后需要带returnUrl跳转到之前的页面,所以需要通过request对象获得url
String requestURL = request.getRequestURL().toString();
//带参数
//requestURL.append(request.getQueryString());
requestURL=requestURL.replace(request.getRequestURI(),"" );
String url=requestURL+request.getContextPath()+isBuyGood.url();
//解决中文乱码问题
// String url = URLEncoder.encode(requestURL.toString(), "utf-8");
//同样解决&带参数当做一个参数的问题
// url = url.replace("&","%26");
if(userId != null){
String goodId = request.getParameter("goodsId");// 商品id
if(userId!=null && !goodId.isEmpty()) {
Order order = dubboOrderService.queryUserGoodsOrder(Integer.parseInt(goodId),userId);
if(order!=null) {
isBuy = true;
}else {
isBuy = false;
}
if (profile != null && "dev".equals(profile)) {
// 测试环境
if("10898".equals(goodId)) {
isBuy = true;
}
}else {
if("11033".equals(goodId) || "11149".equals(goodId) || "11183".equals(goodId)) {
isBuy = true;
}
}
}
if(!isBuy) {
return "redirect:"+url;
}
//false继续执行目标方法
}
//执行目标方法 --- 带指定的形参列表
Object result = proceedingJoinPoint.proceed(args);
//执行目标方法后的方法返回值就是目标方法的返回值
return result;
}
}
使用
@RequestMapping("lianXi")
@IsBuyGood(url="/home")
public String lianXi() {
}
还没有评论,来说两句吧...