简体   繁体   中英

How to filter based on query parameter key and value with Spring

Our application submits jobs to another service on either a monthly or quarterly basis. We have an API that allows us to trigger one of the following scenarios:

  1. Submit a single job using its ID
  2. Submit all jobs that are scheduled to run each month
  3. Submit all jobs that are scheduled to run each quarter

Currently we have 3 different API endpoints for the 3 scenarios, but would like to update the API to use a structure similar to the following:

  1. /submit?type=single&id=123
  2. /submit?type=all&frequency=monthly
  3. /submit?type=all&frequency=quarterly

My question is how can we achieve this kind of mapping inside a Controller class so that each of the 3 API's has its own method, uniquely identified by the key-values provided to it.

Currently we have 3 methods similar to the following, which allows us to share the API path between the 3 methods, but differentiate them based on the params value. Is there a similar approach we could use that allows us to filter based on both the query param key and value?

@PostMapping(value = "/submit", params = "monthly")
@ResponseStatus(HttpStatus.ACCEPTED)
public void submitAllMonthlyJobs() {
// Code
}

One approach is to use a single method that handles all 3 scenarios, and inside that method we fork to one of the 3 options based on the query params. But I'm hopeful there's a cleaner approach where Spring handles this for us.

Thanks for your help.

Each request mapping like @RequestMapping , @GetMapping , @PostMapping etc. can be filtered not only by path , but also by params . Your endpoint with the three mappings could look like this:

@RestController
public class JobEndpoint {

    @PostMapping(path = "submit", params = "type=single")
    public void submitSingleJob(@RequestParam("id") long id) {
        System.out.println("submitting single job " + id);
    }

    @PostMapping(path = "submit", params = {"type=all", "frequency=monthly"})
    public void submitMonthlyJobs() {
        System.out.println("submitting monthly jobs");
    }

    @PostMapping(path = "submit", params = {"type=all", "frequency=quarterly"})
    public void submitQuarterlyJobs() {
        System.out.println("submitting quarterly jobs");
    }
}

And just to be sure that it works:

@WebMvcTest
@ExtendWith(OutputCaptureExtension.class)
class JobEndpointTest {

    @Autowired
    private MockMvc mvc;

    @Test
    void submitSingleJob(CapturedOutput output) throws Exception {
        mvc.perform(post("/submit?type=single&id=123")).andExpect(status().isOk());
        assertThat(output).contains("submitting single job 123");
    }

    @Test
    void submitMonthlyJobs(CapturedOutput output) throws Exception {
        mvc.perform(post("/submit?type=all&frequency=monthly")).andExpect(status().isOk());
        assertThat(output).contains("submitting monthly jobs");
    }

    @Test
    void submitQuarterlyJobs(CapturedOutput output) throws Exception {
        mvc.perform(post("/submit?type=all&frequency=quarterly")).andExpect(status().isOk());
        assertThat(output).contains("submitting quarterly jobs");
    }
}

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