目录
二、创建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接口和注解:
-
javax.ws.rs.core.Application
:- 用于定义JAX-RS应用程序,可以注册JAX-RS资源和提供者。
-
javax.ws.rs.Path
:- 注解用于定义资源的URI路径。
-
HTTP方法注解:
@GET
:处理HTTP GET请求。@POST
:处理HTTP POST请求。@PUT
:处理HTTP PUT请求。@DELETE
:处理HTTP DELETE请求。@PATCH
:处理HTTP PATCH请求。
-
javax.ws.rs.Produces
:- 注解用于指定资源方法可以生成的媒体类型(如
application/json
,text/html
)。
- 注解用于指定资源方法可以生成的媒体类型(如
-
javax.ws.rs.Consumes
:- 注解用于指定资源方法可以消费的媒体类型。
-
javax.ws.rs.core.MediaType
:- 类提供定义媒体类型的常量和实用方法。
-
javax.ws.rs.core.Response
:- 类用于构造和表示HTTP响应,包括状态码和响应体。
-
javax.ws.rs.GET
等:- 除了
@GET
,还包括@POST
,@PUT
,@DELETE
等,用于将资源类的方法映射到特定的HTTP方法。
- 除了
-
javax.ws.rs.PathParam
:- 注解用于从URI模板中提取参数。
-
javax.ws.rs.QueryParam
:- 注解用于绑定查询参数。
-
javax.ws.rs.FormParam
:- 注解用于绑定表单提交的数据。
-
javax.ws.rs.HeaderParam
:- 注解用于获取HTTP请求头的值。
-
javax.ws.rs.CookieParam
:- 注解用于获取HTTP cookie的值。
-
javax.ws.rs.MatrixParam
:- 注解用于处理URI矩阵参数。
-
javax.ws.rs.core.Request
和javax.ws.rs.core.SecurityContext
:- 接口用于访问HTTP请求的详细信息和安全上下文。
-
javax.ws.rs.ext.Provider
:- 注解用于标记扩展提供者,如消息体读取器、消息体编写器等。
JAX-RS还定义了其他一些接口和类,用于更高级的功能,如异常处理、拦截器、容器特定的配置等。使用JAX-RS,开发者可以使用注解来简化Web服务的客户端和服务端的开发和部署。基于JAX-RS实现的框架有Jersey、RESTEasy等,它们提供了JAX-RS规范的具体实现。