2015-03-30 28 views
5

Obecnie migrujemy projekt Struts 1.1 do Spring 4.x.Java - jak połączyć adnotacje walidacji i AOP i użyć go w kontrolerach Spring?

Pomyślnie przekonwertowaliśmy klasę Action na Controller i formbean na Model, a nawet jesteśmy w stanie przekonwertować sprawdzanie poprawności na Spring validation.

Ale mamy do czynienia z problemem, gdy próbujemy dodać AOP dla wszystkich kontrolerów. Celem jest dodanie dziennika do pomiaru czasu potrzebnego do wszystkich metod kontrolera.

poniżej fragment kodu,

@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"); 
    } 
} 

Używamy poniżej punktu-cut zastosowanie 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; 
    } 
} 

Albo Validation lub AOP pracuje naraz. Jeśli AOP nie zostanie zastosowane, to walidacja zostanie uruchomiona. Jeśli stosuje się tylko AOP, to jest on wyrzucany.

Czy ktoś może w tym pomóc?

Dzięki ...

+0

Jestem w stanie powtórzyć problem. Coś, co łamie sposób, w jaki używasz aspektów. Sprawdzasz rozwiązanie. Sprawdź, czy ten link Ci pomoże. http: //forum.spring.io/forum/spring-projects/web/64867-kontroler-połącz-z-aspektem-can-t-work .. – ArunM

Odpowiedz

0

Mam to działa. Musisz zrobić 2 zmiany.

Zmiana nr: 1

  1. Twoja definicja obrazu jest źle z jakiegoś powodu (Nie mam pojęcia dlaczego).. Ale poniższy aspekt zadziała.

    @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()); 
    } 
    

    }

Zmiana nr: 2

initBinder powinny być zadeklarowane jako publiczne. Obecnie zdefiniowano tę metodę jako prywatna. Ponownie nie jestem pewien, dlaczego to działa poprawnie bez aspektów.

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

2 zmiany będą działać.

+0

Dziękujemy za cenny komentarz. Niech sprawdzę –

0

W rzeczywistości wersja Aruna nie powinna mieć dużej różnicy poza czystością (jak w bardziej ogólnym) i bardziej szczegółową, chyba że Selvakumar ma na początku zły punkt. Ponieważ nie pokazuje nam żadnych nazw paczek dla aspektu lub kontrolera, jest to spekulatywne, ale może kontroler nie znajduje się bezpośrednio w pakiecie com.controller, ale w obrębie jakiegoś podpakietu. W tym przypadku punktu przekroju powinno być raczej

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

proszę nie podwójna kropka składnia .. co w przybliżeniu oznacza „obejmować dowolną liczbę poziomów sub-pakiet”.