我已经定义了这个类方面适用于服务(除非用户具有角色MANAGER,否则不允许访问,但控制器没有限制(?)
@Aspect
public class DeviceAspect extends ServiceSupport {
@Pointcut("execution(* fo.belecam.services.client.ManageLicenseService.*(..))")
public void manage() {
}
@Pointcut("execution(* fo.belecam.services.client.AwardService.*(..))")
public void award() {
}
@Pointcut("execution(* fo.belecam.services.client.DeviceService.*(..))")
public void handleDeviceServiceMethod() {
}
@Pointcut("execution(* fo.belecam.controller.manage.ImportController.*(..))")
public void handleImportController() {
}
@Before("fo.belecam.services.aop.DeviceAspect.handleImportController() || fo.belecam.services.aop.DeviceAspect.handleDeviceServiceMethod() || fo.belecam.services.aop.DeviceAspect.manage() || fo.belecam.services.aop.DeviceAspect.award()")
@After ("fo.belecam.services.aop.DeviceAspect.handleImportController() || fo.belecam.services.aop.DeviceAspect.handleDeviceServiceMethod() || fo.belecam.services.aop.DeviceAspect.manage() || fo.belecam.services.aop.DeviceAspect.award()")
public void before(JoinPoint _jp) {
User user = getUser();
if(user == null || user.getUserRole() != UserRole.MANAGER) {
throw new NoSufficientRoleException(user == null ? null : user.getUserRole(), UserRole.MANAGER);
}
}
}
和ImportController:
@SuppressWarnings("deprecation")
public class ImportController extends AbstractFormController {
private String view;
private String successView;
@Autowired
protected UserService userService;
@Autowired
private ManageDeviceService manageDeviceService;
public String getView() {
return view;
}
public void setView(String view) {
this.view = view;
}
public String getSuccessView() {
return successView;
}
public void setSuccessView(String successView) {
this.successView = successView;
}
@Override
public ModelAndView processFormSubmission(final HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
final ModelAndView mav = new ModelAndView(getView());
FileUploadCommand file = (FileUploadCommand)command;
MultipartFile multipartFile = file.getFile();
if(multipartFile!=null && multipartFile.getSize()>0) {
Workbook workbook = Workbook.getWorkbook(multipartFile.getInputStream());
DataCollector dataCollector = new XLSDataCollector(workbook, true);
final List<Application> applications = manageDeviceService.loadApplications (dataCollector.getDataCollection());
List<ApplicationImporterError> importationErrors = manageDeviceService.validateApplications(applications);
savedApplications.add(manageDeviceService.getApplicationById(application.getId(), true));
}
return mav;
}
@Override
public ModelAndView showForm(HttpServletRequest request, HttpServletResponse arg1, BindException errors)
throws Exception {
return new ModelAndView(getView());
}
}
/**
* @param applications
* @param competentBody
* @return
* @throws Exception
*/
private List<Application> saveApplications(List<Application> applications,User user) throws Exception {
return manageDeviceService.saveImportedApplications (applications, user);
}
/**
* @param session
* @return
*/
public User getUser(HttpSession session) {
User user = (User) session.getAttribute(Const.SESSION_USER);
if (user == null) {
user = new User();
}
return user;
}
}
当我以UserRole.MANAGER身份登录时,调用(JoinPoint _jp)之前的方法,否则不是
我知道,当我只是在浏览器中粘贴网址时,不会调用之前的方法(JoinPoint _jp).... http://127.0.0.1:7001/devices/manage/import.do
答案 0 :(得分:1)
Spring的基于动态代理的AOP的一个限制是,它只能建议公共连接点 - 来自文档:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html
由于Spring的AOP框架基于代理的特性,根据定义,受保护的方法既不是针对JDK代理(这不适用),也不针对CGLIB代理(这在技术上可行,但不建议用于AOP)目的)。因此,任何给定的切入点都只能与公共方法匹配! 如果您的拦截需要包括受保护/私有方法甚至构造函数,请考虑使用Spring驱动的本机AspectJ编织而不是Spring的基于代理的AOP框架。这构成了具有不同特征的不同AOP使用模式,因此在做出决定之前一定要先熟悉编织。
您的许多控制器方法都是protected
,因此虽然您的控制器已注册为Spring bean(可能) - 但不建议使用非公共方法。
答案 1 :(得分:1)
我遇到了同样的问题,其中Repository的建议正在运行,但是对Controller的建议却没有。最后我找到了解决方案。简而言之,您需要确保在Servlet上下文中加载AOP定义,而不是在不同的上下文中加载。
就我而言,我的Spring AOP定义在tools-config.xml
中定义。从这里移动后
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/tools-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
到这里,
<servlet>
<servlet-name>petclinic</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc-core-config.xml, classpath:spring/tools-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
对Controller的建议正在发挥作用。
答案 2 :(得分:0)
问题可能在于控制器对象本身会调用您尝试拦截的方法(它们最初都受到保护),从抽象控制器直接调用其覆盖方法之一。 Spring AOP的工作方式是在对象周围创建一个拦截方法的代理,但只有在通过Spring注入的依赖从外部调用该方法时才有效。这不是这里的情况 - 因为该方法是从它自己的对象中调用的,所以该调用绕过了为“外部世界”包装对象的任何代理。