700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Spring中自定义注解支持SpEl表达式(仅限在AOP中使用)

Spring中自定义注解支持SpEl表达式(仅限在AOP中使用)

时间:2019-05-26 05:10:01

相关推荐

Spring中自定义注解支持SpEl表达式(仅限在AOP中使用)

大家平时在写代码的时候,安全方面一般都会考虑使用Shiro或者SpringSecurity,他们其中提供了很多注解可以直接使用,很方便,那么今天就来重复造个小轮子,如果不用他们的,自己在项目中如何基于注解利用SpEl表达式来控制权限呢。下面我们上代码

首先我们定义了一个异常类,代码如下:

public class NoPermissionException extends RuntimeException {/*** */private static final long serialVersionUID = 626463678812588L;public NoPermissionException() {super();}/** Constructs a new runtime exception with the specified detail message.* The cause is not initialized, and may subsequently be initialized by a* call to {@link #initCause}.** @param message the detail message. The detail message is saved for*later retrieval by the {@link #getMessage()} method.*/public NoPermissionException(String message) {super(message);}/*** Constructs a new runtime exception with the specified detail message and* cause. <p>Note that the detail message associated with* {@code cause} is <i>not</i> automatically incorporated in* this runtime exception's detail message.** @param message the detail message (which is saved for later retrieval* by the {@link #getMessage()} method).* @param cause the cause (which is saved for later retrieval by the* {@link #getCause()} method). (A <tt>null</tt> value is* permitted, and indicates that the cause is nonexistent or* unknown.)* @since 1.4*/public NoPermissionException(String message, Throwable cause) {super(message, cause);}}

在看看我们的自定义注解,这个注解直接复制的SpringSecurity中的注解

/** Copyright 2002- the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.xzm.annotations;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** Annotation for specifying a method access-control expression which will be evaluated to* decide whether a method invocation is allowed or not.** @author Luke Taylor* @since 3.0*/@Target({ ElementType.METHOD, ElementType.TYPE })@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic @interface PreAuthorize {/*** @return the Spring-EL expression to be evaluated before invoking the protected* method*/String value();}

Controller层的代码如下:

@RequestMapping(value = "/index")@PreAuthorize("#msg == 'abc'")public List<User> helloApi(String msg) {List<User> users = userMapper.selectList();System.out.println(users);return users;}

下面我们来看AOP层面的代码定义

package com.xzm.aop;import java.lang.reflect.Method;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.core.DefaultParameterNameDiscoverer;import org.springframework.expression.EvaluationContext;import org.springframework.expression.Expression;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.expression.spel.support.StandardEvaluationContext;import org.ponent;import com.xzm.annotations.PreAuthorize;import com.xzm.exceptions.NoPermissionException;@Aspect@Componentpublic class SpelEnhance {/*** 用于SpEL表达式解析.*/private SpelExpressionParser parser = new SpelExpressionParser();/*** 用于获取方法参数定义名字.*/private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();@Around("@annotation(com.xzm.annotations.PreAuthorize)")public Object around(ProceedingJoinPoint p) throws Throwable {MethodSignature sign = (MethodSignature) p.getSignature();Method method = sign.getMethod();PreAuthorize preAuthorize = method.getAnnotation(PreAuthorize.class);if (preAuthorize == null) {return p.proceed();}String value = preAuthorize.value();String resV = generateKeyBySpEL(value, p);if (resV.equals("true")) {return p.proceed();}throw new NoPermissionException("无权限访问");}public String generateKeyBySpEL(String spELString, ProceedingJoinPoint joinPoint) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod());Expression expression = parser.parseExpression(spELString);EvaluationContext context = new StandardEvaluationContext();Object[] args = joinPoint.getArgs();for (int i = 0; i < args.length; i++) {context.setVariable(paramNames[i], args[i]);}return expression.getValue(context).toString();}}

以上基本上就完了,主要是这段代码

public String generateKeyBySpEL(String spELString, ProceedingJoinPoint joinPoint) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod());Expression expression = parser.parseExpression(spELString);EvaluationContext context = new StandardEvaluationContext();Object[] args = joinPoint.getArgs();for (int i = 0; i < args.length; i++) {context.setVariable(paramNames[i], args[i]);}return expression.getValue(context).toString();}

用来解析SpEl表达式,解析成功后把结果返回。有兴趣的可以在下面评论,技术问题可以私聊我

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。