我跟着Spring走。io是一个关键的教程,可以让REST API与MySQL DB一起启动,一切都进展顺利。然而,我发现了一个我无法配置或解决的行为。
当我使用内置功能从PagingAndSortingRepository中检索资源时,生成的剩余资源会自动分页,并用有用的HAL链接(链接、self、搜索、链接资源等)进行封装。我想用这个。
当我实现我的控制器来定制PostMapping行为并引入健全性检查、验证等时,GetMapping停止工作。所以我重新实现了一个GetMapping,它利用了我的服务层。
不幸的是,这样做打破了以前提供的HATEOAS。
我想要的是能够自定义PostMapping,但保留GetMapping与默认完全相同。如果可能的话,我希望避免自己编写,因为我知道框架可以提供它。
有办法吗?
控制器:
@RestController
public class PartyMemberController {
@Autowired
PartyMemberService partyMemberService;
@RequestMapping(method = RequestMethod.GET, value = "/partyMembers")
public ResponseEntity<Iterable<PartyMember>> getAllPartyMembers() {
Iterable<PartyMember> partyMemberList = partyMemberService.getAll();
return new ResponseEntity<>(partyMemberList, HttpStatus.OK);
}
@RequestMapping(method = RequestMethod.POST, value = "/partyMembers")
public ResponseEntity<PartyMember> addEmployee(@Valid @RequestBody PartyMember partyMember) {
if (partyMemberService.exists(partyMember)) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
partyMember = partyMemberService.save(partyMember);
return new ResponseEntity<PartyMember>(partyMember, HttpStatus.CREATED);
}
}
结果JSON
[
{
"id": 2,
"ward": {
"id": 1,
"name": "Mercier",
"wardNumber": 42,
"numberOfMembers": 3
},
"firstName": "Cindy",
"lastName": "Tremblay",
"partyMemberId": "12-1234-09876",
"primaryPhone": "514-555-2323",
"postalAddress": "1155 Robert-Bourassa, Montreal, Quebec, Canada, H3B3A7",
"emailAddress": null,
"secondaryPhone": null,
"bestTimeToContact": null,
"bestWayToContact": null,
"membershipExpiry": null,
"dateOfBirth": null,
"donationEntries": [],
"note": null
},
{
"id": 3,
"ward": {
"id": 1,
"name": "Mercier",
"wardNumber": 42,
"numberOfMembers": 3
},
"firstName": "Robert",
"lastName": "Paulson",
"partyMemberId": "12-1234-54321",
"primaryPhone": "514-555-1212",
"postalAddress": "440 Rue Saint-Pierre, App 5, Montreal, Quebec, Canada, H2Y2M5",
"emailAddress": "rpaulson@papermillsoapcompany.com",
"secondaryPhone": null,
"bestTimeToContact": null,
"bestWayToContact": null,
"membershipExpiry": null,
"dateOfBirth": null,
"donationEntries": [],
"note": null
},
{
"id": 4,
"ward": {
"id": 1,
"name": "Mercier",
"wardNumber": 42,
"numberOfMembers": 3
},
"firstName": "Richard",
"lastName": "Schnobb",
"partyMemberId": "12-4321-09876",
"primaryPhone": "514-555-2323",
"postalAddress": "440 Rue Saint-Pierre, App 5, Montreal, Quebec, Canada, H2Y2M5",
"emailAddress": null,
"secondaryPhone": null,
"bestTimeToContact": null,
"bestWayToContact": null,
"membershipExpiry": null,
"dateOfBirth": null,
"donationEntries": [],
"note": null
}
]
默认JSON(注意_嵌入、_链接等)。这就是我想要的结果。
{
"_embedded" : {
"partyMembers" : [ {
"firstName" : "Cindy",
"lastName" : "Tremblay",
"partyMemberId" : "12-1234-09876",
"primaryPhone" : "514-555-2323",
"postalAddress" : "1155 Robert-Bourassa, Montreal, Quebec, Canada, H3B3A7",
"emailAddress" : null,
"secondaryPhone" : null,
"bestTimeToContact" : null,
"bestWayToContact" : null,
"membershipExpiry" : null,
"dateOfBirth" : null,
"donationEntries" : [ ],
"note" : null,
"_links" : {
"self" : {
"href" : "http://127.0.0.1:8080/partyMembers/2"
},
"partyMember" : {
"href" : "http://127.0.0.1:8080/partyMembers/2"
},
"ward" : {
"href" : "http://127.0.0.1:8080/partyMembers/2/ward"
}
}
}, {
"firstName" : "Robert",
"lastName" : "Paulson",
"partyMemberId" : "12-1234-54321",
"primaryPhone" : "514-555-1212",
"postalAddress" : "440 Rue Saint-Pierre, App 5, Montreal, Quebec, Canada, H2Y2M5",
"emailAddress" : "rpaulson@papermillsoapcompany.com",
"secondaryPhone" : null,
"bestTimeToContact" : null,
"bestWayToContact" : null,
"membershipExpiry" : null,
"dateOfBirth" : null,
"donationEntries" : [ ],
"note" : null,
"_links" : {
"self" : {
"href" : "http://127.0.0.1:8080/partyMembers/3"
},
"partyMember" : {
"href" : "http://127.0.0.1:8080/partyMembers/3"
},
"ward" : {
"href" : "http://127.0.0.1:8080/partyMembers/3/ward"
}
}
}, {
"firstName" : "Richard",
"lastName" : "Schnobb",
"partyMemberId" : "12-4321-09876",
"primaryPhone" : "514-555-2323",
"postalAddress" : "440 Rue Saint-Pierre, App 5, Montreal, Quebec, Canada, H2Y2M5",
"emailAddress" : null,
"secondaryPhone" : null,
"bestTimeToContact" : null,
"bestWayToContact" : null,
"membershipExpiry" : null,
"dateOfBirth" : null,
"donationEntries" : [ ],
"note" : null,
"_links" : {
"self" : {
"href" : "http://127.0.0.1:8080/partyMembers/4"
},
"partyMember" : {
"href" : "http://127.0.0.1:8080/partyMembers/4"
},
"ward" : {
"href" : "http://127.0.0.1:8080/partyMembers/4/ward"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://127.0.0.1:8080/partyMembers{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://127.0.0.1:8080/profile/partyMembers"
},
"search" : {
"href" : "http://127.0.0.1:8080/partyMembers/search"
}
},
"page" : {
"size" : 20,
"totalElements" : 3,
"totalPages" : 1,
"number" : 0
}
}
控制器上的返回类型不是Spring HATEOASResourceSupport
类型,因此它的HAL序列化程序永远不会被调用。
您应该返回资源
进行这些更改,然后是可重用的
ResourceAssembler的概念
要了解基于REST的服务的演变,请查看本教程(几个月前我重写了本教程,以正确显示Spring HATEAOS的用法)=
你对响应的控制很差,所以它不再自动为你构建。这意味着您必须使用LinkBuilder或ControllerLinkBuilder来构建与这些响应相关联的链接。
这里的文档和示例:https://docs.spring.io/spring-hateoas/docs/current/reference/html/#fundamentals.obtaining-链接。实体链接
一个简单的例子:
@Getter
public class PersonResource extends ResourceSupport {
private final Person person;
public PersonResource(final Person person) {
this.person = person;
final long id = person.getId();
add(linkTo(PersonController.class).withRel("people"));
add(linkTo(methodOn(GymMembershipController.class).all(id)).withRel("memberships"));
add(linkTo(methodOn(PersonController.class).get(id)).withSelfRel());
}
}
从这个最优秀的图坦卡蒙:https://dzone.com/articles/applying-hateoas-to-a-rest-api-with-spring-boot
为了让Spring为您完成大部分工作,您应该使用注释@RepositoryRestController
。文档中的更多解释:
有时,您可能需要为特定资源编写自定义处理程序。要利用Spring数据REST的设置、消息转换器、异常处理等,请使用@RepositoryRestController注释,而不是标准的Spring MVC@Controller或@RestController。使用@RepositoryRestController注释的控制器从RepositoryRestConfiguration中定义的API基本路径提供服务。setBasePath,所有其他RESTfulendpoint(例如,/api)都使用它。
为了简化HATEOAS资源的生成(使用您提到的\u链接
),您可以利用ResourceAssemblerSupport
。
由于从实体到资源类型的映射必须在多个地方使用,因此创建一个专门负责这样做的类是有意义的。转换当然包含非常定制的步骤,但也有一些样板步骤。(...) Spring Hateoas现在提供了ResourceAssemblerSupport基类,帮助减少需要编写的代码量
我无法在创建模式下以Hibernate空间启动我的Spring启动(2.6.3)项目。它告诉我类型“几何不存在”。几何类型来自Hibernate空间库。 但是,我应用了所有必要的东西: > 添加Hibernate空间依赖项(我的版本5.6.3.Final) 使用组织.hibernate.空间.方言.postgis.Postgis方言 此外,该类已被弃用,文档对应于相同的版本,它仍然指示使用它,我不
我正在用Thymeleaf构建一个Spring Boot应用程序。我的模板(视图)和静态文件夹都在src/main/Resources/静态和src/main/Resources/tem板下。当我通过main方法(使用eclipse)运行应用程序时,一切都很好。但是,我已经按照说明创建了一个war文件,当我将其部署到Tomcat 7时——静态内容丢失了,只显示了Thymeleaf html模板。
作为一个新的Web应用程序项目的一部分,我计划学习Spring。我开始通读Spring框架参考。当我在谷歌上搜索时,我遇到了Spring boot。我所理解的是,Spring boot通过减少配置帮助构建应用程序的速度比Spring快得多。现在我有点困惑,我应该继续学习Spring还是跳转到Spring boot。我的目的是了解Spring作为一个框架是如何工作的,而不是一些特性。所以请让我知道,
我正在使用Spring boot 2.0.2应用程序通过HTTPS对外部api进行REST api调用。 我是TLS和SSL的新手。我的理解是,TLS是一种更安全的方式,用于传输安全的敏感数据。 我的问题是: 如何确定我的应用程序使用的TLS版本
我有两个项目。我用Angular2 cli构建的Angular2应用程序和只为Angular2应用程序服务的Spring Boot应用程序。我用构建Angular2应用程序,它会生成一个文件夹。然后,我将文件夹的内容放在Spring Boot应用程序的中。 我的Spring启动应用程序有两个文件。 Spring Boot应用程序类: 及其应用。属性文件: 它工作得很好,但是如果我转到一个url并点
我正在练习使用spring boot来处理restful应用程序 我已经设置了@RestController和@Entity这样 和 当我用邮递员http://localhost:8080/cardatabase/api/cars我有一张汽车清单 但即使我去http://localhost:8081/cardatabase/cars,顶部嵌入 正常吗? 谢谢