Java控制器无论我做什么都始终返回404。

huangapple go评论84阅读模式
英文:

Java controller always return a 404 no matter what I do

问题

package com.example.accessingdatamysql;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping(path="/demo")
public class MainController {
    @Autowired
    private UserRepository userRepository;

    @PostMapping(path="/add")
    public @ResponseBody String addNewUser (@RequestParam String name, @RequestParam String email) {
        User n = new User();
        n.setName(name);
        n.setEmail(email);
        userRepository.save(n);
        return "Saved";
    }

    @GetMapping(path="/all")
    public @ResponseBody Iterable<User> getAllUsers() {
        return userRepository.findAll();
    }
}
package com.braintobytes.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.braintobytes.data.repository.CurrencyRepository;

@RestController
@RequestMapping("/demo")
public class CurrencyController {
    @Autowired
    private CurrencyRepository currencyRepository;

    @GetMapping("/currency")
    public String getCurrency() {
        return "currency";
    }
}
<!-- pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- ... Other configurations ... -->
    <dependencies>
        <!-- ... Other dependencies ... -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
        </dependency>
        <!-- ... Other dependencies ... -->
    </dependencies>
    <!-- ... Other configurations ... -->
</project>

Please note that your issue might be due to various factors such as incorrect URL paths, incorrect database configurations, or other parts of your project setup. The code snippets provided above are based on the content you've shared, but debugging specific issues might require a deeper analysis of your entire project.

英文:

I was following an example from the spring boot documentation and the java controller always returns a 404 for some reason

This is what I tried

package com.example.accessingdatamysql;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller // This means that this class is a Controller
@RequestMapping(path=&quot;/demo&quot;) // This means URL&#39;s start with /demo (after Application path)
public class MainController {
  @Autowired // This means to get the bean called userRepository
         // Which is auto-generated by Spring, we will use it to handle the data
  private UserRepository userRepository;

  @PostMapping(path=&quot;/add&quot;) // Map ONLY POST Requests
  public @ResponseBody String addNewUser (@RequestParam String name
      , @RequestParam String email) {
    // @ResponseBody means the returned String is the response, not a view name
    // @RequestParam means it is a parameter from the GET or POST request

    User n = new User();
    n.setName(name);
    n.setEmail(email);
    userRepository.save(n);
    return &quot;Saved&quot;;
  }

  @GetMapping(path=&quot;/all&quot;)
  public @ResponseBody Iterable&lt;User&gt; getAllUsers() {
    // This returns a JSON or XML with the users
    return userRepository.findAll();
  }
}

which is the example given by spring boot here https://spring.io/guides/gs/accessing-data-mysql/

Then I also tried

@RestController
@RequestMapping(&quot;/demo&quot;)
public class GreetingClass {

	@GetMapping(&quot;/greeting&quot;)
	public String getGreeting() {
		return &quot;hello&quot;;
	}
}

.pom file:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;
	xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
	xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
	&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
	&lt;parent&gt;
		&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
		&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
		&lt;version&gt;2.3.2.RELEASE&lt;/version&gt;
		&lt;relativePath /&gt; &lt;!-- lookup parent from repository --&gt;
	&lt;/parent&gt;
	&lt;groupId&gt;com.braintobytes&lt;/groupId&gt;
	&lt;artifactId&gt;Finance_microservice&lt;/artifactId&gt;
	&lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
	&lt;name&gt;Finance_microservice&lt;/name&gt;
	&lt;description&gt;Finance service&lt;/description&gt;

	&lt;properties&gt;
		&lt;java.version&gt;1.8&lt;/java.version&gt;
	&lt;/properties&gt;

	&lt;dependencies&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
			&lt;artifactId&gt;spring-boot-starter-data-rest&lt;/artifactId&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
			&lt;artifactId&gt;spring-boot-starter-mail&lt;/artifactId&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
			&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
			&lt;artifactId&gt;spring-boot-starter-webflux&lt;/artifactId&gt;
		&lt;/dependency&gt;

		&lt;dependency&gt;
			&lt;groupId&gt;mysql&lt;/groupId&gt;
			&lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
			&lt;scope&gt;runtime&lt;/scope&gt;
		&lt;/dependency&gt;
		&lt;!-- https://mvnrepository.com/artifact/javax.persistence/javax.persistence-api --&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;javax.persistence&lt;/groupId&gt;
			&lt;artifactId&gt;javax.persistence-api&lt;/artifactId&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
			&lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
			&lt;scope&gt;test&lt;/scope&gt;
			&lt;exclusions&gt;
				&lt;exclusion&gt;
					&lt;groupId&gt;org.junit.vintage&lt;/groupId&gt;
					&lt;artifactId&gt;junit-vintage-engine&lt;/artifactId&gt;
				&lt;/exclusion&gt;
			&lt;/exclusions&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;io.projectreactor&lt;/groupId&gt;
			&lt;artifactId&gt;reactor-test&lt;/artifactId&gt;
			&lt;scope&gt;test&lt;/scope&gt;
		&lt;/dependency&gt;
	&lt;/dependencies&gt;

	&lt;build&gt;
		&lt;plugins&gt;
			&lt;plugin&gt;
				&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
				&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
			&lt;/plugin&gt;
		&lt;/plugins&gt;
	&lt;/build&gt;

&lt;/project&gt;

I know this is weird, I set up everything as instructed on the page but apparently nothing works, and I also checked other questions similar to this none of them answer my question.

It does seem that the tomcat server is hit, because it says when I make a call

o.s.web.servlet.DispatcherServlet        : Completed initialization in 9 ms

but then I get with this call curl 'http://localhost:8080/demo/greeting' and with 'http://localhost:8080/demo/all'

curl : The remote server returned an error: (404) Not Found.

Logs (the file path is removed on the first line):

  .   ____          _            __ _ _
 /\\ / ___&#39;_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | &#39;_ | &#39;_| | &#39;_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  &#39;  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.2.RELEASE)

2020-08-31 08:19:16.508  INFO 20708 --- [           main] c.b.f.FinanceMicroserviceApplication     : Starting FinanceMicroserviceApplication on DESKTOP-A65224I with PID 20708 ()
2020-08-31 08:19:16.510  INFO 20708 --- [           main] c.b.f.FinanceMicroserviceApplication     : No active profile set, falling back to default profiles: default
2020-08-31 08:19:17.096  INFO 20708 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-08-31 08:19:17.101  INFO 20708 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-08-31 08:19:17.101  INFO 20708 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.37]
2020-08-31 08:19:17.150  INFO 20708 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-08-31 08:19:17.150  INFO 20708 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 618 ms
2020-08-31 08:19:17.465  INFO 20708 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService &#39;applicationTaskExecutor&#39;
2020-08-31 08:19:17.675  INFO 20708 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path &#39;&#39;
2020-08-31 08:19:17.681  INFO 20708 --- [           main] c.b.f.FinanceMicroserviceApplication     : Started FinanceMicroserviceApplication in 1.328 seconds (JVM running for 1.835)
2020-08-31 08:20:21.893  INFO 20708 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet &#39;dispatcherServlet&#39;
2020-08-31 08:20:21.893  INFO 20708 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet &#39;dispatcherServlet&#39;
2020-08-31 08:20:21.905  INFO 20708 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 12 ms

Response:

{
    &quot;timestamp&quot;: &quot;2020-08-31T13:20:21.930+00:00&quot;,
    &quot;status&quot;: 404,
    &quot;error&quot;: &quot;Not Found&quot;,
    &quot;message&quot;: &quot;&quot;,
    &quot;path&quot;: &quot;/demo/greeting&quot;
}

This works if I do this:

https://github.com/BraintoByte/Test_App_Stack/tree/master/demo

Different example:

I have attached a different example with hirarchy exactly the same but business logic omitted:

Code in controller:

package com.braintobytes.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.braintobytes.data.Currency;
import com.braintobytes.data.repository.CurrencyRepository;

@RestController
@RequestMapping(&quot;/demo&quot;)
public class CurrencyController {
	@Autowired
	private CurrencyRepository currencyRepository;
	
	@GetMapping(&quot;/currency&quot;)
	public String getCurrency() {
		return &quot;currency&quot;;
	}
}

Project hierarchy:

Java控制器无论我做什么都始终返回404。

Same exact pom and in application.properties:

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mydatabase
spring.datasource.username=myusername
spring.datasource.password=mypassword

答案1

得分: 3

你的控制器所在的包是 - com.example.accessingdatamysql

Spring Boot 的启动日志显示你的主应用程序类 c.b.f.FinanceMicroserviceApplication 位于另一个无关的包层次结构中。

Spring Boot 建议将主应用程序类放在高于其他类的根包中,以便组件扫描可以顺利进行。

如果你将包 com.example 保持为根包,并将主应用程序类 FinanceMicroserviceApplication 移动到其中,那么一切都应该正常工作。

如果你不遵循 Spring Boot 对包层次结构的建议,那么你需要使用 @SpringBootApplication 注解显式指定要扫描的包。

英文:

Your controller is in package - com.example.accessingdatamysql

Spring boot startup log shows your main application class c.b.f.FinanceMicroserviceApplication is in another non related package hierarchy.

Spring boot recommends to locate main application class in a root package above other classes so that the component scan works out of box.

If you keep package com.example as root package and move your main application class FinanceMicroserviceApplication to it then everything should work as expected.

If you don't follow Spring boot recommendation for package hierarchy then you need to explicitly specify packages to scan with @SpringBootApplication annotation.

答案2

得分: 0

好的,以下是翻译好的部分:

好的,以上的建议都没有奏效,不过我们走在了正确的道路上。

将结构更改如下有效:

Java控制器无论我做什么都始终返回404。

在 application.properties 中还存在路径问题,因此我进行了如下更改:

spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}

更改为:

jdbc:mysql://localhost

最后:

package com.braintobytes.finance.data.repository;

import org.springframework.data.repository.CrudRepository;

import com.braintobytes.finance.data.Currency;

public interface CurrencyRepository extends CrudRepository&lt;Currency, Integer&gt; {

}

哇!

英文:

Alright so none of the suggestions above worked, we were on the right path though.

Changing the structure as so worked:

Java控制器无论我做什么都始终返回404。

There was also a pathing problem in the application.properties and thus I changed as so:

spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}

To:

jdbc:mysql://localhost

And finally:

package com.braintobytes.finance.data.repository;

import org.springframework.data.repository.CrudRepository;

import com.braintobytes.finance.data.Currency;

public interface CurrencyRepository extends CrudRepository&lt;Currency, Integer&gt; {

}

Woah!

答案3

得分: 0

对于任何遇到这个奇怪问题的人,只需将Spring Boot的主类移动到应用程序的主包中,类似于这样,我的主类名叫Demo2Application。

英文:

For anyone whom facing this wired issue, just move the main class of spring boot to become in the main package of the application, something like that, my main class named, Demo2Application

Java控制器无论我做什么都始终返回404。

huangapple
  • 本文由 发表于 2020年8月31日 12:08:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/63664671.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定