如何从控制器分离逻辑并使用注释将其放入某个处理程序?(How to detach logic from controllers and put it to some handler using annotations?)

在我们的项目中,我们已经有了一些必要的控制器,我的任务是让它更容易。 它应该像这样工作:我只是在控制器下面放一个注释,一个处理程序完成它的所有工作。 我已经拥有的东西:

/** * This annotation marks collector methods */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Collect { } @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Collectors { /** * An array of subclasses that can load and provide values for * generating a ModelMap. */ Class<?>[] value(); }

我找不到任何示例如何做到这一点。 控制器示例:

@Controller public class TestController { private final SchoolService schoolService; private final TeacherService teacherService; public TestController(SchoolService schoolService, TeacherService teacherService) { this.schoolService = schoolService; this.teacherService = teacherService; } /** * Saves the static list of users in model and renders it * via freemarker template. * * @param model * @return The index view (FTL) */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/freemarkertest", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model) { List<SchoolDTO> schoolList = new ArrayList<SchoolDTO>(); schoolList = schoolService.findAll(); model.addAttribute("schoolList", schoolList); return "freemarkertest"; } /** * Add a new School * * @param schoolDTO * @return Redirect back to same /freemarkertest page to display school list, if successful */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/freemarkertest/add", method = RequestMethod.POST) public String add(@ModelAttribute("schoolDTO") SchoolDTO schoolDTO) { if(schoolDTO.getName() != null && !schoolDTO.getName().isEmpty() && schoolDTO.getEnabled() != null) { schoolService.save(schoolDTO); return "redirect:"; } else { return "redirect:error"; //TODO: create error page } } /** * Get list of teachers. * * @param model * @param schoolId * @return The index view (FTL) */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/teachers/{schoolId}", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model, @PathVariable Long schoolId) { List<TeacherDTO> teachers = teacherService.getAllBySchoolId(schoolId); model.addAttribute("teachersList", teachers); model.addAttribute("schoolId", schoolId); return "teachers"; } }

In our project we already have some necessary controllers and my task is to make it easier. It should work like this: I just put an annotation under a controller and a handler do all its job. What I already have:

/** * This annotation marks collector methods */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Collect { } @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Collectors { /** * An array of subclasses that can load and provide values for * generating a ModelMap. */ Class<?>[] value(); }

I can't find any example how to do it. Controller example:

@Controller public class TestController { private final SchoolService schoolService; private final TeacherService teacherService; public TestController(SchoolService schoolService, TeacherService teacherService) { this.schoolService = schoolService; this.teacherService = teacherService; } /** * Saves the static list of users in model and renders it * via freemarker template. * * @param model * @return The index view (FTL) */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/freemarkertest", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model) { List<SchoolDTO> schoolList = new ArrayList<SchoolDTO>(); schoolList = schoolService.findAll(); model.addAttribute("schoolList", schoolList); return "freemarkertest"; } /** * Add a new School * * @param schoolDTO * @return Redirect back to same /freemarkertest page to display school list, if successful */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/freemarkertest/add", method = RequestMethod.POST) public String add(@ModelAttribute("schoolDTO") SchoolDTO schoolDTO) { if(schoolDTO.getName() != null && !schoolDTO.getName().isEmpty() && schoolDTO.getEnabled() != null) { schoolService.save(schoolDTO); return "redirect:"; } else { return "redirect:error"; //TODO: create error page } } /** * Get list of teachers. * * @param model * @param schoolId * @return The index view (FTL) */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/teachers/{schoolId}", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model, @PathVariable Long schoolId) { List<TeacherDTO> teachers = teacherService.getAllBySchoolId(schoolId); model.addAttribute("teachersList", teachers); model.addAttribute("schoolId", schoolId); return "teachers"; } }

最满意答案

你需要的是HandlerInterceptorAdapters。 那些必须在SpringMvc-servlet.xml定义,而不是那些将拦截您的所有请求。

public class CollectorHandler extends HandlerInterceptorAdapter { @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (handler instanceof HandlerMethod && modelAndView != null) { HandlerMethod handlerMethod = (HandlerMethod) handler; if (handlerMethod.getMethodAnnotation(Collectors.class) == null) { return; } /** * Your logic here */ } } }

进一步阅读:

http://www.baeldung.com/spring-mvc-handlerinterceptor https://www.mkyong.com/spring-mvc/spring-mvc-handler-interceptors-example/

PS:我还想补充一点,你的代码不起作用,因为你有一些“错误”...返回字符串而不是对象作为例子

What you need are HandlerInterceptorAdapters. Those have to be defined in your SpringMvc-servlet.xml, than those will intercept all your requests.

public class CollectorHandler extends HandlerInterceptorAdapter { @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (handler instanceof HandlerMethod && modelAndView != null) { HandlerMethod handlerMethod = (HandlerMethod) handler; if (handlerMethod.getMethodAnnotation(Collectors.class) == null) { return; } /** * Your logic here */ } } }

For further reading:

http://www.baeldung.com/spring-mvc-handlerinterceptor https://www.mkyong.com/spring-mvc/spring-mvc-handler-interceptors-example/

PS: I also want to add, that your code will not work, as you have some "errors" in it... returning Strings instead of objects as an example

如何从控制器分离逻辑并使用注释将其放入某个处理程序?(How to detach logic from controllers and put it to some handler using annotations?)

在我们的项目中,我们已经有了一些必要的控制器,我的任务是让它更容易。 它应该像这样工作:我只是在控制器下面放一个注释,一个处理程序完成它的所有工作。 我已经拥有的东西:

/** * This annotation marks collector methods */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Collect { } @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Collectors { /** * An array of subclasses that can load and provide values for * generating a ModelMap. */ Class<?>[] value(); }

我找不到任何示例如何做到这一点。 控制器示例:

@Controller public class TestController { private final SchoolService schoolService; private final TeacherService teacherService; public TestController(SchoolService schoolService, TeacherService teacherService) { this.schoolService = schoolService; this.teacherService = teacherService; } /** * Saves the static list of users in model and renders it * via freemarker template. * * @param model * @return The index view (FTL) */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/freemarkertest", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model) { List<SchoolDTO> schoolList = new ArrayList<SchoolDTO>(); schoolList = schoolService.findAll(); model.addAttribute("schoolList", schoolList); return "freemarkertest"; } /** * Add a new School * * @param schoolDTO * @return Redirect back to same /freemarkertest page to display school list, if successful */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/freemarkertest/add", method = RequestMethod.POST) public String add(@ModelAttribute("schoolDTO") SchoolDTO schoolDTO) { if(schoolDTO.getName() != null && !schoolDTO.getName().isEmpty() && schoolDTO.getEnabled() != null) { schoolService.save(schoolDTO); return "redirect:"; } else { return "redirect:error"; //TODO: create error page } } /** * Get list of teachers. * * @param model * @param schoolId * @return The index view (FTL) */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/teachers/{schoolId}", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model, @PathVariable Long schoolId) { List<TeacherDTO> teachers = teacherService.getAllBySchoolId(schoolId); model.addAttribute("teachersList", teachers); model.addAttribute("schoolId", schoolId); return "teachers"; } }

In our project we already have some necessary controllers and my task is to make it easier. It should work like this: I just put an annotation under a controller and a handler do all its job. What I already have:

/** * This annotation marks collector methods */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Collect { } @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Collectors { /** * An array of subclasses that can load and provide values for * generating a ModelMap. */ Class<?>[] value(); }

I can't find any example how to do it. Controller example:

@Controller public class TestController { private final SchoolService schoolService; private final TeacherService teacherService; public TestController(SchoolService schoolService, TeacherService teacherService) { this.schoolService = schoolService; this.teacherService = teacherService; } /** * Saves the static list of users in model and renders it * via freemarker template. * * @param model * @return The index view (FTL) */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/freemarkertest", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model) { List<SchoolDTO> schoolList = new ArrayList<SchoolDTO>(); schoolList = schoolService.findAll(); model.addAttribute("schoolList", schoolList); return "freemarkertest"; } /** * Add a new School * * @param schoolDTO * @return Redirect back to same /freemarkertest page to display school list, if successful */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/freemarkertest/add", method = RequestMethod.POST) public String add(@ModelAttribute("schoolDTO") SchoolDTO schoolDTO) { if(schoolDTO.getName() != null && !schoolDTO.getName().isEmpty() && schoolDTO.getEnabled() != null) { schoolService.save(schoolDTO); return "redirect:"; } else { return "redirect:error"; //TODO: create error page } } /** * Get list of teachers. * * @param model * @param schoolId * @return The index view (FTL) */ @Collectors(SchoolCollector.class) @RequestMapping(value = "freemarker/teachers/{schoolId}", method = RequestMethod.GET) public String index(@ModelAttribute("model") ModelMap model, @PathVariable Long schoolId) { List<TeacherDTO> teachers = teacherService.getAllBySchoolId(schoolId); model.addAttribute("teachersList", teachers); model.addAttribute("schoolId", schoolId); return "teachers"; } }

最满意答案

你需要的是HandlerInterceptorAdapters。 那些必须在SpringMvc-servlet.xml定义,而不是那些将拦截您的所有请求。

public class CollectorHandler extends HandlerInterceptorAdapter { @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (handler instanceof HandlerMethod && modelAndView != null) { HandlerMethod handlerMethod = (HandlerMethod) handler; if (handlerMethod.getMethodAnnotation(Collectors.class) == null) { return; } /** * Your logic here */ } } }

进一步阅读:

http://www.baeldung.com/spring-mvc-handlerinterceptor https://www.mkyong.com/spring-mvc/spring-mvc-handler-interceptors-example/

PS:我还想补充一点,你的代码不起作用,因为你有一些“错误”...返回字符串而不是对象作为例子

What you need are HandlerInterceptorAdapters. Those have to be defined in your SpringMvc-servlet.xml, than those will intercept all your requests.

public class CollectorHandler extends HandlerInterceptorAdapter { @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (handler instanceof HandlerMethod && modelAndView != null) { HandlerMethod handlerMethod = (HandlerMethod) handler; if (handlerMethod.getMethodAnnotation(Collectors.class) == null) { return; } /** * Your logic here */ } } }

For further reading:

http://www.baeldung.com/spring-mvc-handlerinterceptor https://www.mkyong.com/spring-mvc/spring-mvc-handler-interceptors-example/

PS: I also want to add, that your code will not work, as you have some "errors" in it... returning Strings instead of objects as an example