SpringBoot整合JAX-RS接口

news2024/9/20 14:30:11

目录

二、创建RESTful资源

三、注册JAX-RS资源

四、修改配置等信息

五、启动SpringBoot程序、访问服务

六、遇到的问题

 七、与feign进行配合使用

1、接口定义

2、接口实现

3、注册资源

4、调用方web服务实现,跟注入普通服务一样

5、启动两个服务,调用


一、增加Jersey依赖

    implementation 'jakarta.ws.rs:jakarta.ws.rs-api:3.1.0'
//    implementation 'jakarta.ws.rs:jakarta.ws.rs-api:2.1.1'
    implementation 'org.glassfish.jersey.core:jersey-server:3.1.7'
    implementation 'org.glassfish.jersey.inject:jersey-hk2:3.1.7'
    implementation 'org.springframework.boot:spring-boot-starter-jersey:3.2.7'
    implementation 'org.javassist:javassist:3.28.0-GA'

二、创建RESTful资源

使用jakarta.ws.rs注解定义RESTful资源

package com.example.service;

import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.springframework.stereotype.Component;

@Component
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/jersey-service")
public class JerseyService {

    @GET
    @Path("test")
    public String test(){
        return "jersey demo test";
    }
}

三、注册JAX-RS资源

三种方式:

1、创建自定义的ResourceConfig

package com.example.service;

import jakarta.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;

@Configuration
@ApplicationPath("/api")
public class MyApplication extends ResourceConfig {
    public MyApplication() {
        // 注册资源类
        register(JerseyService.class);
        // 可以注册更多的资源和提供者
    }
}

访问地址:http://localhost:10002/api/jersey-service/test

加spring.jersey.application-path=demo配置后 不能访问。这两个路径互斥,保留一个即可

2、返回一个ResourceConfig类型的@Bean

package com.example;

import com.example.service.JerseyService;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;

@EnableFeignClients(basePackages = {"com.example"})
@SpringBootApplication(scanBasePackages = {"com.example"})
public class DemoServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoServiceApplication.class, args);
    }

//    @Bean
//    public MyApplication myApplication(){
//        return new MyApplication();
//    }

    @Bean
    public ResourceConfig resourceConfig(){
        ResourceConfig resourceConfig= new ResourceConfig();
        resourceConfig.register(JerseyService.class);
        return resourceConfig;
    }
}

访问地址:http://localhost:10002/jersey-service/test

加spring.jersey.application-path=demo配置后

http://localhost:10002/demo/jersey-service/test

3、配置一组ResourceConfigCustomizer对象

四、修改配置等信息

可以在配置文件application.properties中设置端口路径上下文等

#spring.jersey.application-path=demo
server.port=10002

Springboot默认把Jersey的根路径映射在/*上;如果要更改默认的根路径设置,对于自定义的ResourceConfig方式来说,可以在类上面添加一个@ApplicationPath注解即可。
也可以在application.properties中添加配置spring.jersey.application-path来改变项目的根路径。

五、启动SpringBoot程序、访问服务

六、遇到的问题

1、启动不生效,未增加Springboot集成jersey依赖

解决方案:增加依赖

implementation 'org.springframework.boot:spring-boot-starter-jersey'

2、build报错

增加implementation 'org.springframework.boot:spring-boot-starter-jersey:3.2.7'依赖后build报错

解决方案:改成指定增加依赖

implementation 'org.javassist:javassist:3.28.0-GA'

3、正常启动后访问有问题

2024-07-10T10:53:26.410+08:00 ERROR 22420 --- [demo-service] [io-10002-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Servlet.init() for servlet [com.example.service.MyApplication] threw exception

java.lang.NoClassDefFoundError: org/glassfish/jersey/message/internal/NullOutputStream
	at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311) ~[jersey-container-servlet-core-3.1.7.jar:na]
	at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154) ~[jersey-container-servlet-core-3.1.7.jar:na]
	at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:339) ~[jersey-container-servlet-core-3.1.7.jar:na]
	at jakarta.servlet.GenericServlet.init(GenericServlet.java:143) ~[tomcat-embed-core-10.1.25.jar:6.0]
	at jakarta.servlet.http.HttpServlet.init(HttpServlet.java:121) ~[tomcat-embed-core-10.1.25.jar:6.0]
	at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:837) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:588) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:115) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25]
	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: java.lang.ClassNotFoundException: org.glassfish.jersey.message.internal.NullOutputStream
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na]
	... 23 common frames omitted

jersey-common3.1.7里面没有这个类org.glassfish.jersey.message.internal.NullOutputStream

把引用的jersey-server包也改成3.1.7,或者都用最新的。之前是指定了3.1.0的版本。总之版本要一致。

4、同时配置spring.jersey.application-path=demo 和 @ApplicationPath("/api")

http://localhost:10002/demo/api/jersey-service/test并不能访问

 七、与feign进行配合使用

配合上次的那个可以结合feign做服务的调用,通用一个接口

Spring Boot单体服务之间用feign调用-CSDN博客

web和service是两个服务。api复用,web通过feign调用service提供的JAX-RS接口。

这是是单体运用做测试,所以配置了url

1、接口定义

package com.example.api;

import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(name ="IDemoService", path = "api/demo-service/", url = "${rootServiceUrl}", primary = false, contextId = "jaxrs")
@Path("/demo-service")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface IDemoService {

    @GetMapping("test")
    @GET
    @Path("test")
    String test();
}

2、接口实现

package com.example.service;

import com.example.api.IDemoService;
import org.springframework.stereotype.Service;


@Service
public class DemoService implements IDemoService {
    @Override
    public String test() {
        return "demo service";
    }
}

3、注册资源

package com.example.service;

import jakarta.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;

@Configuration
@ApplicationPath("/api")
public class MyApplication extends ResourceConfig {
    public MyApplication() {
        // 注册资源类
        register(JerseyService.class);
        register(DemoService.class);
        // 可以注册更多的资源和提供者
    }
}

4、调用方web服务实现,跟注入普通服务一样

@RestController
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private IDemoService demoService;

    @GetMapping("test")
    public String test(){
        return demoService.test();
    }
}

5、启动两个服务,调用

八、JAX-RS说明

JAX-RS(Java API for RESTful Web Services)是Java EE规范的一部分,为构建RESTful Web服务提供了一套统一的API。JAX-RS接口和类主要定义了如何创建和操作RESTful服务。以下是一些核心的JAX-RS接口和注解:

  1. javax.ws.rs.core.Application

    • 用于定义JAX-RS应用程序,可以注册JAX-RS资源和提供者。
  2. javax.ws.rs.Path

    • 注解用于定义资源的URI路径。
  3. HTTP方法注解

    • @GET:处理HTTP GET请求。
    • @POST:处理HTTP POST请求。
    • @PUT:处理HTTP PUT请求。
    • @DELETE:处理HTTP DELETE请求。
    • @PATCH:处理HTTP PATCH请求。
  4. javax.ws.rs.Produces

    • 注解用于指定资源方法可以生成的媒体类型(如application/jsontext/html)。
  5. javax.ws.rs.Consumes

    • 注解用于指定资源方法可以消费的媒体类型。
  6. javax.ws.rs.core.MediaType

    • 类提供定义媒体类型的常量和实用方法。
  7. javax.ws.rs.core.Response

    • 类用于构造和表示HTTP响应,包括状态码和响应体。
  8. javax.ws.rs.GET

    • 除了@GET,还包括@POST@PUT@DELETE等,用于将资源类的方法映射到特定的HTTP方法。
  9. javax.ws.rs.PathParam

    • 注解用于从URI模板中提取参数。
  10. javax.ws.rs.QueryParam

    • 注解用于绑定查询参数。
  11. javax.ws.rs.FormParam

    • 注解用于绑定表单提交的数据。
  12. javax.ws.rs.HeaderParam

    • 注解用于获取HTTP请求头的值。
  13. javax.ws.rs.CookieParam

    • 注解用于获取HTTP cookie的值。
  14. javax.ws.rs.MatrixParam

    • 注解用于处理URI矩阵参数。
  15. javax.ws.rs.core.Requestjavax.ws.rs.core.SecurityContext

    • 接口用于访问HTTP请求的详细信息和安全上下文。
  16. javax.ws.rs.ext.Provider

    • 注解用于标记扩展提供者,如消息体读取器、消息体编写器等。

JAX-RS还定义了其他一些接口和类,用于更高级的功能,如异常处理、拦截器、容器特定的配置等。使用JAX-RS,开发者可以使用注解来简化Web服务的客户端和服务端的开发和部署。基于JAX-RS实现的框架有Jersey、RESTEasy等,它们提供了JAX-RS规范的具体实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1923461.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

很多人误解:谷歌账号就是谷歌邮箱账号吗?Google账号=Gmail?

在服务的过程中&#xff0c;我发现有一些朋友对于什么是Google账号、谷歌账号和gmail地址&#xff0c;谷歌邮箱和辅助邮箱等等的概念和用法搞得不够清爽&#xff0c;使得偶会会出现问题&#xff0c;甚至给谷歌账号带来一些风险。所以这篇文章&#xff0c;GG账号服务为大家解析一…

LeetCode刷题之HOT100之打家劫舍Ⅲ

2024 7/13 七月就要过去一半了&#xff0c;伴随着蝉鸣&#xff0c;酷暑被窗户隔离&#xff0c;我坐在凳子上&#xff0c;有一只蚊子不愿意放过我。 1、题目描述 2、算法分析 前面做过打家劫舍Ⅱ&#xff0c;今天来做打家劫舍Ⅲ&#xff0c;小偷也是越来越聪明了&#xff0c;意…

集训 Day 3 总结 虚树 + dfs tree + 基环树

虚树 虚树&#xff0c;顾名思义是 只关注原树上的某些 关键点&#xff0c;在保留原树祖孙关系的前提下建出的一棵边数、点数大大减少的树 适用于优化某些在整棵树上进行 d p dp dp、 d f s dfs dfs 的问题 通常是题目中出现多次询问&#xff0c;每次给出树上的一些关键点&a…

唯一索引插入引发的死锁问题

MySQL 8.4.0 RR隔离级别 场景复现 分析下面SQL死锁的场景 对于switch表&#xff0c;有主键索引id和唯一索引(uid、type)。 CREATE TABLE switch (id int NOT NULL AUTO_INCREMENT COMMENT Unique identifier for each switch,uid int NOT NULL COMMENT User ID associated wi…

Autoware 定位之基于ARTag的landmark定位(六)

Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务&#xff0c;并且需要GPU资源&#xff0c;可以考虑使用UCloud云计算旗下的Compshare的GPU算力云平台。他们提供高性价比的4090 GPU&#xff0c;按时收费每卡2.6元&#xff0c;月卡只需要1.7元每小时&…

AI大模型来了,低代码还有机会吗?

AI大模型的突飞猛进&#xff0c;不仅引领了技术的革新浪潮&#xff0c;也为各行各业的发展带来了前所未有的挑战与机遇。近年来&#xff0c;随着人工智能技术的不断进步&#xff0c;关于各行各业将被AI取代的论调此起彼伏&#xff0c;引发了许多从业者的不安。 几年前&#xf…

Flowable-流程图标与流程演示

BPMN 2.0是业务流程建模符号2.0的缩写。它由Business Process Management Initiative这个非营利协会创建并不断发展。作为一种标识&#xff0c;BPMN 2.0是使用一些符号来明确业务流程设计流程图的一整套符号规范&#xff0c;它能增进业务建模时的沟通效率。目前BPMN2.0是最新的…

AI人工智能填词,唱响心中独特旋律

在音乐的无垠宇宙中&#xff0c;每个人的内心都有一段独一无二的旋律在悄然回荡。而如今&#xff0c;人工智能填词正以其神奇的力量&#xff0c;帮助我们将这些深藏心底的旋律化作动人的歌词&#xff0c;让它们得以放声歌唱。 “妙笔生词智能写歌词软件&#xff08;veve522&am…

【QT】布局管理器

布局管理器 布局管理器1. 垂直布局2. 水平布局3. 网格布局4. 表单布局5. Spacer 布局管理器 之前使⽤ Qt 在界⾯上创建的控件, 都是通过 “绝对定位” 的⽅式来设定的&#xff1b;也就是每个控件所在的位置, 都需要计算坐标, 最终通过 setGeometry 或者 move ⽅式摆放过去。 …

一文彻底学会Vue3路由:全面讲解路由流程、路由模式、传参等——全栈开发之路--前端篇(7)路由详解

全栈开发一条龙——前端篇 第一篇&#xff1a;框架确定、ide设置与项目创建 第二篇&#xff1a;介绍项目文件意义、组件结构与导入以及setup的引入。 第三篇&#xff1a;setup语法&#xff0c;设置响应式数据。 第四篇&#xff1a;数据绑定、计算属性和watch监视 第五篇 : 组件…

pytorch-pytorch之LSTM

目录 1. nn.LSTM2. nn.LSTMCell 1. nn.LSTM 初始化函数输入参数与RNN相同&#xff0c;分别是input_size&#xff0c;hidden_size和num_layer foward函数也与RNN类似&#xff0c;只不过返回值除了out外&#xff0c;ht变为(ht,ct) 代码见下图&#xff1a; 2. nn.LSTMCell 初…

SQL优化-索引

什么是索引&#xff1f; 索引&#xff08; index &#xff09;是帮助 MySQL 高效获取数据的数据结构 ( 有序 ) 。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c; 这…

这是我见过最棒的大模型干货!!!

大模型技术的发展和迭代2024年已经可以按天来计算了&#xff0c;几乎每天都有新的大模型和技术登场。 从基座模型Mamba2&#xff0c;Jamaba&#xff0c;到Dora&#xff0c;LoftQ&#xff0c;GaLore等最新的微调技术&#xff1b;KTO&#xff0c;IPO&#xff0c;SimPO等微调技术…

STM32实战篇:按键(外部输入信号)触发中断

功能要求 将两个按键分别与引脚PA0、PA1相连接&#xff0c;通过按键按下&#xff0c;能够触发中断响应程序&#xff08;不需明确功能&#xff09;。 代码流程如下&#xff1a; 实现代码 #include "stm32f10x.h" // Device headerint main() {//开…

ZGC的流程图

GC标记过程 1、初始标记 扫描所有线程栈的根节点&#xff0c;然后再扫描根节点直接引用的对象并进行标记。这个阶段需要停顿所有的应用线程&#xff08;STW&#xff09;&#xff0c;但由于只扫描根对象直接引用的对象&#xff0c;所以停顿时间很短。停顿时间高度依赖根节点的数…

鸿蒙HarmonyOS应用开发为何选择ArkTS不是Java?

前言 随着智能设备的快速发展&#xff0c;操作系统的需求也变得越来越多样化。为了满足不同设备的需求&#xff0c;华为推出了鸿蒙HarmonyOS。 与传统的操作系统不同&#xff0c;HarmonyOS采用了一种新的开发语言——ArkTS。 但是&#xff0c;刚推出鸿蒙系统的时候&#xff0…

uni-app 保存号码到通讯录

1、 添加模块 2、添加权限 3、添加策略 Android&#xff1a; "permissionExternalStorage" : {"request" : "none","prompt" : "应用保存运行状态等信息&#xff0c;需要获取读写手机存储&#xff08;系统提示为访问设备上的照片…

Prometheus + alermanager + webhook-dingtalk 告警

添加钉钉机器人 1. 部署 alermanager 1.1 下载软件包 wget https://github.com/prometheus/alertmanager/releases/download/v0.26.0/alertmanager-0.26.0.linux-amd64.tar.gz 网址 &#xff1a;Releases prometheus/alertmanager (github.com) 1.2 解压软件包 mkdir -pv …

用 Kotlin 编写四则运算计算器:从零开始的简单教程

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

电-气阀门定位器YT-1000系列产品说明

电-气阀门定位器YT-1000系列 使用注意事项 • 搬运安装或使用中对产品过大的震动或撞击会成为产品故障的原因。 • 超过规定参数范围使用也会成为产品故陷的原因。 • 不使用的气路接口要用堵塞堵住。 • 不使用产品而长时间放悝在室外时,要盖上产品外壳以免雨水进入产品…