在我的控制器中,我的控制器方法名称等于请求映射网址。例如,/list
等于方法名称list
。是否有一个通用的处理程序方法来缩短我的代码?我不想以这种方式编写每个控制器和方法。我记得.net mvc有一个简单的方法来配置它。关于Spring MVC的什么?
@Controller
@RequestMapping(value = "/fooController ")
public class FooController {
@RequestMapping("/list") public String list(...) { ... }
@RequestMapping("/save") public String save(...) { ... }
@RequestMapping("/delete") public String delete(...) { ... }
}
@Controller
@RequestMapping(value = "/basketballController ")
public class BasketballController {
@RequestMapping("/list") public String list(...) { ... }
@RequestMapping("/save") public String save(...) { ... }
@RequestMapping("/delete") public String delete(...) { ... }
}
答案 0 :(得分:2)
您可以使用RequestMappingHandlerMapping
并覆盖默认代码
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;
}
正如您在此处所看到的,它尝试从方法中解析RequestMapping注释并与Controller类注释结合使用。
只需将逻辑替换为使用方法名称。
参见here类似的逻辑。而不是方法名称使用安全检查。
更新:
要测试的类。对我来说它有效。 MappingHandler我使用方法名称检查,因为有更多的控制器,错误控制器等。对于真正的解决方案,我将在控制器上引入一个注释,以从逻辑中排除默认的弹簧控制器
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();
}
}
配置使用映射
@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;
}
}
控制器
@RestController
@RequestMapping("/common")
public class MethodNameController {
public String test() {
return "test";
}
public String test2() {
return "test2";
}
}
测试类
@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"));
}
}
答案 1 :(得分:0)
两个控制器的抽象基类是否适合您?
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> {
}
答案 2 :(得分:0)
您可以扩展到AbstractControllerUrlHandlerMapping
并覆盖该方法并在web.xml中添加bean。
<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" />
这是example。