簡體   English   中英

Spring 在 REST API 上僅調用 404

[英]Spring Boot 404 on REST API calls only

問題:

我正在開發需要部署在 tomcat(WAR 文件)上的 Spring-Boot Web 應用程序。 When running the application as Java (right click application.java file and run as Java in Eclipse) or running via mvnw.cmd spring-boot:run, everything works PERFECTLY (home page shows, all CRUD operations work).

When I export a WAR file and deploy to tomcat, my static web content and homepage still load fine, but any API calls return a 404 response.

該項目是使用 Spring Initializr 創建的。 我嘗試通過 Eclipse 戰爭導出和 mvnw.cmd package 導出。 將 WAR 文件放在服務器上的 webapps 目錄中並運行。

目錄結構:

在此處輸入圖像描述

申請文件:

package com.blank.systemshare;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SystemshareApplication {

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

}

Servlet初始化器:

package com.blank.systemshare;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SystemshareApplication.class);
    }

}

Controller:

package com.blank.systemshare.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.blank.systemshare.exception.ResourceNotFoundException;
import com.blank.systemshare.model.System;
import com.blank.systemshare.repository.SystemRepository;

@RestController
@RequestMapping("/api/v1/")
public class SystemController {

    @Autowired
    private SystemRepository systemRepository;

    // get systems

    @GetMapping("systems")
    public List<System> getSystems() {
        return this.systemRepository.findAllByOrderByVersionDesc();
    }

    // create system
    @PostMapping("systems")
    public System createSystem(@RequestBody System system) {
        return this.systemRepository.save(system);
    }

    // update system
    @PutMapping("systems/{id}")
    public ResponseEntity<System> updateSystem(@PathVariable(value = "id") Long systemId,
                                               @Valid @RequestBody System systemDetails) throws ResourceNotFoundException {

        System system = systemRepository.findById(systemId)
                .orElseThrow(() -> new ResourceNotFoundException("System not found - ID: " + systemId));

        system.setVersion(systemDetails.getVersion());
        system.setUrl(systemDetails.getUrl());
        system.setCredentials(systemDetails.getCredentials());
        system.setFrameworks(systemDetails.getFrameworks());
        system.setFw_credentials(systemDetails.getFw_credentials());
        system.setNotes(systemDetails.getNotes());
        system.setOwner(systemDetails.getOwner());

        return ResponseEntity.ok(this.systemRepository.save(system));
    }

    //delete system
    @DeleteMapping("systems/{id}")
    public  Map<String, Boolean> deleteSystem(@PathVariable(value = "id") Long systemId) throws ResourceNotFoundException {

        System system = systemRepository.findById(systemId)
                .orElseThrow(() -> new ResourceNotFoundException("System not found - ID: " + systemId));

        this.systemRepository.delete(system);

        Map<String, Boolean> response = new HashMap<>();
        response.put("deleted",  Boolean.TRUE);

        return response;
    }

}

存儲庫:

package com.blank.systemshare.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.blank.systemshare.model.System;

@Repository
public interface SystemRepository extends JpaRepository<System, Long>{
    public List<System> findAllByOrderByVersionDesc();
}

應用程序.js

var systemShareApp = angular.module('systemShareApp', [])
.controller('mainController', ($scope, $http, $window) => {

    $scope.version = '1.0';
    $scope.systemData = {};
    $scope.createSystemFormData = {};
    $scope.editSystemFormData = {};

    $scope.dbErrorStatus = false;



    // Get all systems
    var getAllSystems = function() {
        $http.get('/systemshare/api/v1/systems')
        .success((data) => {
            $scope.systemData = data;
            $scope.dbErrorStatus = false;
            console.log(data);
        })
        .error((error) => {
            console.log('Error: ' + error);
            $scope.dbErrorStatus = true;
        });
    };

  //initial load of page - get systems.
    getAllSystems();




    // Create a new system
    $scope.createSystem = () => {

        $http.post('/systemshare/api/v1/systems', $scope.createSystemFormData)
            .success((data) => {
                $scope.createSystemFormData = {};
                getAllSystems();
            })
            .error((error) => {
                console.log('Error: ' + error);
            });
    };


    // Delete a system
    $scope.deleteSystem = (systemID) => {
        $http.delete('/systemshare/api/v1/systems/' + systemID)
            .success((data) => {
                getAllSystems();
            })
            .error((data) => {
                console.log('Error: ' + data);
            });
    };

    // Update a system
    $scope.updateSystem = (systemID) => {
        $http.put('/systemshare/api/v1/systems/' + systemID, $scope.editSystemFormData)
            .success((data) => {
                $scope.editSystemFormData = {};
                getAllSystems();
            })
            .error((data) => {
                console.log('Error: ' + data);
            });
    };

    //select system function for transfer of object data in list to modal. 
    $scope.selectSystem = function(system) {

        $scope.thisSystem = system;
        //editSystemFormData Modal updates:
        $scope.editSystemFormData.owner = system.owner;
        $scope.editSystemFormData.version = system.version;
        $scope.editSystemFormData.url = system.url;
        $scope.editSystemFormData.credentials = system.credentials;
        $scope.editSystemFormData.frameworks = system.frameworks;
        $scope.editSystemFormData.fw_credentials = system.fw_credentials;
        $scope.editSystemFormData.notes = system.notes;
    };
});

應用程序屬性

spring.datasource.url=jdbc:postgresql://xx.xx.xxx.xxx:5432/systemshare
spring.datasource.username=xx
spring.datasource.password=xx
spring.jpa.show-sql=true

## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto=update

server.servlet.contextPath=/systemshare

pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.6.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.blank</groupId>
        <artifactId>systemshare</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
        <name>systemshare</name>
        <description>System Share Project</description>

        <properties>
            <java.version>1.8</java.version>
        </properties>

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>

        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
</project>

mvnw.cmd spring-boot:run output(工作場景)

mvnw.cmd spring-boot:run
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< com.blank:systemshare >------------------------
[INFO] Building systemshare 0.0.1-SNAPSHOT
[INFO] --------------------------------[ war ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.2.6.RELEASE:run (default-cli) > test-compile @ systemshare >>>
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ systemshare ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 4 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ systemshare ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 8 source files to C:\Users\user\Documents\JavaProjects\systemshare\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ systemshare ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Users\user\Documents\JavaProjects\systemshare\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ systemshare ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\user\Documents\JavaProjects\systemshare\target\test-classes
[INFO]
[INFO] <<< spring-boot-maven-plugin:2.2.6.RELEASE:run (default-cli) < test-compile @ systemshare <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:2.2.6.RELEASE:run (default-cli) @ systemshare ---
[INFO] Attaching agents: []

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.6.RELEASE)

2020-04-21 14:50:58.430  INFO 19748 --- [  restartedMain] c.p.systemshare.SystemshareApplication   : Starting SystemshareApplication on L37853WUS with PID 19748 (C:\Users\user\Documents\JavaProjects\systemshare\target\classes started by userin C:\Users\mck
eb2\Documents\JavaProjects\systemshare)
2020-04-21 14:50:58.435  INFO 19748 --- [  restartedMain] c.p.systemshare.SystemshareApplication   : No active profile set, falling back to default profiles: default
2020-04-21 14:50:58.513  INFO 19748 --- [  restartedMain] o.s.b.devtools.restart.ChangeableUrls    : The Class-Path manifest attribute in C:\Users\user\.m2\repository\org\glassfish\jaxb\jaxb-runtime\2.3.2\jaxb-runtime-2.3.2.jar referenced one or more files th
at do not exist: file:/C:/Users/user/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/jakarta.xml.bind-api-2.3.2.jar,file:/C:/Users/user/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/txw2-2.3.2.jar,file:/C:/Users/user/.m2/repository/org/glassfi
sh/jaxb/jaxb-runtime/2.3.2/istack-commons-runtime-3.0.8.jar,file:/C:/Users/user/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/stax-ex-1.8.1.jar,file:/C:/Users/user/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/FastInfoset-1.2.16.jar,file:/C:/U
sers/user/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.2/jakarta.activation-api-1.2.1.jar
2020-04-21 14:50:58.513  INFO 19748 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-04-21 14:50:58.513  INFO 19748 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2020-04-21 14:50:59.303  INFO 19748 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-04-21 14:50:59.383  INFO 19748 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 71ms. Found 1 JPA repository interfaces.
2020-04-21 14:51:00.475  INFO 19748 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-04-21 14:51:00.489  INFO 19748 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-04-21 14:51:00.490  INFO 19748 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.33]
2020-04-21 14:51:00.674  INFO 19748 --- [  restartedMain] o.a.c.c.C.[.[localhost].[/systemshare]   : Initializing Spring embedded WebApplicationContext
2020-04-21 14:51:00.675  INFO 19748 --- [  restartedMain] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2161 ms
2020-04-21 14:51:00.858  INFO 19748 --- [  restartedMain] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-04-21 14:51:00.942  INFO 19748 --- [  restartedMain] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.12.Final
2020-04-21 14:51:01.117  INFO 19748 --- [  restartedMain] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-04-21 14:51:01.228  INFO 19748 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-04-21 14:51:01.603  INFO 19748 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-04-21 14:51:01.621  INFO 19748 --- [  restartedMain] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
2020-04-21 14:51:02.803  INFO 19748 --- [  restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-04-21 14:51:02.810  INFO 19748 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-04-21 14:51:02.825  INFO 19748 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2020-04-21 14:51:03.186  WARN 19748 --- [  restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view
to disable this warning
2020-04-21 14:51:03.334  INFO 19748 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-21 14:51:03.402  INFO 19748 --- [  restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: class path resource [static/index.html]
2020-04-21 14:51:03.571  INFO 19748 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path '/systemshare'
2020-04-21 14:51:03.575  INFO 19748 --- [  restartedMain] c.p.systemshare.SystemshareApplication   : Started SystemshareApplication in 5.624 seconds (JVM running for 6.47)
2020-04-21 14:51:17.737  INFO 19748 --- [nio-8080-exec-1] o.a.c.c.C.[.[localhost].[/systemshare]   : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-04-21 14:51:17.737  INFO 19748 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-04-21 14:51:17.745  INFO 19748 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 7 ms

WAR部署在tomcat(非工作場景)

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.6.RELEASE)

2020-04-21 14:55:49.434  INFO 12280 --- [ost-startStop-1] com.blank.systemshare.ServletInitializer  : Starting ServletInitializer v0.0.1-SNAPSHOT on L37853WUS with PID 12280 (C:\Users\user\Documents\Software\apache-tomcat-8.5.29\webapps\systemshare\WEB-INF\classes started by user in C:\Users\user\Documents\Software\apache-tomcat-8.5.29\bin)
2020-04-21 14:55:49.451  INFO 12280 --- [ost-startStop-1] com.blank.systemshare.ServletInitializer  : No active profile set, falling back to default profiles: default
2020-04-21 14:55:52.213  INFO 12280 --- [ost-startStop-1] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-04-21 14:55:52.458  INFO 12280 --- [ost-startStop-1] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 200ms. Found 1 JPA repository interfaces.
2020-04-21 14:55:53.923  INFO 12280 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 4212 ms
2020-04-21 14:55:55.125  INFO 12280 --- [ost-startStop-1] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-04-21 14:55:55.675  INFO 12280 --- [ost-startStop-1] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.12.Final
2020-04-21 14:55:56.461  INFO 12280 --- [ost-startStop-1] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-04-21 14:55:57.051  INFO 12280 --- [ost-startStop-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-04-21 14:55:57.633  INFO 12280 --- [ost-startStop-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-04-21 14:55:57.728  INFO 12280 --- [ost-startStop-1] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
2020-04-21 14:56:01.538  INFO 12280 --- [ost-startStop-1] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-04-21 14:56:01.578  INFO 12280 --- [ost-startStop-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-04-21 14:56:03.216  WARN 12280 --- [ost-startStop-1] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2020-04-21 14:56:03.699  INFO 12280 --- [ost-startStop-1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-21 14:56:04.075  INFO 12280 --- [ost-startStop-1] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: class path resource [static/index.html]
2020-04-21 14:56:04.472  INFO 12280 --- [ost-startStop-1] com.blank.systemshare.ServletInitializer  : Started ServletInitializer in 16.741 seconds (JVM running for 32.139)
21-Apr-2020 14:56:04.517 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive [C:\Users\user\Documents\Software\apache-tomcat-8.5.29\webapps\systemshare.war] has finished in [25,067] ms

來自 Chrome devtools 的特定 404 錯誤消息:

{
"timestamp":"2020-04-21T19:50:27.749+0000",
"status":404,
"error":"Not Found",
"message":"No message available",
"path":"/systemshare/api/v1/systems"
}

此外,tomcat 日志沒有顯示任何有用的信息。

刪除 ServletInitializer.java class 並將我的應用程序文件更新為以下解決了該問題(擴展 SpringBootServletInitializer 並覆蓋配置方法)。 請注意,我之前嘗試過,但是使用 Eclipse 和 InteliJ 構建了應用程序。 兩次仍然出現相同的問題。 我最后一次使用mvnw package ,並且在目標目錄中生成的 WAR 工作正常。

package com.blank.systemshare;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class SystemshareApplication extends SpringBootServletInitializer {

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

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SystemshareApplication.class);
    }

}

嘗試server.servlet.context-path而不是server.servlet.contextPath

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM