Объедините методы запросов GET и POST в Spring

У меня есть ресурс, который поддерживает запросы GET и POST. Вот пример кода для примера ресурса:

@RequestMapping(value = "/books", method = RequestMethod.GET)
public ModelAndView listBooks(@ModelAttribute("booksFilter") BooksFilter filter, two @RequestParam parameters, HttpServletRequest request)
    throws ParseException {
        LONG CODE
}


@RequestMapping(value = "/books", method = RequestMethod.POST)
public ModelAndView listBooksPOST(@ModelAttribute("booksFilter") BooksFilter filter, BindingResult result)
        throws ParseException {
        SAME LONG CODE with a minor difference
}

Код в этих двух методах практически одинаков, за исключением, скажем, определения переменной. Два метода можно легко комбинировать, используя method = {RequestMethod.POST, RequestMethod.GET} и простой if внутри. Я пытался, но это не работает, потому что два метода имеют разные параметры в конце, то есть HttpServletRequest и BindingResult (@RequestParam не требуются и, следовательно, не нужны в запросе POST). Любые идеи, как объединить два метода?


person Community    schedule 01.08.2013    source источник
comment
Почему бы вам не перенести свой ДЛИННЫЙ КОД в отдельный метод?   -  person Narendra Pathai    schedule 01.08.2013
comment
А если он такой длинный, то стоит даже разбить его на несколько коротких методов   -  person JB Nizet    schedule 01.08.2013
comment
Потому что я ищу более элегантное и общее решение. Я не думаю, что хорошо иметь метод booksLogic, который является единственным, что я вызываю в двух методах.   -  person    schedule 01.08.2013
comment
@MilanMilanov: это было бы самым элегантным решением. Вам следует стремиться к коротким методам, которые хорошо выполняют одну задачу и делегируют полномочия другим коротким методам.   -  person JB Nizet    schedule 01.08.2013
comment
Обычно вы используете GET для вещей, которые не изменяют сервер, и POST для вещей, которые изменяют сервер. Это эквивалентные http-операции READ и WRITE в базе данных. Поэтому идеально разделить их и разделить общую логику на другой метод.   -  person Dhanush Gopinath    schedule 01.08.2013
comment
ДЛИННЫЙ КОД на самом деле не такой длинный, это просто логика для моего контроллера. Я хотел, чтобы вы поняли, что я не хочу копировать и вставлять один и тот же код.   -  person    schedule 01.08.2013


Ответы (3)


@RequestMapping(value = "/testonly", method = { RequestMethod.GET, RequestMethod.POST })
public ModelAndView listBooksPOST(@ModelAttribute("booksFilter") BooksFilter filter,
        @RequestParam(required = false) String parameter1,
        @RequestParam(required = false) String parameter2, 
        BindingResult result, HttpServletRequest request) 
        throws ParseException {

    LONG CODE and SAME LONG CODE with a minor difference
}

если @RequestParam(required = true) то вы должны передать параметр1, параметр2

Используйте BindingResult и запрашивайте их на основе ваших условий.

Другой способ

@RequestMapping(value = "/books", method = RequestMethod.GET)
public ModelAndView listBooks(@ModelAttribute("booksFilter") BooksFilter filter,  
    two @RequestParam parameters, HttpServletRequest request) throws ParseException {

    myMethod();

}


@RequestMapping(value = "/books", method = RequestMethod.POST)
public ModelAndView listBooksPOST(@ModelAttribute("booksFilter") BooksFilter filter, 
        BindingResult result) throws ParseException {

    myMethod();

    do here your minor difference
}

private returntype myMethod(){
    LONG CODE
}
person Prabhakaran Ramaswamy    schedule 01.08.2013
comment
Есть ли способ узнать, какой тип request, то есть GET или POST, пришел? - person Govinda Sakhare; 04.09.2016
comment
Вы можете проверить заголовок запроса. - person Karan; 24.01.2019
comment
SonarQube выдает предупреждение. Рассмотрите возможность сужения этого списка методов до одного. - person Ashishkel; 26.08.2020

Ниже приведен один из способов, которым вы можете достичь этого, возможно, не идеальный способ.

Имейте один метод, принимающий оба типа запроса, затем проверьте, какой тип запроса вы получили, является ли он типом «GET» или «POST», как только вы это узнаете, выполните соответствующие действия и вызовите один метод, который выполняет общую задачу для оба метода запроса, т.е. GET и POST.

@RequestMapping(value = "/books")
public ModelAndView listBooks(HttpServletRequest request){
     //handle both get and post request here
     // first check request type and do respective actions needed for get and post.

    if(GET REQUEST){

     //WORK RELATED TO GET

    }else if(POST REQUEST){

      //WORK RELATED TO POST

    }

    commonMethod(param1, param2....);
}
person Jayesh    schedule 01.08.2013
comment
Я прошу именно сигнатуру этого общего метода.. как он может принимать как HttpServletRequest, так и BindingResult? - person ; 01.08.2013
comment
По умолчанию, если вы не укажете какой-либо метод сопоставления ‹ @RequestMapping(value = /books) ›, он будет принимать как GET, так и POST-запросы, единственная часть, которую вам нужно проверить, это BindingResult. Нужно изучить это. я думаю, что это может справиться с этой частью, которую еще нужно проверить - person Jayesh; 01.08.2013
comment
вы можете принять внутренний параметр HttpServletRequest. Кроме того, если у вас меньше данных о BindingResult, примите свой параметр, используя request.getParameter(paramName) и проверьте условия, которые будут работать для обоих. (попробуйте это, если BindingResult вызывает у вас проблемы, тогда только в противном случае он будет работать, удалив сопоставление RequestMethod, я думаю) - person Jayesh; 01.08.2013

@RequestMapping(value = "/books", method = { RequestMethod.GET, 
RequestMethod.POST })
public ModelAndView listBooks(@ModelAttribute("booksFilter") BooksFilter filter,
     HttpServletRequest request) 
    throws ParseException {

//your code 
}

Это будет работать как для GET, так и для POST.

Для GET, если ваш pojo (BooksFilter) должен содержать атрибут, который вы используете в параметре запроса

как ниже

public class BooksFilter{

private String parameter1;
private String parameter2;

   //getters and setters

URL должен быть таким, как показано ниже

/книги?parameter1=бла

Таким образом, вы можете использовать его как для GET, так и для POST

person MPPNBD    schedule 11.09.2017