1

我想知道如何验证我的 Rest API 路径 ID 的最佳实践。

例如:

当我执行 GET 检索建筑物时,我需要先验证 {universityId} 和 {campusId} 是否确实有效(存在于数据库中),然后再继续。

现在我已经实现了一个自定义 RepositoryValidation,它通过抛出 ResourceNotFoundException() 来提供这些功能,并且在我的服务类中为 GET、PUT、POST..etc 调用这些方法

有没有更好的方法来进行验证?我已阅读有关拦截器或过滤器的信息,但不确定这是否是最佳做法。

自定义例外:

@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {

public ResourceNotFoundException() {
    super();
}

public ResourceNotFoundException(String message) {
    super(message);
}

存储库验证:

@Component
public class RepositoryValidation {

@Autowired
private UniversityRepository universityRepository;

@Autowired
private CampusRepository campusRepository;

@Autowired
private BuildingRepository buildingRepository;

public void checkIfUniversityExists(Long universityId){
    if (!universityRepository.exists(universityId))
        throw new ResourceNotFoundException("University with id: " + universityId + " not found");
}

public void checkIfCampusExists(Long campusId){
    if (!campusRepository.exists(campusId))
        throw new ResourceNotFoundException("Campus with id: " + campusId + " not found");
}

public void checkIfBuildingExists(Long buildingId){
    if (!buildingRepository.exists(buildingId))
        throw new ResourceNotFoundException("Building with id: " + buildingId + " not found");
}

}

服务:

@Service
public class BuildingService {

@Autowired
private BuildingRepository buildingRepository;

@Autowired
private RepositoryValidation repositoryValidation;

public Iterable<Building> list(Long campusId) {
    return buildingRepository.findAllByCampusId(campusId);
}

@Transactional
public Building create(Building building) {
    return buildingRepository.save(building);
}

public Building read(Long buildingId,Long campusId) {

    repositoryValidation.checkIfCampusExists(campusId);
    repositoryValidation.checkIfBuildingExists(buildingId);

    return buildingRepository.findBuildingByIdAndCampusId(buildingId,campusId);
}

@Transactional
public Building update(Long buildingId,Building update) {

    repositoryValidation.checkIfBuildingExists(buildingId);

    Building building = buildingRepository.findOne(buildingId);
    building.setBuildingName(update.getBuildingName());

    return buildingRepository.save(building);
}

@Transactional
public void delete(Long buildingId,Long campusId) {

    repositoryValidation.checkIfCampusExists(campusId);
    repositoryValidation.checkIfBuildingExists(buildingId);

    buildingRepository.deleteBuildingByIdAndCampusId(buildingId, campusId);
}
4

1 回答 1

0

您应该查看 Springs 的Validation-Beanvalidation

有了这个,您可以使用@Valid对属性进行简单验证,例如:

    @NotNull
    @Size(max=64)
    private String name;

您还可以@Valid在 REST 端点中添加到输入:

@RequestMapping("/foo", method=RequestMethod.POST)
public void processFoo(@Valid Foo foo) { /* ... */ }

根据您的需要,您可以考虑创建一个自定义@Constraint. 您将首先创建约束注释:

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MyConstraintValidator.class)
public @interface MyConstraint {
}

然后是约束验证器:

import javax.validation.ConstraintValidator;

public class MyConstraintValidator implements ConstraintValidator {

    @Autowired;
    private Foo aDependency;

    ...
}

请注意,您也可以将其他 Spring bean 注入其中ConstraintValidator。一旦实施,这可以很容易地重复使用并且看起来非常简洁。

于 2016-03-05T01:26:15.187 回答