【问题标题】:Spring boot and react application on the same port error finding index.jsSpring启动并在同一端口上反应应用程序错误发现index.js
【发布时间】:2021-12-03 07:50:24
【问题描述】:

我按照本教程在同一端口上初始化 react 和 spring boot 应用程序:这样当我启动 spring boot 应用程序时,我可以从 localhost:8080 查看站点

教程:https://medium.com/codex/run-react-frontend-and-springboot-backend-on-the-same-port-and-package-them-as-a-single-artifact-a790c9e10ac1

问题是当我转到 localhost:8080 时,我得到一个白标签错误页面(HTTP 403)。 这是我项目的结构:

我注意到,如果我在 com.websitePetcare 下移动除应用程序的主程序之外的所有包,我可以在 localhost:8080 上查看该站点,但找不到我的所有 Restcontroller 并且我无法访问 API。 如何保持项目结构(因为它有效)并在 localhost:8080 上显示站点?

config包下的WebSecurity配置:

package com.websitePetcare.Petcare.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import com.websitePetcare.Petcare.services.AuthenticationFilter;
import com.websitePetcare.Petcare.services.LoginFilter;
import com.websitePetcare.Petcare.services.UserDetailsServiceImpl;

import java.util.List;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl customUserDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
        corsConfiguration.setAllowedOrigins(List.of("*"));
        corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT","OPTIONS","PATCH", "DELETE"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setExposedHeaders(List.of("Authorization"));
        http.csrf().disable().cors().configurationSource(request -> corsConfiguration).and().authorizeRequests()
                .antMatchers(HttpMethod.POST, "/api/v1/users/login").permitAll()
                .antMatchers(HttpMethod.POST, "/api/v1/users/create").permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilterBefore(new LoginFilter("/api/v1/users/login", authenticationManager()),
                        UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(new AuthenticationFilter(),
                        UsernamePasswordAuthenticationFilter.class);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
}

包控制器下的UsersController:

package com.websitePetcare.Petcare.controllers;

import com.websitePetcare.Petcare.repositories.UserRepository;
import com.websitePetcare.Petcare.models.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

@RestController
@RequestMapping("/api/v1")
@CrossOrigin(origins = "http://localhost:8080")
public class UsersController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping("/")
    public ModelAndView home() {
        ModelAndView mav=new ModelAndView("index");
        return mav;
    }

    @GetMapping("/users")
    @ResponseStatus(HttpStatus.OK)
    public List<User> list() {
        return userRepository.findAll();
    }

    @PostMapping(value="/users/create")
    @ResponseStatus(HttpStatus.OK)
    public void create(@RequestBody User user) {
        userRepository.save(user);
    }
}

PetcareApplication 主:

package com.websitePetcare.Petcare;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;

@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class PetcareApplication {

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

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.6.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.websitePetcare</groupId>
    <artifactId>Petcare</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Petcare</name>
    <description>Backend and Frontend for Petcare Website</description>
    <properties>
        <java.version>17</java.version>
        <frontend-src-dir>${project.basedir}/src/main/frontend</frontend-src-dir>
        <node.version>v16.13.0</node.version>
        <yarn.version>v1.22.17</yarn.version>
        <frontend-maven-plugin.version>1.12.0</frontend-maven-plugin.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>5.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>5.6.0</version>
        </dependency>
        <dependency>
            <groupId>commons-configuration</groupId>
            <artifactId>commons-configuration</artifactId>
            <version>1.9</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.github.eirslett</groupId>
                <artifactId>frontend-maven-plugin</artifactId>
                <version>${frontend-maven-plugin.version}</version>

                <configuration>
                    <nodeVersion>${node.version}</nodeVersion>
                    <yarnVersion>${yarn.version}</yarnVersion>
                    <workingDirectory>${frontend-src-dir}</workingDirectory>
                    <installDirectory>${project.build.directory}</installDirectory>
                </configuration>

                <executions>
                    <execution>
                        <id>install-frontend-tools</id>
                        <goals>
                            <goal>install-node-and-yarn</goal>
                        </goals>
                    </execution>

                    <execution>
                        <id>yarn-install</id>
                        <goals>
                            <goal>yarn</goal>
                        </goals>
                        <configuration>
                            <arguments>install</arguments>
                        </configuration>
                    </execution>

                    <execution>
                        <id>build-frontend</id>
                        <goals>
                            <goal>yarn</goal>
                        </goals>
                        <phase>prepare-package</phase>
                        <configuration>
                            <arguments>build</arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <executions>
                    <execution>
                        <id>position-react-build</id>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <phase>prepare-package</phase>
                        <configuration>
                            <outputDirectory>${project.build.outputDirectory}/static</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>${frontend-src-dir}/build</directory>
                                    <filtering>false</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Application.properties:

spring.datasource.url=jdbc:postgresql://localhost:5432/websitepetcare
spring.datasource.username=postgres
spring.datasource.password=*******
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
spring.jpa.properties.hibernate.globally_quoted_identifiers=true

# Because detection is disabled you have to set correct dialect by hand.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect

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

spring.thymeleaf.prefix=file:///${user.dir}/target/classes/static/

【问题讨论】:

    标签: java reactjs spring-boot artifact yarn-v2


    【解决方案1】:

    前端和后端不要使用相同的端口号,spring-boot默认使用8080端口或者你可以改变spring的默认端口,你可以修改application.properties文件。

    server.port=8081
    

    (或)

    我认为您必须再次检查@CrossOrigin URL,您已提供 Spring-Application 的 URL,但实际上您将提供您的 React 应用程序的 URL。请检查并运行。 如果我错了,请忽略此消息。

    【讨论】:

    • 感谢您的回答,但它不正确。我想在同一个端口上运行后端和前端。问题是,当我打开 localhost:8080 时,我看不到我的前端(但带有邮递员的后端工作)并且我看到了一个白标签错误页面。
    • 好的,谢谢
    • 请确保您的网址是localhost:8080/api/v1,对吗?或者是其他东西?对于这里是索引页面的反应主页。
    • localhost:8080/api/v1 用于后端 API。如果我打开它,我会看到一个白标签错误页面。当我打开 localhost:8080 时,我必须看到索引页面,这可以通过 thymeleaf 插件来实现,该插件将前端的构建复制到后端的目标/类中。例如,如果我将 com.websitePetcare.Petcare 包之外的所有包(不是主包)移动到 com.websitePetcare,我可以看到我的前端,但后端将不再工作。
    【解决方案2】:

    我假设您想先创建前端的构建包并将其放在资源文件夹下。基本上在您的资源包中,您可以有静态文件夹,但您的前端构建结果在那里。我注意到您正在使用的教程中也对此进行了解释: 我可以建议使用frontend-maven-plugin 构建前端包:

                  <plugin>
                    <groupId>com.github.eirslett</groupId>
                    <artifactId>frontend-maven-plugin</artifactId>
                    <version>1.11.3</version>
                    <configuration>
                        <nodeVersion>v12.12.0</nodeVersion>
                        <npmVersion>6.9.0</npmVersion>
                        <workingDirectory>${project.basedir}/src/main/frontend</workingDirectory>
                    </configuration>
                    <executions>
                        <execution>
                            <id>install node and npm</id>
                            <goals>
                                <goal>install-node-and-npm</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>npm install</id>
                            <goals>
                                <goal>npm</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>npm run build</id>
                            <goals>
                                <goal>npm</goal>
                            </goals>
                            <configuration>
                                <arguments>run build</arguments>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
    

    maven-resources-pluginmaven-antrun-plugin 复制静态文件夹中的资源。

                 <plugin>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <phase>generate-resources</phase>
                            <configuration>
                                <target>
                                    <copy todir="${project.basedir}/src/main/resources/static">
                                        <fileset dir="${project.basedir}/src/main/frontend/build"/>
                                    </copy>
                                </target>
                            </configuration>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
    

    您可能需要添加如下资源处理程序:

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
          registry.addResourceHandler("/**")
              .addResourceLocations("classpath:/static/")
              .resourceChain(true)
              .addResolver(new PathResourceResolver() {
                @Override
                protected Resource getResource(String resourcePath,
                                               Resource location) throws IOException {
                  Resource requestedResource = location.createRelative(resourcePath);
                  return requestedResource.exists() && requestedResource.isReadable()
                      ? requestedResource
                      : new ClassPathResource("/static/index.html");
                }
              });
        }
    

    我希望这会有所帮助:))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-09
      • 2023-03-27
      • 2021-05-18
      • 1970-01-01
      • 2018-08-30
      • 2015-05-13
      • 2021-07-14
      • 1970-01-01
      相关资源
      最近更新 更多