解决spring mvc设置controller切面无效

 

maven 的pem.xml配置

<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.1.1.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.1.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.9</version>
    </dependency>
      <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjrt</artifactId>
          <version>1.8.9</version>
      </dependency>

 

在applicationContext.xml 配置

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">


       <!-- 扫描除controller以外的注解-->
    <context:component-scan base-package="com">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

 

在spring-mvc.xml 一定要加入aop:aspectj-autoproxy, 不要把这个配置加在applicationContext.xml ,否则不起作用

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:task="http://www.springframework.org/schema/task"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <!-- 自动扫描且只扫描@Controller -->
    <context:component-scan base-package="com" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <!-- 找到事务无用的问题,问题出在设置了两次context:component 查找了一样的类。
    如这里之前是只这样设置<context:component-scan base-package="com"/>,但这样会跟application-mybatis.xml里的
    <context:component-scan base-package="com">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
    设置的查找类的范围相冲突,也就是它找一遍上面设置过的类,这样就会把事务的AOP去掉        
    -->
    <!--把代理从jdk交换给aspect切面代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    

方法1:

然后写一个java代码切面

package com.core.controlleraop;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
* 切面 ,记录日志
*/
@Slf4j
@Aspect
@Component
public class ControllerAspect {

    @Before(value = "execution(public * com.test.controller.*.*(..))")
    public void beforeMethod(JoinPoint point) {
        System.out.println("------test aop before");
    }
    @Pointcut("execution(* com.hkps.*.controller.*.*(..)) || execution(* com.hkps.*.*.controller.*.*(..)) || execution(* com.test.controller.*Controller.*(..))") //
    public void controllerMethods() {
    }

    /**
     * ** 支持get POST 的提交,但不支持formData提交
     */
    @Around("controllerMethods()&& args(.., @RequestBody requestBody)") //
    public Object aroundControllerMethods(ProceedingJoinPoint joinPoint, Object requestBody) throws Throwable { //
        // 在这里获取到 POST 请求体中的参数
        // requestBody 就是 POST 请求体中的参数
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String reqUrl=request.getServletPath();
        String data = getFormData(joinPoint, request, requestBody); //
        log.warn("ControllerAspect aroundControllerMethods url:{},body:{}",reqUrl,data);
        Date startDate = new Date();
        try {
            // 执行原始方法
            Object result = joinPoint.proceed();

            // 可以对原始方法的返回值进行拦截和修改

            return result;
        } catch (Throwable e) {
            log.error("aroundControllerMethods url:{},errormsg:{},e :{}",reqUrl,e.getMessage(),e);
            // 处理异常情况
            throw e;
        } finally {
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getResponse();
            Date endDate = new Date();
            Long costTime = endDate.getTime() - startDate.getTime();  //耗时
            int status= response.getStatus();

//            if(response!=null&&status==HttpServletResponse.SC_OK){
//                log.info("aroundControllerMethods url:{},Response Status Code:{},Response Body:{},cost :{} ",reqUrl,status,response.getWriter().toString(),costTime);
//            }else{
                log.info("aroundControllerMethods url:{},Response Status Code:{},cost :{} ",reqUrl,status,costTime);
//            }
//
//            // 获取并处理Response对象
//            System.out.println("Response Status Code: " + response.getStatus());
//            System.out.println("Response Content Type: " + response.getContentType());
//            System.out.println("Response Body: " + response.getWriter().toString());
//            //写入日志到数据库
//            int responseStatue = response.getStatus();
//
        }
    }

//    /**
//     * 解决前端用formData提交没有记录日志问题 ,注意MultipartFile 在方法中的参数一定要放在最后面,不然参数位置不对,会没反应
//     */
//    @Around("controllerMethods() && args(.., mulList)")
//    public Object aroundControllerMethods2(ProceedingJoinPoint joinPoint, @RequestPart List<MultipartFile> mulList) throws Throwable {
//        // 在这里获取到 POST 请求体中的参数
//        // requestBody 就是 POST 请求体中的参数
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        String data = getFormData(joinPoint, request, null);
//        log.info("url:{},body:{}",request.getServletPath(),data);
//        Date startDate = new Date();
//        try {
//            // 执行原始方法
//            Object result = joinPoint.proceed();
//
//            // 可以对原始方法的返回值进行拦截和修改
//
//            return result;
//        } catch (Exception e) {
//            // 处理异常情况
//            throw e;
//        } finally {
//            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
//                    .getResponse();
//            Date endDate = new Date();
//            Long costTime = endDate.getTime() - startDate.getTime();  //耗时
//            log.info("url:{},Response Status Code:{},Response Body:{},cost :{} ",request.getServletPath(),response.getStatus(),response.getWriter().toString(),costTime);
////            // 获取并处理Response对象
////            System.out.println("Response Status Code: " + response.getStatus());
////            System.out.println("Response Content Type: " + response.getContentType());
////            System.out.println("Response Body: " + response.getWriter().toString());
////            //写入日志到数据库
////            int responseStatue = response.getStatus();
//
//        }
//    }
//

    /**             * 解决前端后端特殊类处理        */
//            @Around("controllerMethods() && args(.., reqVo)")
//            public Object aroundControllerMethods3(ProceedingJoinPoint joinPoint, BaseFormData reqVo) throws Throwable {
//                // 在这里获取到 POST 请求体中的参数
//                // requestBody 就是 POST 请求体中的参数
//                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//                String data=getFormData(joinPoint,request,requestBody);
//                Date startDate=new Date();
//                 try {
//                // 执行原始方法
//                Object result = joinPoint.proceed();
//
//                // 可以对原始方法的返回值进行拦截和修改
//
//                return result;
//                } catch (Exception e) {
//                    // 处理异常情况
//                    throw e;
//                } finally {
//                    HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse()
//
//                    Date endDate=new Date();
//                    // 获取并处理Response对象
//                    System.out.println("Response Status Code: " + response.getStatus());
//                    System.out.println("Response Content Type: " + response.getContentType());
//                    System.out.println("Response Body: " + response.getWriter().toString());
//                    //写入日志到数据库
//                    int responseStatue=response.getStatus();
//                    Long costTime=endDate.getTime()-startDate.getTime();  //耗时
//                }
//            }  


    /**
     * * 获取POST GET的data数据 * @param request * @return大
     */
    public static String getFormData(ProceedingJoinPoint joinPoint, HttpServletRequest request, Object requestBody) {
        if ("POST".equalsIgnoreCase(request.getMethod())) {
            if (existFileUpload(request)) {
                Map<String, Object> mapData = new HashMap<>();
                request.getParameterMap().entrySet().stream().forEach(entry -> {
                    mapData.put(entry.getKey(), entry.getValue());
                });
                return JSONObject.toJSONString(mapData);
            } else {
                if (requestBody == null) {
                    Object[] args = joinPoint.getArgs();
                    if (args != null && args.length > 0) {
                        List<Object> newArgs = new ArrayList<>();
                        for (Object arg : args) {
                            if (arg instanceof HttpServletRequest) {

                            } else if (arg instanceof BindingResult) {

                            } else {
                                newArgs.add(arg);
                            }
                        }
                        return JSONObject.toJSONString(newArgs);
                    }
                } else if (requestBody instanceof BeanPropertyBindingResult) {
                    return JSONObject.toJSONString(((BeanPropertyBindingResult) requestBody).getTarget());
                } else if (requestBody instanceof MultipartHttpServletRequest) {
                    Enumeration<String> parameterNames = request.getParameterNames();
                    Map<String, String> map = new HashMap<>();
                    while (parameterNames.hasMoreElements()) {
                        String paramName = (String) parameterNames.nextElement();
                        String paramValue = request.getParameter(paramName);
                        map.put(paramName, paramValue);
                    }
                    return JSONObject.toJSONString(map);
                } else if( requestBody instanceof BindingAwareModelMap){
                    Map<String,Object> map=(BindingAwareModelMap) requestBody;
                    Map<String,Object> newmap=new HashMap<>();
                    for(Map.Entry<String,Object> mapentry : map.entrySet()){
                        if( mapentry.getValue() instanceof BeanPropertyBindingResult){

                        }else{
                            newmap.put(mapentry.getKey(),mapentry.getValue());
                        }
//                        if(!"org.springframework.validation.BindingResult.user".equals(mapentry.getKey()) ){
//                            newmap.put(mapentry.getKey(),mapentry.getValue());
//                        }
                    }
                    return JSONObject.toJSONString(newmap);
                }else {
                    return "{}";
                    //return JSONObject.toJSONString(requestBody);
                }
            }
        }

        String data = request.getParameterMap().entrySet().stream().map(entry -> {
            String result;
            String[] value = entry.getValue();
            if (value != null && value.length > 1) {
                result = Arrays.stream(value).map(s -> entry.getKey() + "=" + s).collect(Collectors.joining("&"));
            } else {
                result = entry.getKey() + "=" + value[0];
            }
            return result;
        }).collect(Collectors.joining("&"));
        return data;
    }

    /***是否是上传文件* @param request* @return*/
    static boolean existFileUpload(HttpServletRequest request) {
        String contentType = request.getContentType();
        if (contentType != null && (contentType.startsWith("multipart/") || contentType.contains("boundary="))) {
            return true; // 是上传文件的诗求

        } else {
            return false; // 不是上传文件的请求
        }

    }
}

方法2:在spring-mvc.xml加上一个bean切面

   <bean id="controllerAspect" class="com.core.controllaop.ControllerAspect"></bean>
    <aop:config proxy-target-class="true">
        <aop:aspect id="webContronllerAspect" ref="controllerAspect">
            <aop:pointcut id="printController"
                          expression="execution(* com.test.controller.*.*(..))"/>
            <aop:around method="aroundControllerMethods"
                        pointcut-ref="printController"/>

        </aop:aspect>
    </aop:config>

然后再代码里面加上

package com.core.controlleraop;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
* 切面 ,记录日志
*/
@Slf4j
public class ControllerAspect {

    public void beforeMethod(JoinPoint point) {
        System.out.println("------test aop before");
    }

    /**
     * ** 支持get POST 的提交,但不支持formData提交
     */
    public Object aroundControllerMethods(ProceedingJoinPoint joinPoint) throws Throwable { //
        // 在这里获取到 POST 请求体中的参数
        // requestBody 就是 POST 请求体中的参数
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String reqUrl=request.getServletPath();
        String data = getFormData(joinPoint, request, null); //
        log.warn("ControllerAspect aroundControllerMethods url:{},body:{}",reqUrl,data);
        Date startDate = new Date();
        try {
            // 执行原始方法
            Object result = joinPoint.proceed();

            // 可以对原始方法的返回值进行拦截和修改

            return result;
        } catch (Throwable e) {
            log.error("aroundControllerMethods url:{},errormsg:{},e :{}",reqUrl,e.getMessage(),e);
            // 处理异常情况
            throw e;
        } finally {
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getResponse();
            Date endDate = new Date();
            Long costTime = endDate.getTime() - startDate.getTime();  //耗时
            int status= response.getStatus();

//            if(response!=null&&status==HttpServletResponse.SC_OK){
//                log.info("aroundControllerMethods url:{},Response Status Code:{},Response Body:{},cost :{} ",reqUrl,status,response.getWriter().toString(),costTime);
//            }else{
                log.info("aroundControllerMethods url:{},Response Status Code:{},cost :{} ",reqUrl,status,costTime);
//            }
//
//            // 获取并处理Response对象
//            System.out.println("Response Status Code: " + response.getStatus());
//            System.out.println("Response Content Type: " + response.getContentType());
//            System.out.println("Response Body: " + response.getWriter().toString());
//            //写入日志到数据库
//            int responseStatue = response.getStatus();
//
        }
    }

//    /**
//     * 解决前端用formData提交没有记录日志问题 ,注意MultipartFile 在方法中的参数一定要放在最后面,不然参数位置不对,会没反应
//     */
//    @Around("controllerMethods() && args(.., mulList)")
//    public Object aroundControllerMethods2(ProceedingJoinPoint joinPoint, @RequestPart List<MultipartFile> mulList) throws Throwable {
//        // 在这里获取到 POST 请求体中的参数
//        // requestBody 就是 POST 请求体中的参数
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        String data = getFormData(joinPoint, request, null);
//        log.info("url:{},body:{}",request.getServletPath(),data);
//        Date startDate = new Date();
//        try {
//            // 执行原始方法
//            Object result = joinPoint.proceed();
//
//            // 可以对原始方法的返回值进行拦截和修改
//
//            return result;
//        } catch (Exception e) {
//            // 处理异常情况
//            throw e;
//        } finally {
//            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
//                    .getResponse();
//            Date endDate = new Date();
//            Long costTime = endDate.getTime() - startDate.getTime();  //耗时
//            log.info("url:{},Response Status Code:{},Response Body:{},cost :{} ",request.getServletPath(),response.getStatus(),response.getWriter().toString(),costTime);
////            // 获取并处理Response对象
////            System.out.println("Response Status Code: " + response.getStatus());
////            System.out.println("Response Content Type: " + response.getContentType());
////            System.out.println("Response Body: " + response.getWriter().toString());
////            //写入日志到数据库
////            int responseStatue = response.getStatus();
//
//        }
//    }
//

    /**             * 解决前端后端特殊类处理        */
//            @Around("controllerMethods() && args(.., reqVo)")
//            public Object aroundControllerMethods3(ProceedingJoinPoint joinPoint, BaseFormData reqVo) throws Throwable {
//                // 在这里获取到 POST 请求体中的参数
//                // requestBody 就是 POST 请求体中的参数
//                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//                String data=getFormData(joinPoint,request,requestBody);
//                Date startDate=new Date();
//                 try {
//                // 执行原始方法
//                Object result = joinPoint.proceed();
//
//                // 可以对原始方法的返回值进行拦截和修改
//
//                return result;
//                } catch (Exception e) {
//                    // 处理异常情况
//                    throw e;
//                } finally {
//                    HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse()
//
//                    Date endDate=new Date();
//                    // 获取并处理Response对象
//                    System.out.println("Response Status Code: " + response.getStatus());
//                    System.out.println("Response Content Type: " + response.getContentType());
//                    System.out.println("Response Body: " + response.getWriter().toString());
//                    //写入日志到数据库
//                    int responseStatue=response.getStatus();
//                    Long costTime=endDate.getTime()-startDate.getTime();  //耗时
//                }
//            }  


    /**
     * * 获取POST GET的data数据 * @param request * @return大
     */
    public static String getFormData(ProceedingJoinPoint joinPoint, HttpServletRequest request, Object requestBody) {
        if ("POST".equalsIgnoreCase(request.getMethod())) {
            if (existFileUpload(request)) {
                Map<String, Object> mapData = new HashMap<>();
                request.getParameterMap().entrySet().stream().forEach(entry -> {
                    mapData.put(entry.getKey(), entry.getValue());
                });
                return JSONObject.toJSONString(mapData);
            } else {
                if (requestBody == null) {
                    Object[] args = joinPoint.getArgs();
                    if (args != null && args.length > 0) {
                        List<Object> newArgs = new ArrayList<>();
                        for (Object arg : args) {
                            if (arg instanceof HttpServletRequest) {

                            } else if (arg instanceof BindingResult) {

                            } else {
                                newArgs.add(arg);
                            }
                        }
                        return JSONObject.toJSONString(newArgs);
                    }
                } else if (requestBody instanceof BeanPropertyBindingResult) {
                    return JSONObject.toJSONString(((BeanPropertyBindingResult) requestBody).getTarget());
                } else if (requestBody instanceof MultipartHttpServletRequest) {
                    Enumeration<String> parameterNames = request.getParameterNames();
                    Map<String, String> map = new HashMap<>();
                    while (parameterNames.hasMoreElements()) {
                        String paramName = (String) parameterNames.nextElement();
                        String paramValue = request.getParameter(paramName);
                        map.put(paramName, paramValue);
                    }
                    return JSONObject.toJSONString(map);
                } else if( requestBody instanceof BindingAwareModelMap){
                    Map<String,Object> map=(BindingAwareModelMap) requestBody;
                    Map<String,Object> newmap=new HashMap<>();
                    for(Map.Entry<String,Object> mapentry : map.entrySet()){
                        if( mapentry.getValue() instanceof BeanPropertyBindingResult){

                        }else{
                            newmap.put(mapentry.getKey(),mapentry.getValue());
                        }
//                        if(!"org.springframework.validation.BindingResult.user".equals(mapentry.getKey()) ){
//                            newmap.put(mapentry.getKey(),mapentry.getValue());
//                        }
                    }
                    return JSONObject.toJSONString(newmap);
                }else {
                    return "{}";
                    //return JSONObject.toJSONString(requestBody);
                }
            }
        }

        String data = request.getParameterMap().entrySet().stream().map(entry -> {
            String result;
            String[] value = entry.getValue();
            if (value != null && value.length > 1) {
                result = Arrays.stream(value).map(s -> entry.getKey() + "=" + s).collect(Collectors.joining("&"));
            } else {
                result = entry.getKey() + "=" + value[0];
            }
            return result;
        }).collect(Collectors.joining("&"));
        return data;
    }

    /***是否是上传文件* @param request* @return*/
    static boolean existFileUpload(HttpServletRequest request) {
        String contentType = request.getContentType();
        if (contentType != null && (contentType.startsWith("multipart/") || contentType.contains("boundary="))) {
            return true; // 是上传文件的诗求

        } else {
            return false; // 不是上传文件的请求
        }

    }
}

 

 

感谢  springAop不能切入controller层的解决方法  给的想法

posted @ 2024-07-09 23:33  ☆♂安♀★  阅读(72)  评论(0编辑  收藏  举报