【发布时间】:2014-04-15 06:45:12
【问题描述】:
我有一个基于 RESTful spring 的端点来获取存储在数据库中的资产到 javascript 编辑器。相关部分归结为:
@RestController
@RequestMapping(ThemeEndpoint.ENDPOINT_NAME)
public class ThemeEndpoint {
public static final String ENDPOINT_NAME = "/themes";
@RequestMapping(value="/{id}/css/{assetName:.*}", method=RequestMethod.GET)
public Asset getCssItem(
@PathVariable("id") ThemeId id,
@PathVariable("assetName") String name) {
CssThemeAsset themeAsset = themeService.getCssAsset(
id, ThemeAssetId.fromString(name));
Asset asset = new Asset();
asset.name = themeAsset.getName();
asset.text = themeAsset.getContent();
return asset;
}
这对像这样的网址按预期工作
http://localhost:8080/app-url/rest/themes/ac18a080-a2f1-11e3-84f4-600308a0bd14/css/main.less
但一旦我将扩展名更改为.css,就会失败。
经过一些调试,我很确定如果我使用像这样的 url,请求甚至没有被映射
http://localhost:8080/app-url/rest/themes/ac18a080-a2f1-11e3-84f4-600308a0bd14/css/main.css
如果日志级别很高,我可以看到映射被 spring 捕获:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
- Mapped "{[/themes/{id}/css/{assetName:.*}],methods=[GET],params=[],headers=[],
consumes=[],produces=[application/json],custom=[]}"
onto public xxx.endpoint.ThemeEndpoint$Asset
xxx.endpoint.ThemeEndpoint.getCssItem(
net.lacho.svc.themes.api.ThemeId,java.lang.String)
并且使用非 .css 扩展名调用控制器:
Found 1 matching mapping(s) for [/themes/ac18a080-a2f1-11e3-84f4-600308a0bd14/css/main.less]
: [{[/themes/{id}/css/{assetName:.*}],methods=[GET],params=[],headers=[],
consumes=[],produces=[application/json],custom=[]}]
但只要我使用 .css 作为扩展名 - 砰:
Looking up handler method for path /themes/ac18a080-a2f1-11e3-84f4-600308a0bd14/css/test.css
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver -
Resolving exception from handler [null]:
org.springframework.web.HttpMediaTypeNotAcceptableException:
Could not find acceptable representation
web.xmland MVC-Config 按要求:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="false">
<welcome-file-list>
<welcome-file>index</welcome-file>
</welcome-file-list>
</web-app>
WebApplicationInitializer:
package net.lacho.opcenter.bootstrap;
public class WebApplicationBootstrapper implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.setConfigLocation(ApplicationConfig.class.getName());
container.addListener(new ContextLoaderListener(rootContext));
registerRestDispatcher(container);
registerDefaultDispatcher(container);
container.addFilter("CharacterEncodingFilter", UTF8EncodingFilter.class).addMappingForUrlPatterns(null, true, "/*");
container.addFilter("headSupportFilter", HeadSupportFilter.class).addMappingForUrlPatterns(null, true, "/*");
DelegatingFilterProxy shallowFrontendContextFilterProxy = new DelegatingFilterProxy("shallowFrontendContextProviderLocalFilter");
shallowFrontendContextFilterProxy.setTargetFilterLifecycle(true);
FilterRegistration.Dynamic shallowFrontendFilter = container.addFilter("ShallowFrontendContextFilter", shallowFrontendContextFilterProxy);
shallowFrontendFilter.setInitParameter("ignoreNullClient", "true");
shallowFrontendFilter.addMappingForUrlPatterns(null, true, "/*");
container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, true, "/*");
container.addFilter("FrontendContextFilter", new DelegatingFilterProxy("frontendContextProviderLocalFilter"))
.addMappingForUrlPatterns(null, true, "/*");
container.addFilter("hiddenHttpMethodFilter", new HiddenHttpMethodFilter()).addMappingForUrlPatterns(null, true, "/rest/*");;
}
public void registerRestDispatcher(ServletContext container) {
AnnotationConfigWebApplicationContext restDispatcherContext = new AnnotationConfigWebApplicationContext();
restDispatcherContext.register(RestCommonsMvcConfig.class);
ServletRegistration.Dynamic restDispatcher = container.addServlet("rest-dispatcher", new DispatcherServlet(restDispatcherContext));
restDispatcher.setLoadOnStartup(1);
restDispatcher.addMapping("/rest/*");
}
public void registerDefaultDispatcher(ServletContext container) {
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(MvcConfig.class);
ServletRegistration.Dynamic dispatcher = container.addServlet("backend-dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*", "/index");
}
}
MVC 配置:
package net.lacho.opcenter.bootstrap;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"net.lacho.opcenter.ui"} )
public class MvcConfig extends WebMvcConfigurerAdapter {
... many lines removed, containing interceptors and velocity-config ...
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/_r/_s/**")
.addResourceLocations("classpath:/static-resources/")
.setCachePeriod(365 * 86400);
registry
.addResourceHandler("/_r/_d/**")
.addResourceLocations("classpath:/static-uncached-resources/");
}
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
有人知道吗?
【问题讨论】:
-
您的 web.xml 和 mvc 映射配置是什么样的?猜测有东西将 *.css 识别为资源并将其映射到资源 servlet
-
如何将
Assert转换为HTTP 响应?显示您的自定义HttpMessageConverter,如果您使用它。 -
@rhinds 添加了请求的文件。
-
@axtavt 没有自定义转换器。我通过 maven 导入 Jackson 2,它被 spring 拾取(正如我所说,只要我的 url 不以 .css 结尾,控制器就会被调用并且编组到 JSON 工作)。
标签: spring-mvc spring-4