Java - 如何组合验证和AOP注释并在Spring Controller中使用它?

时间:2015-03-30 07:09:54

标签: java spring validation spring-mvc aop

目前我们正在将Struts 1.1项目迁移到Spring 4.x.

我们已成功将Action类转换为Controller,并将formbean转换为Model,甚至我们也能将struts验证转换为Spring验证。

但是当我们尝试为所有控制器添加AOP时,我们遇到了一个问题。 目的是添加一个日志来测量所有控制器方法所需的时间。

下面的

是代码段,

@Component
@Controller
public class LoginController {

   @Autowired
       private LoginValidator loginValidator;

   @InitBinder
     private void initBinder(WebDataBinder binder) {
        binder.setValidator(loginValidator);
    }

   @RequestMapping(value = "/login", method = RequestMethod.POST)
  public String loginUser(@Valid @ModelAttribute Login form, BindingResult bindingResult) {
    System.out.println("Entering loginController.loginUser method");
   }
}

我们正在使用以下切入点来应用aop,

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;

@Component
@Aspect
public class Logging {

  @Pointcut("execution(* com.controller.*.*(..))")
  public void businessLogicMethods() {}

  @Around("businessLogicMethods()")
  public Object logAround(ProceedingJoinPoint jp) {

    System.out.println("around() is running!");
    System.out.println(jp.getSignature().getName());
    System.out.println(jp.getArgs());
    Object obj = null;
    try {
      obj = jp.proceed();
    } catch (Throwable e) {
      e.printStackTrace();
    }
    System.out.println("******");
    return obj;
  }
}

验证或AOP一次正在运行。如果未应用AOP,则触发验证。如果应用了aop,则仅触发AOP。

有人可以为此提供帮助吗?

...谢谢

2 个答案:

答案 0 :(得分:0)

我得到了这个工作。你必须做2次更改。

更改编号:1

  1. 您的Aspect定义由于某种原因是错误的。(不知道为什么)。但是下面的方面会起作用。

    @Component
    @Aspect
    public class Logging {
    
    static final Logger LOG = LoggerFactory.getLogger(Logging.class);
    
    @Pointcut("within(@org.springframework.stereotype.Controller *)")
    public void controller() {}
    
    @Pointcut("execution(* *(..))")
    public void methodPointcut() {}
    
    @Pointcut("within(@org.springframework.web.bind.annotation.RequestMapping *)")
    public void requestMapping() {}
    
    @Before("controller() && methodPointcut() && requestMapping()")
    public void aroundControllerMethod(JoinPoint joinPoint) throws Throwable {
        LOG.info("Invoked: " + niceName(joinPoint));
    }
    
    @AfterReturning("controller() && methodPointcut() && requestMapping()")
    public void afterControllerMethod(JoinPoint joinPoint) {
        LOG.info("Finished: " + niceName(joinPoint));
    }
    
    private String niceName(JoinPoint joinPoint) {
        return joinPoint.getTarget().getClass()
                + "#" + joinPoint.getSignature().getName()
                + "\n\targs:" + Arrays.toString(joinPoint.getArgs());
    }
    

    }

  2. 更改编号:2

    initBinder应声明为public。目前,您已将此方法定义为 私有 。我不知道为什么没有这些方面,这项工作正常。

       @InitBinder
         public void initBinder(WebDataBinder binder) {
            binder.setValidator(loginValidator);
         }
    

    这两项更改将有效。

答案 1 :(得分:0)

实际上,除非Selvakumar的切入点开头是错误的,否则Arun的版本除了更清洁(更一般)和更冗长之外不应该有很大的不同。因为他没有向我们展示方面或控制器的任何包名称,这是推测性的,但是控制器可能不直接位于包com.controller内,而是位于某个子包内。在这种情况下,切入点应该是

@Pointcut("execution(* com.controller..*(..))")

请注意,双点语法..大致意味着"包含任意数量的子包级别"。