我是
Spring Boot
的新手,现在,我正在根据 本教程 构建应用程序。我的代码如下所示。
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>3.0.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.pokemonreview</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>api</name>
<description>Pokemon Review API Course 2022</description>
<properties>
<java.version>17</java.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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.0.6</version>
</dependency>
<dependency>
<groupId>com.rungroop</groupId>
<artifactId>web</artifactId>
<version>0.0.1-SNAPSHOT</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>
</plugins>
</build>
</project>
application.properties
文件(简单密码不是秘密,仅用于测试目的):spring.datasource.url=jdbc:postgresql://localhost:5432/pokemonApiCourse
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update
spring.security.user.name=test
spring.security.user.password=test
spring.jpa.show-sql=true
package com.pokemonreview.api.models;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class PokemonEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String type;
}
package com.pokemonreview.api.controllers;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpStatus;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.pokemonreview.api.models.PokemonEntity;
@RestController
@RequestMapping("/api/")
public class PokemonController {
@GetMapping("pokemon")
public ResponseEntity<List<PokemonEntity>> getPokemons() {
List<PokemonEntity> pokemonEntities = new ArrayList<PokemonEntity>();
pokemonEntities.add(new PokemonEntity(1L, "Squirtle", "Water"));
pokemonEntities.add(new PokemonEntity(2L, "Pikachu", "Electric"));
pokemonEntities.add(new PokemonEntity(3L, "Charmander", "Fire"));
return ResponseEntity.ok(pokemonEntities);
}
@GetMapping("pokemon/{id}")
public PokemonEntity pokemonDetail(@PathVariable Long id) {
return new PokemonEntity(id, "Squirtle", "Water");
}
@PostMapping("pokemon/create")
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity<PokemonEntity> createPokemon(@RequestBody PokemonEntity pokemonEntity) {
System.out.println(pokemonEntity.getName());
System.out.println(pokemonEntity.getType());
return new ResponseEntity<PokemonEntity>(pokemonEntity, HttpStatus.CREATED);
}
@PutMapping("pokemon/{id}/update")
public ResponseEntity<PokemonEntity> updatePokemon(@RequestBody PokemonEntity pokemonEntity,
@PathVariable("id") Long id) {
System.out.println(pokemonEntity.getName());
System.out.println(pokemonEntity.getType());
return ResponseEntity.ok(pokemonEntity);
}
@DeleteMapping("pokemon/{id}/delete")
public ResponseEntity<String> deletePokemon(@PathVariable("id") Long id) {
System.out.println(id);
return ResponseEntity.ok("Pokemon deleted successfully");
}
}
请注意……
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.0.6</version>
</dependency>
… 是我添加到
pom.xml
文件中的,但它确实 not 是否存在有所不同。 总是需要身份验证——不管是否添加Spring Security
依赖项! (这是为什么?在教程中,需要no授权!)——如果我不添加这两行……
spring.security.user.name=test
spring.security.user.password=test
…到
application.properties
文件,每次启动user
应用程序时都会生成用户Spring Boot
的密码。
此外,我的
id
变量不是 int
,如教程中所示,而是 Long
。
此外,请注意本教程中使用了
javax.persistence
包。唯一向我建议的包是jakarta.persistence
包。
Postman
问题:只允许GET
请求我正在使用
Postman
来测试 GET
、POST
、PUT
和 DELETE
请求,但只有 GET
请求有效。 每次,我的Authorization
选项卡中的选项设置如下:
Type:
Basic Auth
Username:
test
Password:
test
GET
请求GET
上的第一个 http://localhost:8080/api/pokemon
请求产生以下结果:
[
{
"id": 1,
"name": "Squirtle",
"type": "Water"
},
{
"id": 2,
"name": "Pikachu",
"type": "Electric"
},
{
"id": 3,
"name": "Charmander",
"type": "Fire"
}
]
在
GET
上第二次http://localhost:8080/api/pokemon/5
请求的结果如下:
{
"id": 5,
"name": "Squirtle",
"type": "Water"
}
POST
、PUT
和DELETE
请求POST
请求是在 http://localhost:8080/api/pokemon/create
上进行的,在 Body
选项卡中,选择了 raw
和 JSON
并插入以下内容:
{
"name": "Pidgey",
"type": "Earth"
}
如果我现在点击
Send
,什么都没有返回,状态401 Unauthorized
显示。
PUT
(http://localhost:8080/api/pokemon/5/update
)和DELETE
(http://localhost:8080/api/pokemon/5/delete
)请求产生相同的结果。
怎么了?在教程中,一切正常,我已经尝试根据我在互联网上找到的解决方案以多种方式调整
pom.xml
和application.properties
文件,但所有这些都没有解决我的问题。
我终于找到问题所在了。
Spring Security
没有正确配置。当我添加以下包和类时,一切都开始正常工作:
package com.pokemonreview.api.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf()
.disable()
.authorizeHttpRequests()
.requestMatchers("/api/pokemon/**")
.permitAll();
return httpSecurity.build();
}
}