我如何从 CXF/JAX-RS 提供静态内容并将我的其余 API 映射到根上下文?
How can I serve static content from CXF / JAX-RS with my rest API mapped to root context?
我休息 API 使用 CXF 实现 JAX-RS,其中 REST 端点直接位于根上下文中。
例如,如果我的根上下文是 localhost:8080/myservice
我的端点是:
localhost:8080/myservice/resource1
localhost:8080/myservice/resource2
但我想像这样提供静态内容:
localhost:8080/myservice/docs/swagger.json
在我的 web.xml 中,我想做这样的事情:
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/docs/*</url-pattern>
</servlet-mapping>
但这不起作用,CXFServlet 接收所有请求,我找不到一种方法来配置 CXF/JAX-RS 来服务我的静态内容,而不包括新库和创建字节流等,我不想做。我只想映射到默认的 servlet。
CXF 文档并不容易理解,我尝试执行以下操作但未成功:
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<init-param>
<param-name>static-resources-list</param-name>
<param-value>
/docs/(\S)+\.html
/docs/(\S)+\.json
</param-value>
</init-param>
</servlet>
有什么想法吗?
感谢 this link!
我找到了解决方案
下面是我 web.xml 中的 servlet 配置,用于使用映射到 root 的 CXFServlet 提供静态资源。
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<init-param>
<param-name>redirects-list</param-name>
<param-value>
/docs/(\S)+\.html
/docs/(\S)+\.json
</param-value>
</init-param>
<init-param>
<param-name>redirect-attributes</param-name>
<param-value>
javax.servlet.include.request_uri
</param-value>
</init-param>
<init-param>
<param-name>redirect-servlet-name</param-name>
<param-value>default</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
希望这对其他人有帮助。
您可以通过将静态内容添加到 CXF Jetty 资源处理程序来提供静态内容:
<bean id="jettyHTTPServerEngine" class="org.apache.cxf.transport.http_jetty.JettyHTTPServerEngine">
<property name="threadingParameters" ref="threadingParameters" />
<property name="port" value="8080" />
<property name="handlers">
<list>
<ref bean="contextHandler" />
</list>
</property>
</bean>
<bean name="contextHandler" class="org.eclipse.jetty.server.handler.ContextHandler">
<property name="contextPath" value="/content"/>
<property name="handler" ref="resourceHandler"/>
</bean>
<bean id="resourceHandler" class="org.eclipse.jetty.server.handler.ResourceHandler">
<property name="resourceBase" value="#{classpathResourceResolver.path}"/>
<property name="directoriesListed" value="true"/>
</bean>
<bean id="classpathResourceResolver" class="com.myapp.ClasspathResourceResolver">
<property name="resourceLocation" value="myresources/files"/>
</bean>
其中 属性 contextPath 是 URL 后缀,例如您将在 localhost:8080/content
获得内容
请注意,Jetty ResourceHandler 仅接受 Java 路径(普通),而不接受 Spring 类路径。
因此,您需要从 Spring 到 Java 规范路径的自定义转换器,请参阅:
public class ClasspathResourceResolver
{
private String resourceLocation;
public String getPath()
{
if (StringUtils.isNotEmpty(resourceLocation))
{
try
{
return new ClassPathResource(resourceLocation).getFile().getCanonicalPath();
}
catch (Exception e)
{
log.warn("Unable to resolve classpath as canonical path", e);
}
}
return null;
}
public void setResourceLocation(String resourceLocation)
{
this.resourceLocation = resourceLocation;
}
}
CXFServlet 能够直接提供静态内容;使用 'static-resources-list' init-param 和 space 从类路径分离的静态资源列表:
<init-param>
<param-name>static-resources-list</param-name>
<param-value>/static/(\w)+.css</param-value>
</init-param>
也可以通过 'static-cache-control':
设置 HTTP 响应 Cache-Control header
<init-param>
<param-name>static-cache-control</param-name>
<param-value>public, max-age=31536000</param-value>
</init-param>
Apache CXF Servlet Transport,节 'Redirecting requests and serving the static content'
加上我的 2 美分,因为我受到了这个问题和答案的启发。
我希望在 JAVA 中进行配置,但还发现我必须使用不同的正则表达式。
我会把代码放在这里,但先解释一下:
我的应用程序使用 spring-boot + cxf。 CXF 映射到根“/”并且 CXF 无法为静态资源提供服务器,所以我添加了 redirect-servlet-name 参数,上面写着“嘿 cxf,如果请求以 .css 结尾,将请求分派给 dispatcherServlet”。
为什么使用调度程序 servlet?它是 spring-boot 的默认 servlet,例如能够为来自特定文件夹的静态内容提供服务器。
@Bean
public ServletRegistrationBean<CXFServlet> servletRegistrationBean() {
ServletRegistrationBean<CXFServlet> x = new ServletRegistrationBean<>(new CXFServlet(), "/*");
Map<String, String> params = new HashMap<>();
params.put("redirects-list", ".*\.css$"); // space separated list if multiple values are required
params.put("redirect-servlet-name", "dispatcherServlet");
x.setInitParameters(params);
return x;
}
我休息 API 使用 CXF 实现 JAX-RS,其中 REST 端点直接位于根上下文中。
例如,如果我的根上下文是 localhost:8080/myservice
我的端点是:
localhost:8080/myservice/resource1
localhost:8080/myservice/resource2
但我想像这样提供静态内容:
localhost:8080/myservice/docs/swagger.json
在我的 web.xml 中,我想做这样的事情:
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/docs/*</url-pattern>
</servlet-mapping>
但这不起作用,CXFServlet 接收所有请求,我找不到一种方法来配置 CXF/JAX-RS 来服务我的静态内容,而不包括新库和创建字节流等,我不想做。我只想映射到默认的 servlet。
CXF 文档并不容易理解,我尝试执行以下操作但未成功:
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<init-param>
<param-name>static-resources-list</param-name>
<param-value>
/docs/(\S)+\.html
/docs/(\S)+\.json
</param-value>
</init-param>
</servlet>
有什么想法吗?
感谢 this link!
我找到了解决方案下面是我 web.xml 中的 servlet 配置,用于使用映射到 root 的 CXFServlet 提供静态资源。
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<init-param>
<param-name>redirects-list</param-name>
<param-value>
/docs/(\S)+\.html
/docs/(\S)+\.json
</param-value>
</init-param>
<init-param>
<param-name>redirect-attributes</param-name>
<param-value>
javax.servlet.include.request_uri
</param-value>
</init-param>
<init-param>
<param-name>redirect-servlet-name</param-name>
<param-value>default</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
希望这对其他人有帮助。
您可以通过将静态内容添加到 CXF Jetty 资源处理程序来提供静态内容:
<bean id="jettyHTTPServerEngine" class="org.apache.cxf.transport.http_jetty.JettyHTTPServerEngine">
<property name="threadingParameters" ref="threadingParameters" />
<property name="port" value="8080" />
<property name="handlers">
<list>
<ref bean="contextHandler" />
</list>
</property>
</bean>
<bean name="contextHandler" class="org.eclipse.jetty.server.handler.ContextHandler">
<property name="contextPath" value="/content"/>
<property name="handler" ref="resourceHandler"/>
</bean>
<bean id="resourceHandler" class="org.eclipse.jetty.server.handler.ResourceHandler">
<property name="resourceBase" value="#{classpathResourceResolver.path}"/>
<property name="directoriesListed" value="true"/>
</bean>
<bean id="classpathResourceResolver" class="com.myapp.ClasspathResourceResolver">
<property name="resourceLocation" value="myresources/files"/>
</bean>
其中 属性 contextPath 是 URL 后缀,例如您将在 localhost:8080/content
获得内容
请注意,Jetty ResourceHandler 仅接受 Java 路径(普通),而不接受 Spring 类路径。
因此,您需要从 Spring 到 Java 规范路径的自定义转换器,请参阅:
public class ClasspathResourceResolver
{
private String resourceLocation;
public String getPath()
{
if (StringUtils.isNotEmpty(resourceLocation))
{
try
{
return new ClassPathResource(resourceLocation).getFile().getCanonicalPath();
}
catch (Exception e)
{
log.warn("Unable to resolve classpath as canonical path", e);
}
}
return null;
}
public void setResourceLocation(String resourceLocation)
{
this.resourceLocation = resourceLocation;
}
}
CXFServlet 能够直接提供静态内容;使用 'static-resources-list' init-param 和 space 从类路径分离的静态资源列表:
<init-param>
<param-name>static-resources-list</param-name>
<param-value>/static/(\w)+.css</param-value>
</init-param>
也可以通过 'static-cache-control':
设置 HTTP 响应 Cache-Control header <init-param>
<param-name>static-cache-control</param-name>
<param-value>public, max-age=31536000</param-value>
</init-param>
Apache CXF Servlet Transport,节 'Redirecting requests and serving the static content'
加上我的 2 美分,因为我受到了这个问题和答案的启发。
我希望在 JAVA 中进行配置,但还发现我必须使用不同的正则表达式。
我会把代码放在这里,但先解释一下:
我的应用程序使用 spring-boot + cxf。 CXF 映射到根“/”并且 CXF 无法为静态资源提供服务器,所以我添加了 redirect-servlet-name 参数,上面写着“嘿 cxf,如果请求以 .css 结尾,将请求分派给 dispatcherServlet”。
为什么使用调度程序 servlet?它是 spring-boot 的默认 servlet,例如能够为来自特定文件夹的静态内容提供服务器。
@Bean
public ServletRegistrationBean<CXFServlet> servletRegistrationBean() {
ServletRegistrationBean<CXFServlet> x = new ServletRegistrationBean<>(new CXFServlet(), "/*");
Map<String, String> params = new HashMap<>();
params.put("redirects-list", ".*\.css$"); // space separated list if multiple values are required
params.put("redirect-servlet-name", "dispatcherServlet");
x.setInitParameters(params);
return x;
}