在Spring中结合使用GET和POST请求方法

80

我有一个支持GETPOST请求的资源。这是一个示例资源的示例代码:

@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语句。我尝试过,但不起作用,因为两个方法在末尾有不同的参数,即HttpServletRequestBindingResult@RequestParam不是必需的,因此在POST请求中不需要)。如何将这两种方法结合起来?

14
为什么不将你的长代码移动到一个单独的方法中? - Narendra Pathai
如果代码非常长,你应该把它分成几个短方法。 - JB Nizet
因为我正在寻找一种更优雅和通用的解决方案。我认为拥有一个仅在两个方法中调用的方法booksLogic并不好。 - user1120144
1
@MilanMilanov:这将是最优雅的解决方案。拥有短小精悍的方法,专注于做好一件事并委托给其他短小精悍的方法,这是你应该追求的。 - JB Nizet
2
通常情况下,您使用GET来获取不改变服务器的内容,而使用POST来更改服务器上的内容。它们是数据库中读取和写入操作的等效HTTP操作。因此,最好将它们分开,并将公共逻辑拆分到不同的方法中。 - Dhanush Gopinath
长代码实际上并不是很长,它只是我的控制器逻辑。我希望你能理解我不想复制粘贴相同代码的意图。 - user1120144
3个回答

121
@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),那么你必须传递parameter1和parameter2参数。

根据你的条件使用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
}

5
有没有办法找出是哪种类型的请求,即GET还是POST - Govinda Sakhare
你可以检查请求头。 - Karan
SonarQube 引发警报 - 考虑将此方法列表缩小为一个。 - Ashishkel

9
以下是一种可以实现此目的的方法,可能不是最理想的方法。
创建一个接受两种类型请求的方法,然后检查收到的请求类型是“GET”还是“POST”,一旦确认,执行相应的操作,然后调用一个方法来执行 GET 和 POST 请求共同的任务。请注意保留HTML标记。
@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....);
}

我正在询问那个常见方法的签名..它如何同时接受HttpServletRequestBindingResult - user1120144
1
默认情况下,如果您没有指定任何映射方法 <@RequestMapping(value = "/books")>,则它将接受GET和POST请求,您需要检查的部分仅为BindingResult。需要探索一下。我认为它可以处理那部分,但仍需检查。 - Jayesh
您可以在参数中接受HttpServletRequest。此外,如果BindingResult上的数据较少,则可以使用request.getParameter("paramName")接受参数,并通过条件检查,这将适用于两种情况。 (如果BindingResult存在问题,请尝试此方法,否则只需删除RequestMethod映射即可) - Jayesh

5
@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

网址应该像下面这样

/books?parameter1=blah

这种方式可以同时用于GET和POST请求


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接