填坑之路(SpringBoot Jersey)

Why?

技术变革的车轮不断向前,伴随着k8s、docker等新技术的落地,陈旧的技术栈,千疮百孔的工程,已经逐步成为技术负债的黑洞。秉承着“前人挖坑后人骂,后人填坑苦哈哈”的精神,我来吧,苦哈哈。

What?

  • Jersey2.x 多Servlet-Mapping

Spring 3 映射Mappings,基于web.xml 映射Servlet,如以下代码示例,目的是为了实现接口的默认前缀并控制接口版本,以映射不同的鉴权版本、拦截器等

    
        Jersey2
        org.glassfish.jersey.servlet.ServletContainer
        1
    
    
        Jersey2
        /rest/v1
    
    
        Jersey2
        /rest/v2
    
  
        Jersey2
        /rest/v3
    

基于springboot想实现接口的默认前缀,存在以下几种方式

  • 每一个接口添加前缀 或多个接口实现(当我没说)
  • @ApplicationPath
    然而无法实现多个path共存的想法,因此貌似走到了怪圈里。。走了好久好久好久。。

直到发现了以下的文档:
Springboot 中Jersey 的multiple Application实现
核心思想:即对Servlet扫描规则进行了拓展,完美的解决了以上问题。

  • SpringBoot Jar包运行,提示FileNotFound

原本的配置是这个样子的,基于IDE调试的过程中一直很顺利,直到基于jar部署的时候,凉凉了

public class JerseyConfig extends ResourceConfig {

    public JerseyConfig(){
        //扫描Jersey实例所在包
        packages("com.xx.xx");
        // 注册JacksonFeature
        register(JacksonFeature.class);
    }
}

貌似又走到了怪圈里。。走了好久好久好久。。

直到发现了以下的文档:
jersey在 spring boot 添加 packages 扫描路径支持
核心思想:springboot打包成jar之后,jersey packages扫描不到相关类,故使用Spring的扫描机制进行处理

此处发现可以优化的点,之前是进行包下的所有类扫描并注册,之后启动后会提示一些警告,故可以在之中判断class是有@Path的引用,再进行注册

  • 多Application实例,注册不成功

原以为逃离了怪圈。。好远好远好远。。基于Jar部署后,启动成功了,然而调用接口后,404!!
又又又凉凉凉了。。

貌似又又走到了怪圈里。。走了好久好久。。

之后毅然决然的查看了Application的相关源码,发现了事情的真相。

public class Application {
    
    public Set> getClasses() {
        return Collections.emptySet();
    }
    ...省略
}

getClasses() 方法即为基于以上实例扫描到的Jersey实例,通过debug发现以下为空,瞬间懂了,将上文扫描到的classes,返回即可。

希望这回真的逃离了怪圈。。好远好远好远好远。。

  • @ Produces 不指定类型或者干脆没有这个注解

基于以上的一通儿操作,我以为我今天一定可以霸屏"填坑走多远排行版"第一把交椅,然而又又又又TM的出现了,已经一个正常的请求,后台提示 text/html 没有解析器。

!!!这是一个应该响应成JSON的请求!!!

貌似又又又又又又走到了怪圈里。。有点走走走走走走不动了。。

冷静了许久。。想到了两个解决方案:

  • 全局搜索,然后一个一个补全,之后打死哪些不写全代码的人
  • 配置默认的响应MediaType

最终在Jersey包下找到了以下类ContainerResponseFilter,大体的源码如下

package javax.ws.rs.container;
import java.io.IOException;
public interface ContainerResponseFilter {

    /**
     * Filter method called after a response has been provided for a request
     * (either by a {@link ContainerRequestFilter request filter} or by a
     * matched resource method.
     * 

* Filters in the filter chain are ordered according to their {@code javax.annotation.Priority} * class-level annotation value. *

* * @param requestContext request context. * @param responseContext response context. * @throws IOException if an I/O exception occurs. */ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException; }

关键的一段英文在下面

Filter method called after a response has been provided for a request

!!!在请求的响应返回时触发 !!!

果断实现接口,对于代码做容错,大体逻辑如下:

没有@Produces 响应默认为MediaType.APPLICATION_JSON
有@Produces 但是没有值,则一样变成MediaType.APPLICATION_JSON

To be continued ?

少挖坑,多种树

你可能感兴趣的:(填坑之路(SpringBoot Jersey))