web-dev-qa-db-ja.com

Springデータへのリンクを簡単に追加するにはどうすればよいですかRESTエンティティ

Spring Data JPAを使用するエンティティがありますが、それらに関する統計を生成するために、SpringでjOOQを使用します@Repository

私のメソッドはエンティティのListまたはDoubleのいずれかを返すので、どうすればそれらをリンクとして公開できますか? Userエンティティがあるとしましょう。次のJSONを取得したいとします:

{
  "_embedded" : {
    "users" : [ ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/api/users"
    },
    "stats" : {
      "href" : "http://localhost:8080/api/users/stats"
    }
    "profile" : {
      "href" : "http://localhost:8080/api/profile/users"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 0,
    "totalPages" : 0,
    "number" : 0
  }
} 

そして http:// localhost:8080/api/users/stats jOOQリポジトリで宣言したメソッドとのリンクのリストを取得したいと思います。これにどのようにアプローチしますか?ありがとう。

9
Desiderantes

docs からこれを参照してください

@Bean
public ResourceProcessor<Resource<Person>> personProcessor() {

   return new ResourceProcessor<Resource<Person>>() {

     @Override
     public Resource<Person> process(Resource<Person> resource) {

      resource.add(new Link("http://localhost:8080/people", "added-link"));
      return resource;
     }
   };
}
7
Evgeni Dimitrov

リンクを追加する最良の方法は、コードをさらにきれいに見せるためのSpring-HATEOASを検討することです。

一言アドバイス:応答を簡単にカスタマイズできるため、クライアントに応答を返すには常にorg.springframework.http.ResponseEntityを使用してください。

したがって、応答でリンクを送信することが要件であるため、このベストプラクティスでは、ResourceSupport(org.springframework.hateoas.ResourceSupport)およびResourceAssemblerSupport(org。 springframework.hateoas.mvc.ResourceAssemblerSupport)クライアントに送信する必要のあるリソースを作成します。

:Accountのようなモデルオブジェクトがある場合、クライアントに知らせたくない、または応答に含めたくないフィールドがいくつかある必要があります。これにより、これらの属性を応答から除外できます。使用ResourceAssemblerSupport class '

public TResource toResource(T t);

応答として送信する必要があるモデルオブジェクトからリソースを生成するメソッド。

たとえば、次のようなアカウントクラスがあります(すべてのサーバー側の対話と操作に直接使用できます)

@Document(collection = "Accounts_Details")

public class Account {

    @Id
    private String id;

    private String username;
    private String password;
    private String firstName;
    private String lastName;
    private String emailAddress;
    private String role;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private boolean enabled;
    private long accountNonLockedCounter;
    private Date lastPasswordResetDate;
    private Address address;
    private long activationCode;

    public Account() {
    }

    //getters and setters
}

このPOJOから、選択した属性でクライアントに送信されるResourceオブジェクトを作成します。

このために、クライアントに表示可能な必要なフィールドのみを含むアカウントリソースを作成します。そのために、別のクラスを作成します。

@XmlRootElement

public class AccountResource extends ResourceSupport {

    @XmlAttribute
    private String username;
    @XmlAttribute
    private String firstName;
    @XmlAttribute
    private String lastName;
    @XmlAttribute
    private String emailAddress;
    @XmlAttribute
    private Address address;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getEmailAddress() {
        return emailAddress;
    }
    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }


}

したがって、このリソースは、クライアントが表示するか、操作する必要があるものです。

AccountResourceのブループリントを作成した後、モデルPOJOをこのリソースに変換する方法が必要です。そのための推奨されるベストプラクティスは、ResourceAssemblerSupportクラスを作成し、toResource(T t)メソッドをオーバーライドすることです。

import org.springframework.hateoas.mvc.ControllerLinkBuilder;
import org.springframework.hateoas.mvc.ResourceAssemblerSupport;
import org.springframework.stereotype.Component;

import com.brx.gld.www.api.controller.RegistrationController;
import com.brx.gld.www.api.model.Account;

@Component
public class AccountResourceAssembler extends ResourceAssemblerSupport<Account, AccountResource> {

    public AccountResourceAssembler(Class<RegistrationController> controllerClass,
            Class<AccountResource> resourceType) {
        super(controllerClass, resourceType);
    }

    public AccountResourceAssembler() {
        this(RegistrationController.class, AccountResource.class);
    }

    @Override
    public AccountResource toResource(Account account) {
        AccountResource accountResource =  instantiateResource(account); //or createResourceWithId(id, entity) canbe used which will automatically create a link to itself.
        accountResource.setAddress(account.getAddress());
        accountResource.setFirstName(account.getFirstName());
        accountResource.setLastName(account.getLastName());
        accountResource.setEmailAddress(account.getEmailAddress());
        accountResource.setUsername(account.getUsername());
        accountResource.removeLinks();
        accountResource.add(ControllerLinkBuilder.linkTo(RegistrationController.class).slash(account.getId()).withSelfRel());
        return accountResource;
    }

}

InstanriateReource(..)を使用する代わりにtoReourceメソッドでは、createdResourceWithId(id、entity)を使用してから、カスタムリンクをリソースに追加する必要があります。これも実際に検討するのがベストプラクティスですが、デモンストレーションのために使用しました。 instanceiateResource(..)

これをコントローラーで使用するには:

@Controller
@RequestMapping("/api/public/accounts")
public class RegistrationController {

    @Autowired
    private AccountService accountService;

    @Autowired
    private AccountResourceAssembler accountResourceAssembler;

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<List<AccountResource>> getAllRegisteredUsers() {
        List<AccountResource> accountResList = new ArrayList<AccountResource>();
        for (Account acnt : accountService.findAllAccounts())
            accountResList.add(this.accountResourceAssembler.toResource(acnt));
        return new ResponseEntity<List<AccountResource>>(accountResList, HttpStatus.OK);
    }

/*Use the below method only if you have enabled spring data web Support or otherwise instead of using Account in @PathVariable usr String id or int id depending on what type to id you have in you db*/

    @RequestMapping(value = "{userID}", method = RequestMethod.GET)
    public ResponseEntity<AccountResource>  getAccountForID(@PathVariable("userID") Account fetchedAccountForId) {
        return new ResponseEntity<AccountResource>(
                this.accountResourceAssembler.toResource(fetchedAccountForId), HttpStatus.OK);
    }

前の方法で使用したように渡されたIDに基づいてDBからモデルデータを自動的にフェッチするなど、コードにいくつかの機能を追加するSpring DataWebサポートを有効にします。

ToResource(Account account)メソッドに戻ります。これでは、最初にリソースオブジェクトが初期化され、次に目的の小道具が設定され、静的org.springframework.hateoas.mvcを使用してLinkがAccountResorceに追加されます。 .ControllerLinkBuilder.linkTo(..)メソッド、次にコントローラークラスが渡され、そこからベースURLが選択され、その後、スラッシュ(..)などを使用してURLが作成されます。完全なパスを指定した後、relメソッドを使用してリレーションを指定します(ここでは、withSelfRel()を使用してリレーションを自分自身に指定します。他のリレーションの場合は、withRel(String Relation)を使用してよりわかりやすくすることができます。 toResourceメソッドのコードはaccountResource.add(ControllerLinkBuilder.linkTo(RegistrationController.class).slash(account.getId())。withSelfRel());のようなものを使用しました

これにより、URLが/ api/public/accounts/{userID}として作成されます。

このURLでgetを使用すると、郵便配達員になります http:// localhost:8080/api/public/accounts

{
    "username": "Arif4",
    "firstName": "xyz",
    "lastName": "Arif",
    "emailAddress": "[email protected]",
    "address": {
      "addressLine1": "xyz",
      "addressLine2": "xyz",
      "addressLine3": "xyz",
      "city": "xyz",
      "state": "xyz",
      "zipcode": "xyz",
      "country": "India"
    },
    "links": [
      {
        "rel": "self",
        "href": "http://localhost:8080/api/public/accounts/5628b95306bf022f33f0c4f7"
      }
    ]
  },
  {
    "username": "Arif5",
    "firstName": "xyz",
    "lastName": "Arif",
    "emailAddress": "[email protected]",
    "address": {
      "addressLine1": "xyz",
      "addressLine2": "xyz",
      "addressLine3": "xyz",
      "city": "xyz",
      "state": "xyz",
      "zipcode": "xyz",
      "country": "India"
    },
    "links": [
      {
        "rel": "self",
        "href": "http://localhost:8080/api/public/accounts/5628c04406bf23ea911facc0"
      }
    ]
  }

リンクのいずれかをクリックして、取得リクエストを送信すると、応答は http:// localhost:8080/api/public/accounts/5628c04406bf23ea911facc になります。

{
    "username": "Arif5",
    "firstName": "xyz",
    "lastName": "Arif",
    "emailAddress": "[email protected]",
    "address": {
      "addressLine1": "xyz",
      "addressLine2": "xyz",
      "addressLine3": "xyz",
      "city": "xyz",
      "state": "xyz",
      "zipcode": "xyz",
      "country": "India"
    },
    "links": [
      {
        "rel": "self",
        "href": "http://localhost:8080/api/public/accounts/5628c04406bf23ea911facc0"
      }
    ]
  }
4
Najeeb Arif

リンクを手動で作成するには、 spring-hateoas-examples を参照してください。最も単純なワイは via new Resource DTOがない場合およびextends ResourceSupportDTOの場合。

私がカスタマイズしたspring-data-rest管理対象エンティティへのリンク ルートリソースへのリンク

MyController implements ResourceProcessor<Resource<ManagedEntity>> {

   @Override
   public Resource<Restaurant> process(Resource<ManagedEntity> resource) {
       resource.add(linkTo(methodOn(MyController.class)
           .myMethod(resource.getContent().getId(), ...)).withRel("..."));
       return resource;
}

そして、ページリソースの場合

MyController implements ResourceProcessor<PagedResources<Resource<ManagedEntity>>>

問題は、ジェネリック型消去のためにyorがこの両方のインターフェースを拡張できないため、両方が必要な場合です。ハックとして、ダミーのResourceControllerを作成しました

0
Grigory Kislin