简体   繁体   English

如何使用映射到根上下文的其余 API 提供来自 CXF/JAX-RS 的静态内容?

[英]How can I serve static content from CXF / JAX-RS with my rest API mapped to root context?

I have a rest API using CXF to implement JAX-RS where the REST endpoints are directly on the root context.我有一个使用 CXF 的 REST API 来实现 JAX-RS,其中 REST 端点直接位于根上下文中。

For example if my root context is localhost:8080/myservice例如,如果我的根上下文是 localhost:8080/myservice

And my endpoints are:我的端点是:
localhost:8080/myservice/resource1本地主机:8080/myservice/resource1
localhost:8080/myservice/resource2本地主机:8080/myservice/resource2

But I want to serve static content like this:但我想提供这样的静态内容:
localhost:8080/myservice/docs/swagger.json本地主机:8080/myservice/docs/swagger.json

In my web.xml I'd like to do something like this:在我的 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>

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.但这不起作用,CXFServlet 接收所有请求,我找不到一种方法来配置 CXF/JAX-RS 来为我的静态内容提供服务,而不包括新库和创建字节流等,我不想这样做做。 I want to just map to the default servlet.我只想映射到默认的 servlet。

The CXF documentation is not easy to follow, and I tried unsuccessfully to do the following: 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>

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.下面是我的 web.xml 中的 servlet 配置,用于使用映射到根的 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>

Hope this helps someone else.希望这对其他人有帮助。

You can serve static content by adding it to CXF Jetty resource handler:您可以通过将静态内容添加到 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>

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.其中属性contextPath是 URL 后缀,例如您将在localhost:8080/content content 处获取内容 请注意,Jetty ResourceHandler 仅接受 Java 路径(普通路径),而不接受 Spring 类路径。 So you need custom converter from Spring to Java canonical path, see:因此,您需要从 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 able to serve static content directly; CXFServlet 能够直接提供静态内容; use 'static-resources-list' init-param with space separated list of static resource from classpath:使用 'static-resources-list' init-param 与类路径中的静态资源的空格分隔列表:

        <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':也可以通过“static-cache-control”设置 HTTP 响应 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' Apache CXF Servlet 传输,“重定向请求和提供静态内容”部分

Adding my 2 cents since I was inspired by this question and answers.添加我的 2 美分,因为我受到了这个问题和答案的启发。

I wanted this to configure in JAVA and found out also that I had to use different regex.我希望在 JAVA 中进行配置,并发现我必须使用不同的正则表达式。

I'll put the code here but explanation first:我会把代码放在这里,但先解释一下:

My app was using spring-boot + cxf.我的应用程序使用 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". CXF 映射到根“/”并且 CXF 无法为静态资源提供服务,因此我添加了重定向 servlet-name 参数,表示“嘿 cxf,如果请求以 .css 结尾,则将请求分派给 dispatcherServlet”。

Why dispatcher servlet?为什么是调度程序 servlet? It's spring-boot's default servlet that is for example able to server static content from specific folders.它是 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM