如何制作REST控制器的模式

时间:2016-10-13 18:50:55

标签: java spring spring-mvc

我正在编写我的第一个春季应用程序,并希望获得在spring上制作最佳且极具吸引力的代码的经验。 我有一些休息控制器,它们具有类似代码的重要部分

   @RequestMapping(path = "/1154",
                method = RequestMethod.POST,
                headers = {"Content-Type=application/json"},
                consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
                produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

        public CreateUserResp processRequest(@RequestBody @Valid CreateUserReq request, BindingResult bindingResult) {

            CreateUserResp response = new CreateUserResp();

            if (bindingResult.hasErrors()){

                response.setResultCode(102); // Validation error
                response.setErrMsg("Wrong " + bindingResult.getFieldError().getDefaultMessage() + " value.");

            } else {
                   // main service
                   request = UserService.doSomething();

            }
            return response;
        }

 @RequestMapping(path = "/1155",
                method = RequestMethod.POST,
                headers = {"Content-Type=application/json"},
                consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
                produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

        public ChangeUserResp processRequest(@RequestBody @Valid ChangeUserReq request, BindingResult bindingResult) {

            ChangeUserResp response = new ChangeUserResp();

            if (bindingResult.hasErrors()){

                response.setResultCode(102); // Validation error
                response.setErrMsg("Wrong " + bindingResult.getFieldError().getDefaultMessage() + " value.");

            } else {
                   // main service
                   request = ChangeService.doSomething();

            }
            return response;
        }

 @RequestMapping(path = "/1156",
                method = RequestMethod.POST,
                headers = {"Content-Type=application/json"},
                consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
                produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

        public AddUserResp processRequest(@RequestBody @Valid AddUserReq request, BindingResult bindingResult) {

            AddUserResp response = new AddUserResp();

            if (bindingResult.hasErrors()){

                response.setResultCode(102); // Validation error
                response.setErrMsg("Wrong " + bindingResult.getFieldError().getDefaultMessage() + " value.");

            } else {
                   // main service
                   request = AddService.doSomething();

            }
            return response;
        }

 @RequestMapping(path = "/1157",
                method = RequestMethod.POST,
                headers = {"Content-Type=application/json"},
                consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
                produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

        public ModifyUserResp processRequest(@RequestBody @Valid ModifyUserReq request, BindingResult bindingResult) {

            ModifyUserResp response = new ModifyUserResp();

            if (bindingResult.hasErrors()){

                response.setResultCode(102); // Validation error
                response.setErrMsg("Wrong " + bindingResult.getFieldError().getDefaultMessage() + " value.");

            } else {
                   // main service
                   request = ModifyService.doSomething();

            }
            return response;
        }

等......

(path,@ RequestBody和Responce对象以及被叫服务)的唯一区别。所以,我将拥有像这样的10-12个控制器。这是使这个代码更优化的方法,而不是将这个可重复的代码块写入10次(spring方法或者可能使用泛型类或方法)。这只是一个例子,而不是真正的代码。 THX

特别感谢那些忙着回答但有时间减负的人。

2 个答案:

答案 0 :(得分:0)

我的申请中有类似的东西。

例如,这是我的用户控制器的editProfile方法的样子:

@PostMapping(value = EDIT_CONTACT_INFO)
public ResponseEntity<?> editContactInfo(
        @Autowired HttpServletRequest httpServletRequest,
        @RequestBody @Valid ContactInfoDTO.Req requestBody,
        BindingResult bindingResult
)
{
    if (bindingResult.hasErrors())
        // 400 - BAD REQUEST
        return ErrorsDTO.from(bindingResult).responseEntity();

    String userName = ControllerUtils.getUserName(httpServletRequest);
    User user =  userService.findByUserName(userName);
    ContactInfo contactInfo = modelMapper.map(requestBody, ContactInfo.class);

    if (!userService.editContactInfo(user, contactInfo))
        // 500 - INTERNAL SERVER ERROR
        return ErrorsDTO.from(INTERNAL_SERVER_ERROR).responseEntity();

    // 200 - OK
    return ResponseEntity.ok(null);
}

我的大多数API看起来与你的非常相似。我刚刚编写了自定义机制来报告错误,我使用ResponseEntity实例来返回数据。

此外,我还有一个库可以将数据从DTO传递到我的模型并返回(它被称为ModelMapper)。

答案 1 :(得分:0)

编辑:看起来这篇博文包含了您的问题: http://blog.codeleak.pl/2013/09/request-body-validation-in-spring-mvc-3.2.html

如果你真的想要变得肮脏,你可以 编写一个拦截器,在新注释ValidateBinding上使用切入点,并使用BindingResult的参数。它可能看起来像:

@Around("@annotation(ValidateBinding) && execution(* *(..)) && args(bindingResult)
public Object handleInvalidBindings(ProceedingJoinPoint p, BindingResult bindingResult) {

    if (bindingResult.hasErrors()){
        GenericResponse response = createTypedResponse(p);
        response.setResultCode(102); // Validation error
        response.setErrMsg("Wrong " + bindingResult.getFieldError().getDefaultMessage() + " value.");
        return response;
    } 
    return pjp.proceed();
}

private GenericResponse createTypedResponse(ProceedingJoinPoint p) {
    MethodSignature signature = (MethodSignature) p.getSignature();
    Method method = signature.getMethod();
    Class responseClass = method.getReturnType();
    if(!GenericResponse.class.isAssignableFrom(responseClass)) {
        throw new IllegalArgumentException("Could not create proper response class - it should implement the GenericResponse interface");
    return (GenericResponse) responseClass.newInstance();
}

但我不能保证表达式或代码有效。这是对其外观的粗略猜测。

为此,您需要一个由您的响应类实现的接口GenericResponse,并且具有setResultCode和setErrMsg。