簡體   English   中英

如何使用Spring Boot從Class中僅返回幾種類型?

[英]How to return only few types from Class using spring boot?

我有一個包含用戶信息(包括密碼字段)的類。 當用戶登錄時,它將返回類中的所有內容,包括密碼。 除了密碼或僅保留在數據庫中的任何重要數據之外,我如何不從類中返回所有內容。

我嘗試使用Map,這也返回了我想要的方式,但我希望有比Map更容易或更快速的東西。

幾乎沒有建議使用JsonIgnore和暫態的答案。 如果使用這兩種方法,則無法登錄。 因為我需要密碼才能登錄。

我的POJO班

@Entity
public class Users {

@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;

@Column(name = "firstname")
private String firstName;

@Column(name = "lastname")
private String lastName;

@Id
@Column(name = "username")
private String username;

@Column(name = "email")
private String email;

@Column(name = "role")
private String role;

@Column(name = "password")
private String password;

回購類

  public interface UsersRepository extends CrudRepository<Users, 
  String> {

public Users findByUsername(String username);
}

這是Rest Api

@GetMapping("/users/{username}")
public Map<String, Object> usersCheck(@PathVariable String 
 username) {
    Map<String, Object> addUser = new HashMap<>();
    Users user = userRepo.findByUsername(username);
    addUser.put("email", user.getEmail());
    addUser.put("firstName",user.getFirstName());
 "
 "
    return addUser;
}

有沒有比Map更好的方法。 任何建議都會有所幫助。

實際上,jpa查詢中有一種方法可以只返回特定字段,因此您可以在獲取結果時直接使用。

但是,如果您不想打擾findByUsername方法,而不僅僅是創建User類的對象並僅設置所需的字段。

您當前使用的方法也是可行的解決方案。

因此,有兩種方法可以解決此問題。

  1. 在您的Entity類中使密碼字段transient

這樣,當您獲取用戶對象時,密碼字段將為空白。

缺點 :暫時設置密碼將導致以下事實:您將無法通過應用程序中任何位置的實體獲取密碼。

  1. 在密碼字段上使用@JsonIgnore (來自jackson庫)。 這樣,當您返回Users對象的對象時,密碼字段將被忽略。

缺點 :這再次意味着,如果您想將密碼字段用作輸入或通過應用程序返回密碼字段,則將無法這樣做。 另外,不建議您返回POJO類的對象作為響應。

因此,您可以任意選擇一種方法,同時牢記每種方法的缺點。

除了已經提到的答復外,還有其他幾種方法,例如JsonIgnoreProperties,JsonIgnoreType,JsonFilter。 我更喜歡JsonIgnore來抑制輸出中的字段。

這是一個很好的例子的鏈接https://www.baeldung.com/jackson-ignore-properties-on-serialization

另外,您始終可以創建單獨的POJO類以返回期望值。

此處的典型最佳實踐是將密碼視為子資源 :從邏輯上講 ,它不是用戶資源的直接部分,而是與之相關的(例如,它可能在/users/{id}/password具有自己的URL)。 當您具有JPA @OneToOne關系時,Spring Data REST會自動處理此問題,但是您自己做就沒有問題。

此示例說明為什么不直接將@Entity類用作JSON API表示不是一個好主意的原因,因為您可能希望在內部具有差異(包括將來進行更改而不會打擾客戶)。 而是使用數據傳輸對象 (DTO)作為您實體的“ JSON副本”。 諸如MapStruct之類的工具使在UserUserDto之間復制屬性變得非常簡單。

(最后,如果您確實出於某種奇怪的原因而需要返回裸露的Map (確實如此),通常為了簡便起見Map.of("key", value)最好使用Map.of("key", value) 。)

另一個解決方案是在存儲庫中創建帶有@Query注釋的方法,例如:

@Query("SELECT NEW MyEntity(M.firstName, M.lastName, M.email) FROM MyEntity M WHERE M.username = ?1")
public MyEntity getByUsername(String username);

然后在MyEntity類中創建一個與查詢的構造函數匹配的構造函數。

最后,在您的控制器中:

代替:

public Map<String, Object> usersCheck(@PathVariable String 
 username)

做:

public MyEntity usersCheck(@PathVariable String 
 username){
   return userRepo.getByUsername(username);
}

直接返回將導致spring與Jackson序列化自然集成,因此默認情況下,您的響應將是json對象

我認為這種解決方案是您的理想選擇。

如果要從響應中排除密碼,請使用@JsonIgnore注釋密碼字段。

如果你想在排除多個領域的User實體然后創建一個UserDto類,並在添加所需的字段UserDto類。

使用ModelMapper將User實體映射到UserDto類。 最后,將此UserDto類作為響應對象返回。

例:

  User user = new User();

  UserDto userDto = new ModelMapper.map(user, UserDto.class);

這將僅包括UserDto中的字段

最簡單的方法是通過默認JSON庫(傑克遜)提供的注釋來控制序列化到JSON。

https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonIgnore.html

@JsonIgnore
@Column(name = "password")
private String password;

您也可以通過Jackson混合來執行此操作,以避免使用JSON處理指令“污染”實體。

暫無
暫無

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

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