简体   繁体   中英

Apply Spring ModelAttribute to all controllers that use a specific parameter type

In a SpringBoot REST application I have a TableRequest type that contains column sorting, filtering, and paging details for GET requests for tabular data. It's generic in that it doesn't care what the specific data being requested is, it only specifies generic table parameters. As such it's applicable across many different controller methods. Also, because it applies to GET requests the fields are passed as request parameters (no @RequestBody json parameter). I've got a @ModelAttribute method inside the controller class that parses the request parameters into a TableRequest object, then the actual @RequestMapping method receives that object as a @ModelAttribute parameter.

Because the TableRequest class is generic, I'd like to be able to use it across multiple controllers without having to copy the parsing logic into every one. I'm wondering if there's a Spring-y annotation-based way of reusing the same @ModelAttribute method any time a controller has a TableRequest input parameter.

Thanks in advance :)


My Solution (based on selected answer below)

I created a @TableRequestController annotation and a corresponding @ControllerAdvice class that applies only to controller classes that have that annotation. That ControllerAdvice class includes the @ModelAttribute method tht parses the GET request parameters into a TableRequest object.

The one important caveat here is that the new @TableRequestController may only be applied to Controller class as a whole, not to individual controller methods. As such, I created a separate inner controller class, tagged with that annotation, whose @RequestMapping methods all accept a TableRequest object.

@TableRequestController:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TableRequestController {}

ControllerAdvice class:

@ControllerAdvice(annotations = TableRequestController.class)
public class TableRequestControllerAdvice {

    @ModelAttribute
    public TableRequest tableRequest(
            @RequestParam Map<String, String> params,
            @RequestParam int pageStart,
            @RequestParam int pageSize) {

        return new TableRequest(params, pageStart, pageSize);
    }
}

TableRequest REST controller class:

@RestController
@TableRequestController
public static class MyTableRequestController {

    @RequestMapping("/the/table/request/url")
    public MyResponse makeTableRequest(
            TableRequest tableRequest) {

        return new MyResponse(tableRequest);
    }
}

You can use @ControllerAdvice . Everything defined here applies to all controllers, or a defined subset, if you prefer that.

Documentation

Another alternative (better imho) is to write a message converter . It only handles one specific type. You no longer need @ModelAttribute but simply have a TableRequest parameter in you controller method.

In a SpringBoot REST application I have a TableRequest type that contains column sorting, filtering, and paging details for GET requests for tabular data. It's generic in that it doesn't care what the specific data being requested is, it only specifies generic table parameters

This means what you have is a utility service.

So define the class as service and access it inside the views.

Access any beans in your application context using SpringEL's syntax: ${@myBean.doSomething()}

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