日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

spring AOP 之五:Spring MVC通过AOP切面编程来拦截controller

發(fā)布時(shí)間:2023/11/29 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring AOP 之五:Spring MVC通过AOP切面编程来拦截controller 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

示例1:通過包路徑及類名規(guī)則為應(yīng)用增加切面

該示例是通過攔截所有com.dxz.web.aop包下的以Controller結(jié)尾的所有類的所有方法,在方法執(zhí)行前后打印和記錄日志到數(shù)據(jù)庫。

新建一個(gè)springboot項(xiàng)目

1:首先定義maven

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.dxz.auth</groupId><artifactId>auth-demo1</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>auth-demo1</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.9.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc-portlet</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

2:在攔截controller之前需要自定義一個(gè)注解,該注解是放在需要通過AOP織入系統(tǒng)日志的方法上。

package com.dxz.web.aop;import java.lang.annotation.*;@Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SystemLog {String module() default "";String methods() default ""; }

3:定義記錄日志的切面

package com.dxz.web.aop;import java.lang.reflect.Method; import java.util.Date;import javax.servlet.http.HttpServletRequest;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes;@Component @Aspect public class LogAopAction {// 獲取開始時(shí)間private long BEGIN_TIME;// 獲取結(jié)束時(shí)間private long END_TIME;// 定義本次log實(shí)體private LogModel logModel = new LogModel();@Pointcut("execution(* com.dxz.web.aop.*Controller.*(..))")private void controllerMethodAspect() {}/*** 方法開始執(zhí)行*/@Before("controllerMethodAspect()")public void doBefore() {BEGIN_TIME = new Date().getTime();System.out.println("aop--開始");}/*** 方法結(jié)束執(zhí)行*/@After("controllerMethodAspect()")public void after() {END_TIME = new Date().getTime();System.out.println("aop--結(jié)束");}/*** 方法結(jié)束執(zhí)行后的操作*/@AfterReturning("controllerMethodAspect()")public void doAfter() {if (logModel.getState() == 1 || logModel.getState() == -1) {logModel.setActionTime(END_TIME - BEGIN_TIME);logModel.setGmtCreate(new Date(BEGIN_TIME));System.out.println("aop--將logModel="+logModel +",存入到數(shù)據(jù)庫");} else {System.out.println(logModel);System.out.println("aop-->>>>>>>>不存入到數(shù)據(jù)庫");}}/*** 方法有異常時(shí)的操作*/@AfterThrowing("controllerMethodAspect()")public void doAfterThrow() {System.out.println("aop--例外通知-----------------------------------");}/*** 方法執(zhí)行* * @param pjp* @return* @throws Throwable*/@Around("controllerMethodAspect()")public Object around(ProceedingJoinPoint pjp) throws Throwable {// 日志實(shí)體對(duì)象HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();// 獲取當(dāng)前登陸用戶信息String uid = request.getParameter("uid");if (uid == null) {logModel.setLoginAccount("—— ——");} else {logModel.setLoginAccount(uid);}// 攔截的實(shí)體類,就是當(dāng)前正在執(zhí)行的controllerObject target = pjp.getTarget();// 攔截的方法名稱。當(dāng)前正在執(zhí)行的方法String methodName = pjp.getSignature().getName();// 攔截的方法參數(shù)Object[] args = pjp.getArgs();// 攔截的放參數(shù)類型Signature sig = pjp.getSignature();MethodSignature msig = null;if (!(sig instanceof MethodSignature)) {throw new IllegalArgumentException("該注解只能用于方法");}msig = (MethodSignature) sig;Class[] parameterTypes = msig.getMethod().getParameterTypes();Object object = null;Method method = null;try {method = target.getClass().getMethod(methodName, parameterTypes);} catch (NoSuchMethodException e1) {// TODO Auto-generated catch block e1.printStackTrace();} catch (SecurityException e1) {// TODO Auto-generated catch block e1.printStackTrace();}if (null != method) {// 判斷是否包含自定義的注解,說明一下這里的SystemLog就是我自己自定義的注解if (method.isAnnotationPresent(SystemLog.class)) {SystemLog systemlog = method.getAnnotation(SystemLog.class);logModel.setModule(systemlog.module());logModel.setMethod(systemlog.methods());logModel.setLoginIp(getIp(request));logModel.setActionUrl(request.getRequestURI());try {object = pjp.proceed();logModel.setDescription("執(zhí)行成功");logModel.setState((short) 1);} catch (Throwable e) {// TODO Auto-generated catch blocklogModel.setDescription("執(zhí)行失敗");logModel.setState((short) -1);}} else {// 沒有包含注解object = pjp.proceed();logModel.setDescription("此操作不包含注解");logModel.setState((short) 0);}} else { // 不需要攔截直接執(zhí)行object = pjp.proceed();logModel.setDescription("不需要攔截直接執(zhí)行");logModel.setState((short) 0);}return object;}/*** 獲取ip地址* * @param request* @return*/private String getIp(HttpServletRequest request) {if (request.getHeader("x-forwarded-for") == null) {return request.getRemoteAddr();}return request.getHeader("x-forwarded-for");} }

?其中我的LogModel實(shí)體類如下:

package com.dxz.web.aop;import java.util.Date;public class LogModel {/**日志id */private Integer id;/** * 當(dāng)前操作人id */private String loginAccount;/**當(dāng)前操作人ip */private String loginIp;/**操作請(qǐng)求的鏈接 */private String actionUrl;/**執(zhí)行的模塊 */private String module;/**執(zhí)行的方法 */private String method;/**執(zhí)行操作時(shí)間 */private Long actionTime;/** 描述 */private String description;/** 執(zhí)行的時(shí)間 */private Date gmtCreate;/** 該操作狀態(tài),1表示成功,-1表示失敗! */private Short state;//set()/get() }

4:業(yè)務(wù)controller中增加@SystemLog注解

package com.dxz.web.aop;import javax.servlet.http.HttpServletRequest;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/user") public class LoginController {/*** 登錄方法* @param request* @return*/@RequestMapping(value="/toLogin", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})@SystemLog(methods="用戶管理", module = "用戶登錄")public String toLogin(HttpServletRequest request) {System.out.println("biz--登錄驗(yàn)證中");return "login";} }

5、springboot配置類

package com.dxz;import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.EnableAspectJAutoProxy;@SpringBootApplication @EnableAspectJAutoProxy @ComponentScan public class AuthDemo1Application {public static void main(String[] args) {new SpringApplicationBuilder(AuthDemo1Application.class).web(true).run(args);} }

啟動(dòng)springboot后,

通過瀏覽器訪問:http://localhost:8080/user/toLogin?uid=duanxz后的結(jié)果如下:

二、@Pointcut("execution(* com.dxz.web.aop.*Controller.*(..))")是“com.dxz.web.aop”包下所有以Controller結(jié)尾的類的所有方法,為了驗(yàn)證,我再增加2個(gè)controller如下:

package com.dxz.web.aop;import javax.servlet.http.HttpServletRequest;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/user") public class LogoutController {/*** 退出方法* @param request* @return*/@RequestMapping(value="/logout", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})@SystemLog(methods="用戶管理", module = "用戶退出")public String logout(HttpServletRequest request) {System.out.println("biz--退出邏輯");return "logout";} } package com.dxz.web.aop;import javax.servlet.http.HttpServletRequest;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/user") public class TestController2 {/*** test方法* @param request* @return*/@RequestMapping(value="/test", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})@SystemLog(methods="用戶管理", module = "用戶測試")public String test(HttpServletRequest request) {System.out.println("biz--test");return "test";} }

結(jié)果:

?示例2:通過within()指定所有@RestController注解類 +?@annotation()指定方法上有@Auth注解

package com.dxz.web.aop.auth;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;import org.springframework.core.Ordered; import org.springframework.core.annotation.Order;@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Order(Ordered.HIGHEST_PRECEDENCE) //優(yōu)先級(jí),暫定最高級(jí) public @interface Auth {boolean login() default false; }package com.dxz.web.aop.auth;import javax.servlet.http.HttpServletRequest;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component;@Aspect @Component public class AuthAopAction {@Before("within(@org.springframework.web.bind.annotation.RestController *) && @annotation(authParam)")public void requestLimit(JoinPoint joinPoint, Auth authParam) throws AuthException {HttpServletRequest request = null;try {Object[] args = joinPoint.getArgs();for (int i = 0; i < args.length; i++) {if (args[i] instanceof HttpServletRequest) {request = (HttpServletRequest) args[i];break;}}if (null == request) {System.out.println("auth handler error : target:[{}] no param : HttpServletRequest");throw new AuthException("HttpServletRequest is null error.");}if (null != authParam && authParam.login()) {// 登錄權(quán)限驗(yàn)證開啟//Object userId = request.getSession().getAttribute("uid");Object userId = request.getParameter("uid");if ("duanxz".equals(userId)) {System.out.println("賬號(hào)正確,成功登錄");} else {System.out.println("賬號(hào)不正確,需要重新登錄");throw new AuthException("NEED_LOGIN");}}} catch (Exception e) {System.out.println("auth handler error : exception:{}" + e.getMessage());throw e;}} } package com.dxz.web.aop.auth; public class AuthException extends Exception {private static final long serialVersionUID = -1341655401594111052L;public AuthException() {super();}public AuthException(String message) {super(message);}}

下面的交易controller用于是否登錄的權(quán)限驗(yàn)證

package com.dxz.web.aop;import javax.servlet.http.HttpServletRequest;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController;import com.dxz.web.aop.auth.Auth;@Controller @RestController @RequestMapping("/pay") public class PayController {@Auth(login = true)@RequestMapping(value="prePay", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})public String prePay(HttpServletRequest request) {String result = "預(yù)交易,uid=" + request.getParameter("uid");System.out.println(result);return result;} }

瀏覽器訪問:

http://localhost:8080/pay/prePay?uid=duanxz

及 ??http://localhost:8080/pay/prePay?uid=duanxz2的結(jié)果如下:

?

總結(jié)

以上是生活随笔為你收集整理的spring AOP 之五:Spring MVC通过AOP切面编程来拦截controller的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。