示例项目

对最终项目的两个技术建议

这些笔记将涵盖我对你们期末项目的一些建议。第一个建议的目的是防止一个技术问题的帖子,而第二个建议是一个建议,使您的开发过程更快,更容易。

处理岗位

106人用来处理POST请求的JavaScript代码有一个特性需要注意。如果您的服务器用200或201状态码响应POST请求,但没有在响应中发回正文,那么它们的软件将把请求视为失败,尽管您返回了表示成功的状态码。

解决这个问题的方法是确保在您所服务的每个POST请求的主体中始终返回一些内容。

从post返回内容的一种方法是在响应体中返回字符串。即使这种方法也有一些问题,因为JavaScript实际上对其JSON格式规则非常严格。JSON中一个模糊的规则是赢博体育字符串都必须加引号。这意味着如果您的POST方法这样做,例如

返回“OK”;

这还不够好。这将导致响应体看起来像

好吧

这不是有效的JSON,因为它缺少引号。正确的做法是

返回“\”好\ ";

这就形成了这样的尸体

“OK”

在现实世界中,大多数程序员都遵循广泛使用的POST请求惯例,这使得正确处理事情变得很容易。惯例是总是在响应体中回显客户端在post中发送的对象。

这里有一个例子。我已经修改了拍卖的例子,总是采取这种方法的帖子。一个简单的例子是发布新拍卖的控制器方法:

@PostMapping public ResponseEntity<AuctionDTO> save(Authentication Authentication,@RequestBody AuctionDTO auction) {AuctionUserDetails details = (AuctionUserDetails) Authentication . getprincipal ();auction.setSeller (details.getUsername ());字符串id;try {id = auctionService.save(拍卖);auction.setAuctionid (id);} catch(WrongUserException ex) {return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(auction);}返回ResponseEntity.status(HttpStatus.CREATED).body(auction);}

这段代码从客户机接收一个AuctionDTO,将拍卖存储在数据库中,然后作为保存的副作用获取拍卖的UUID。然后代码将UUID放回AuctionDTO,然后将该对象发送回响应的主体中。

另一个例子与发帖用户有关。我之前发布用户的代码在响应体中发回了一个JWT。在新版本中,我首先向UserDTO类添加了一个新的成员变量,我可以用它来存储令牌:

公共类UserDTO{私有字符串名称;private String密码;private String令牌;public UserDTO() {token = "";} //未显示getter和setter}

有了这个改变,我现在可以修改方法来发布一个新用户到这个表单:

@PostMapping public ResponseEntity<UserDTO> save(@RequestBody UserDTO user) {if (user. getname ().isBlank() || user. getpassword ().isBlank()) {return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(user);}字符串键;Try {key = us.save(user);} catch(DuplicateException ex){返回ResponseEntity.status(HttpStatus.CONFLICT).body(user);} String token = jwtService.makeJwt(key);user.setToken(令牌);返回ResponseEntity.status (HttpStatus.CREATED) .body(用户);}

此代码将用户存储在数据库中。执行此操作的服务方法在其响应中返回新用户的UUID。然后基于该UUID构建JWT,将JWT放回UserDTO对象中,然后在响应体中返回该对象。

新项目首选Spring Data

我给您的第二个技术建议是,在新项目中选择Spring Data和Hibernate而不是JDBC。当我第一次在课堂上介绍Spring Data和Hibernate时,这些主题看起来非常可怕和技术化。我们在Auction赢博体育程序中看到的复杂性很大一部分来自于这样一个事实:我想演示在现有数据库之上构建Hibernate赢博体育程序的样子。

这样做的一个好处是,您将不需要使用现有的数据库。在没有现有数据库的情况下,可以以最简单的形式使用Hibernate。您所要做的就是设置实体类,然后告诉Hibernate自动为您生成数据库。

为了演示这是多么简单,我构造了另一个版本的拍卖赢博体育程序。您可以通过单击这些注释顶部的按钮来访问本示例的完整项目。在这个版本的拍卖赢博体育程序,我扔掉了现有的数据库,只是写了简单的实体类的一切。由于这些实体类不必遵循现有的数据库,因此它们可以非常简单。例如,以下是拍卖实体类的新版本:

@实体公共类Auction {@Id @GeneratedValue(strategy = GenerationType.UUID) private UUID auctionid;@ManyToOne私人用户卖家;私有字符串项;私有字符串描述;私有字符串imageurl;私人储备;private LocalDate打开;private LocalDate关闭;私有布尔值完成;@OneToMany(mappedBy="auction") List<Tag> tags;@OneToMany(mappedBy="auction") List<Bid>出价;public Auction(){} //遗漏的getter和setter}

我们仍然需要完成在实体类之间建立关系的练习,但是这里的其他一切都很容易设置。

如果希望以自动生成数据库表的模式操作Hibernate,那么还需要执行一个小的附加步骤。在您的赢博体育程序中。属性文件中需要添加的行

Spring.jpa.hibernate.ddl-auto = create

显式地告诉Hibernate自动为您创建数据库表。在运行项目之前,您需要使用MySQL为您正在使用的任何数据库创建新的空模式。第一次运行赢博体育程序或单元测试时,Hibernate将为您生成这些数据库中的赢博体育表。

您可能需要处理的最后一件小事与在数据库中存储uid有关。默认情况下,Hibernate选择最有效的数据类型来存储uuid, BINARY(16) MySQL数据类型。这是一个二进制形式,这意味着当您查看数据库中的这些字段时,您将看到一个BLOB框,它表明数据是二进制的,并且没有显示在工作台中。如果您需要将这些blob转换为文本用于工作台中的任何目的,您可以在工作台中运行此查询:

SELECT BIN_TO_UUID(userid) FROM user;

BIN_TO_UUID()函数可以为您将这些uuid从二进制转换为文本形式。