How to optimize my code in Spring MVC Controller using @RequestMapping?

后端 未结 3 661
生来不讨喜
生来不讨喜 2020-12-30 16:57

In my controller,My controller method names are equals to the requestmapping url.For example,/list is equal to method name list. Is there has a com

相关标签:
3条回答
  • 2020-12-30 17:37

    Will an abstract base class for both controllers work for you?

    public abstract class BaseController<T> {
         @RequestMapping("/list") public String list(...) { ... }
         @RequestMapping("/save") public String save(...) { ... }
         @RequestMapping("/delete") public String delete(...) { ... }
    }
    
    @Controller
    @RequestMapping(value = "/fooController ")
    public class FooController extends BaseController<Foo> {      
    }
    
    @Controller
    @RequestMapping(value = "/basketballController ")
    public class BasketballController extends BaseController<Basketball> {
    }
    
    0 讨论(0)
  • 2020-12-30 17:42

    You can use RequestMappingHandlerMapping and override default code

    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo info = createRequestMappingInfo(method);
        if (info != null) {
            RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType);
            if (typeInfo != null) {
                info = typeInfo.combine(info);
            }
        }
        return info;
    }
    

    As you can see here it tries to resolve RequestMapping annotation from method and combine with Controller class annotation.

    Just replace the logic to use method name instead.

    See here a similar logic. Instead of method name security check was used.

    UPDATE:

    The classes to test. For me it works. MappingHandler I use method name check because there are much more controllers, errors controllers etc. For real solution I would introduce an annotation on the controllers to exclude default spring controllers from the logic

    public class ExtendedRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    
        protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
            RequestMappingInfo info;
            if (method.getName().startsWith("test")) {
                info = createRequestMappingInfoByMethodName(method);
            }
            else {
                info = super.getMappingForMethod(method, handlerType);
            }
            return info;
        }
    
        protected RequestMappingInfo createRequestMappingInfoByMethodName(Method method) {
            RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), RequestMapping.class);
            String path = requestMapping.value()[0] + "/" + method.getName();
            return RequestMappingInfo
                    .paths(path)
                    .methods(requestMapping.method())
                    .params(requestMapping.params())
                    .headers(requestMapping.headers())
                    .consumes(requestMapping.consumes())
                    .produces(requestMapping.produces())
                    .mappingName(requestMapping.name())
                    .build();
        }
    }
    

    Config to use the mapping

    @Configuration
    public class ExtendedWebMvcConfiguration extends WebMvcConfigurationSupport {
    
        @Override @Bean
        public RequestMappingHandlerMapping requestMappingHandlerMapping() {
            ExtendedRequestMappingHandlerMapping handlerMapping = new ExtendedRequestMappingHandlerMapping();
            handlerMapping.setOrder(0);
            handlerMapping.setInterceptors(getInterceptors());
            return handlerMapping;
        }
    
        @Override @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
            adapter.setIgnoreDefaultModelOnRedirect(true);
            return adapter;
        }
    
    }
    

    Controller

    @RestController
    
    @RequestMapping("/common")
    public class MethodNameController {
        public String test() {
            return "test";
        }
        public String test2() {
            return "test2";
        }
    }
    

    test class

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class MethodNameControllerTest {
        @LocalServerPort
        private int port;
    
        @Value("${server.contextPath}")
        private String contextPath;
        private String base;
    
        @Autowired
        private TestRestTemplate template;
    
        @Before
        public void setUp() throws Exception {
            this.base = "http://localhost:" + port;
        }
    
        @Test
        public void testMethodNameMappingResolving() throws Exception {
            TestRestTemplate template = new TestRestTemplate();
            String url = base + contextPath + "/common/test";
            String res1 = template.getForObject(url, String.class);
            assertThat(res1, equalTo("test"));
    
            url += "2";
            String res2 = template.getForObject(url, String.class);
            assertThat(res2, equalTo("test2"));
        }
    
    }
    
    0 讨论(0)
  • 2020-12-30 17:50

    You can extend to AbstractControllerUrlHandlerMapping and override the method and add bean in web.xml.

      <beans:bean id="myControllerClassNameHandlerMapping" class="com.qiyongkang.sys.controller.MyControllerClassNameHandlerMapping">
      <beans:property name="interceptors">
          <beans:array>
              <beans:bean id="sysLogInterceptor" class="com.qiyongkang.sys.interceptor.SysLogInterceptor"></beans:bean>
          </beans:array>
      </beans:property>
      <beans:property name="caseSensitive" value="true" />
      <beans:property name="frameworkPackagePrefixs" value="com.qiyongkang." />
      <beans:property name="actionPackageSuffixs" value=".ctrl,.controller" />
      <beans:property name="actionClassSuffixs" value="Ctrl,Controller" />
    

    Here is an example.

    0 讨论(0)
提交回复
热议问题