I have a rest API using CXF to implement JAX-RS where the REST endpoints are directly on the root context.
For example if my root context is localhost:8080/myservice
And my endpoints are:
localhost:8080/myservice/resource1
localhost:8080/myservice/resource2
But I want to serve static content like this:
localhost:8080/myservice/docs/swagger.json
In my web.xml I'd like to do something like this:
<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>
But that doesn't work, the CXFServlet picks up all requests and I could not find a way to configure CXF / JAX-RS to serve my static content without including new libraries and creating byte streams, etc. which I don't want to do. I want to just map to the default servlet.
The CXF documentation is not easy to follow, and I tried unsuccessfully to do the following:
<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>
Any ideas?
I found the solution thanks to this link !
Below is my servlet config in my web.xml to serve static resources with a CXFServlet that is mapped to root.
<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>
Hope this helps someone else.
You can serve static content by adding it to CXF Jetty resource handler:
<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>
where property contextPath is URL suffix, eg you will get content at localhost:8080/content
Be aware, that Jetty ResourceHandler accepts only Java path (plain), not Spring classpath. So you need custom converter from Spring to Java canonical path, see:
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 able to serve static content directly; use 'static-resources-list' init-param with space separated list of static resource from classpath:
<init-param>
<param-name>static-resources-list</param-name>
<param-value>/static/(\w)+.css</param-value>
</init-param>
Its also possible to set HTTP response Cache-Control header via 'static-cache-control':
<init-param>
<param-name>static-cache-control</param-name>
<param-value>public, max-age=31536000</param-value>
</init-param>
Apache CXF Servlet Transport , section 'Redirecting requests and serving the static content'
Adding my 2 cents since I was inspired by this question and answers.
I wanted this to configure in JAVA and found out also that I had to use different regex.
I'll put the code here but explanation first:
My app was using spring-boot + cxf. CXF is mapped to root "/" and CXF was unable to server static resources, so I added redirect-servlet-name param that says "hey cxf, if request ends with .css, dispatch the requet to dispatcherServlet".
Why dispatcher servlet? It's spring-boot's default servlet that is for example able to server static content from specific folders.
@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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.