Kombinieren Sie GET- und POST-Anforderungsmethoden im Frühjahr

70

Ich habe eine Ressource, die sowohl GETals auch POSTAnfragen unterstützt. Hier ein Beispielcode für eine Beispielressource:

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

Der Code in den beiden Methoden ist praktisch der gleiche, mit Ausnahme einer Variablendefinition. Die beiden Methoden können mit method = {RequestMethod.POST, RequestMethod.GET}und einem einfachen ifInneren leicht kombiniert werden . Ich habe es versucht, aber es funktioniert nicht, da die beiden Methoden am Ende einen unterschiedlichen Parameter haben, dh HttpServletRequestund BindingResult(die @RequestParamsind nicht erforderlich und werden daher in der POSTAnforderung nicht benötigt ). Irgendwelche Ideen, wie man die beiden Methoden kombiniert?

BalusC
quelle
12
Warum verschieben Sie Ihren LANGEN CODE nicht auf eine separate Methode?
Narendra Pathai
Und wenn es so lang ist, sollten Sie es sogar in mehrere kurze Methoden aufteilen
JB Nizet
Weil ich nach einer eleganteren und allgemeineren Lösung suche. Ich denke nicht, dass es gut ist, eine Methode zu haben booksLogic, die das einzige ist, was ich in den beiden Methoden nenne.
1
@MilanMilanov: Dies wäre die eleganteste Lösung. Sie sollten danach streben, kurze Methoden zu haben, die eine Sache gut machen und an andere kurze Methoden delegieren.
JB Nizet
2
Im Allgemeinen verwenden Sie GET für Dinge, die den Server nicht ändern, und POST für Dinge, die den Server ändern. Sie sind die entsprechenden http-Operationen von READ und WRITE in der Datenbank. Es ist also ideal, sie zu trennen und die gemeinsame Logik auf eine andere Methode aufzuteilen
Dhanush Gopinath,

Antworten:

102
@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
}

Wenn @RequestParam(required = true)dann müssen Sie Parameter1, Parameter2 übergeben

Verwenden Sie BindingResult und fordern Sie sie basierend auf Ihren Bedingungen an.

Der andere Weg

@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
}
Prabhakaran Ramaswamy
quelle
5
Gibt es eine Möglichkeit zu finden, welche Art von requestdh GEToder POSTkam?
Govinda Sakhare
Sie können den Anforderungsheader überprüfen.
Karan
SonarQube löst eine Warnung aus - Ziehen Sie in Betracht, diese Liste von Methoden auf eine zu beschränken.
Ashishkel
9

Im Folgenden finden Sie eine Möglichkeit, wie Sie dies erreichen können. Dies ist möglicherweise keine ideale Methode.

Lassen Sie eine Methode beide Anfragetypen akzeptieren, und überprüfen Sie dann, welche Art von Anforderung Sie erhalten haben. Ist sie vom Typ "GET" oder "POST", führen Sie die entsprechenden Aktionen aus und rufen Sie eine Methode auf, für die eine allgemeine Aufgabe ausgeführt wird beide Anforderungsmethoden dh GET und 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....);
}
Jayesh
quelle
Ich frage genau nach der Signatur dieser gemeinsamen Methode. Wie kann sie sowohl HttpServletRequestals auch akzeptieren BindingResult?
1
Wenn Sie keine Zuordnungsmethode <@RequestMapping (value = "/ books")> erwähnen, werden standardmäßig sowohl GET- als auch POST-Anforderungen akzeptiert. Der einzige Teil, den Sie überprüfen müssen, ist BindingResult. Müssen das erforschen. Ich denke, es kann damit umgehen, dass der Teil noch überprüft werden muss
Jayesh
Sie können HttpServletRequest innerhalb des Parameters akzeptieren. Wenn Sie weniger Daten zu BindingResult haben, akzeptieren Sie Ihren Parameter mit request.getParameter ("paramName") und überprüfen Sie anhand von Bedingungen, die für beide funktionieren würden. (Versuchen Sie dies, wenn BindingResult Ihnen Probleme bereitet, dann funktioniert es nur, wenn Sie das RequestMethod-Mapping entfernen, glaube ich.)
Jayesh
1
@RequestMapping(value = "/books", method = { RequestMethod.GET, 
RequestMethod.POST })
public ModelAndView listBooks(@ModelAttribute("booksFilter") BooksFilter filter,
     HttpServletRequest request) 
    throws ParseException {

//your code 
}

Dies funktioniert sowohl für GET als auch für POST.

Für GET, wenn Ihr Pojo (BooksFilter) das Attribut enthalten muss, das Sie im Anforderungsparameter verwenden

Wie unten

public class BooksFilter{

private String parameter1;
private String parameter2;

   //getters and setters

URl sollte wie folgt sein

/ books? parameter1 = bla

Auf diese Weise können Sie es sowohl für GET als auch für POST verwenden

MPPNBD
quelle