英文:
Spring Webflux returns 404 ( Not Foud )
问题
我需要以响应式的方式使用 Spring Webflux 保存一些值。但是当我发送请求时,会收到 404 状态作为响应。
pom.xml
----------
<!-- language: xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
EmpController 类
---------------------
<!-- language: java -->
@RestController
@RequestMapping("/emp")
public class EmpController {
private EmployeeRepository empRepo;
@Autowired
public EmpController(EmployeeRepository empRepo) {
this.empRepo = empRepo;
}
@PostMapping("/save")
@Consumes({MediaType.APPLICATION_JSON})
public void saveEmp(@RequestBody Mono<Employee> emp) {
emp.subscribe(e -> {
e.setDate(new Date());
empRepo.saveEmp(e);
});
}
}
当我通过 PostMan 发送请求时,返回 404(未找到)。
[![enter image description here][2]][2]
[![enter image description here][1]][1]
英文:
I have to save some values in a reactive way using spring Webflux. But when I send the request then 404 status is returned as a response.
pom.xml
<!-- language: xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
EmpController class
<!-- language: java -->
@RestController
@RequestMapping("/emp")
public class EmpController {
private EmployeeRepository empRepo;
@Autowired
public EmpController(EmployeeRepository empRepo)
{
this.empRepo=empRepo;
}
@PostMapping("/save")
@Consumes({MediaType.APPLICATION_JSON})
public void saveEmp(@RequestBody Mono<Employee> emp)
{
emp.subscribe(e-> {
e.setDate(new Date());
empRepo.saveEmp(e);
});
}
}
When I send the request via PostMan then 404(not found) is returned.
答案1
得分: 2
JAX-RS
是Java EE
中关于如何编写REST API的规范。随后,几个库实现了这个规范,比如Jersey
或者restEasy
。在构建Java EE应用程序时,你需要其中一个这些库来能够构建REST API。
Spring构建了他们自己的构建REST API的方式,spring-web
用于非响应式应用程序,而spring-webflux
用于响应式应用程序。
Jersey
和restEasy
(据我所知)只适用于构建非响应式应用程序。
为了让你的代码工作,你需要移除以下部分:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
Jersey
是JAX-RS
的Java EE实现。它在Java EE中用于构建Java EE风格的REST API。你正在构建一个使用Spring Webflux的响应式应用程序,它有自己构建REST API的方式。
Spring并不是一个Java EE应用程序。当你添加了那个依赖项时,Spring假定你想要构建一个Spring应用程序,但不使用Spring内置的REST API函数和注解等,因此它没有注册你用Spring构建REST API的方式编写的代码。
它认为你将要按照"Jersey方式"编写REST API,如果你使用Jersey,你需要手动注册你的API类。而(据我所知)Jersey只适用于非Webflux应用程序。
这基本上都是基础知识,如果你不明白为什么,我建议你先阅读并构建一个常规的Spring Boot应用程序,然后再尝试Webflux。
我建议你阅读以下部分:
英文:
JAX-RS
is a specification within Java EE
of how to code REST api's. Several libraries have then implemented said specification, Like Jersey
or restEasy
. WHen building a Java EE application, you needed one of these libraries to be able to build a rest api.
Spring built their own way of building rest apis spring-web
for non reactive applications, and spring-webflux
for reactive applications.
Jersey
and restEasy
(to my knowledge) only works if you are building a non-reactive application.
In order to make your code work you need to remove:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
Jersey
is a Java EE implementation of JAX-RS
. It is used in Java EE to build Java EE styled rest apis. You are building a reactive application, using Spring Webflux which has its own way of building REST api's.
Spring is not a Java EE application. When you added that dependency, spring assumed that you wanted to build a Spring Application but not use the Spring built in REST api functions and annotations etc, so it didn't register your code, that you have written with Springs way of building rest apis.
It assumed you were going to write a REST api the "jersey way" and if you are using jersey you need to register your api classes manually. And (to my knowledge) Jersey only works with non-webflux applications.
This is all mainly basic knowledge, and if you dont understand why i suggest you read up and build a regular spring boot application, before trying out webflux.
I suggest you read the following parts:
Reactive programming, Reactor getting started
答案2
得分: 0
以下是您要翻译的内容:
奇怪的是,当我移除了jersey
的依赖后,它就起作用了。对于背后的原因还不太确定。
我发起了一个拉取请求,您可以合并相同的更改
https://github.com/Benzeman97/reactive-async-app/pull/1
英文:
It is Strange but when I removed jersey
dependency and it Worked. Still not sure about the reason behind it.
raised pull request you the merge the same to take the changes I have done
https://github.com/Benzeman97/reactive-async-app/pull/1
答案3
得分: 0
你需要移除以下的Jersey依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
移除的原因是 spring-boot-starter-jersey
是用于使用 JAX-RS 和 Jersey 构建 RESTful web 应用的入门依赖。由于你在项目中使用了它,Spring 就不会使用内置的 Spring 功能来创建像 @GetMapping
、@PostMapping
这样的 REST API。
如果你想继续使用 Jersey 来创建 REST API,可以使用 @GET
注解来标记 GET 请求的 API,并使用 @Produces
来定义映射,如下所示:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.springframework.stereotype.Service;
@Service
@Path("/hello")
public class HelloService {
@GET
@Produces("text/plain")
public String hello() {
return "Hello from Spring";
}
}
另外,你需要在 JerseyConfig
类中注册这个服务类:
import com.zetcode.endpoint.HelloService;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(HelloService.class);
}
}
如果你想使用 Spring 内置的功能并且使用响应式编程,只需移除 Jersey 依赖,并添加 webflux
依赖来创建你的 REST API。
英文:
You need to remove below Jersey dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
The reason behind is that the spring-boot-starter-jersey is a starter for building Restful web applications using JAX-RS and Jersey. Since you have used it in your project the spring does not use in built spring functions for rest api's like @GetMapping, @PostMapping.
If you want to use jersey to create the rest api then use @GET annotation for Get api and the @Produces to defined the mapping as below.
Eg.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.springframework.stereotype.Service;
@Service
@Path("/hello")
public class HelloService {
@GET
@Produces("text/plain")
public String hello() {
return "Hello from Spring";
}
}
Also you have to register this class in JerseyConfig.
import com.zetcode.endpoint.HelloService;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(HelloService.class);
}
}
And if you want to go ahead with the spring build in functions and use reactive just remove the jersey dependency and use webflux dependency to create your rest api's.
答案4
得分: 0
我有同样的问题。
解决方法:
- 前往 application.properties 文件,
- 移除 server.servlet.context-path 配置,
- 添加 spring.webflux.base-path 配置。
英文:
I had the same problem.
The solution:
- go to application.properties,
- remove server.servlet.context-path
- and add spring.webflux.base-path
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论