简体   繁体   中英

Spring Controller: Custom annotation with combined Spring annotations does not work

I have properly working Spring Controller, where I have a method mapped in a following way

@RequestMapping(
    value = "/users"
    consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
    produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
    method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public UserResponse retrieveUsers() {
    return new UserResponse();
}

@RequestMapping(
    value = "/contracts"
    consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
    produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
    method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public ContractResponse retrieveContracts() {
    return new ContractResponse();
}

This works fine, GET requests are served as accepted, and in case of for example POST I am receiving proper 405 status code.

Now I want to introduce custom combined annotation, not to have the same bunch of annotations in each and every method.

My custom annotation looks like,

@RequestMapping(
        consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
        produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
        method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Get {}

Accordingly, I change the method to

@Get
@RequestMapping(value = "/users")
public UserResponse retrieveUsers() {
    return new UserResponse();
}

In this case I can see that whatever type of request I send to /users it is served properly. For example even if I do POST , I see response. So the @RequestMapping does not work properly.

What am I doing wrong here? Is it possible to make controllers behave properly with custom combined annotation?

You overwrite the @RequestMapping annotation you had set up in your @Get annotation. Therefore it specifies only the value part of the request mapping, leaving all other properties to default.

I suspect that the @RequestMapping(value = "/users") on UserResponse#retrieveUsers replaces the @RequestMapping on the @Get interface.

See if this works:

@RequestMapping(
        consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
        produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
        method = RequestMethod.GET)
@ResponseBody
@ResponseStatus(HttpStatus.OK)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Get {

    @AliasFor(annotation = RequestMapping.class, attribute = "value")
    String[] value() default {};
}

@Get(value = "/users")
public UserResponse retrieveUsers() {
    return new UserResponse();
}

You may be interested in GetJson in the spring-composed project.

Note that @AliasFor was only released with Spring 4.2. It's not available in earlier versions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM