A list,

In SpringMVC, the Controller Controller is responsible for handling the requests distributed by DispatcherServlet. It encapsulates the data requested by the user into a Model after being processed by the business processing layer, and then returns the Model to the corresponding View for display. There’s a very easy way to define a Controller in SpringMVC, you don’t have to inherit a particular class or implement a particular interface, you just use @Controller to mark a class as Controller, Then use @requestMapping and @RequestParam annotations to define the mapping between the URL request and the Controller method so that the Controller can be accessed. In addition, Controller does not rely directly on HttpServlet objects such as HttpServletRequest and HttpServletResponse, which can be obtained flexibly through Controller method parameters. To get an idea of the Controller, let’s define a simple Controller:

Case 1:

@Controller public class MyController { @RequestMapping ( "/showView" ) public ModelAndView showView() { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName( "viewName" ); Modelandview.addobject (" The name of the property that needs to be placed in the model ", "the corresponding property value, which is an object"); return modelAndView; }}Copy the code

In the example above, @Controller is tagged above class MyController, so class MyController is a SpringMVC Controller object, Then use @requestMapping (” /showView “) to tag the Controller method so that MyController’s showView method is accessed when requesting/showview. do. This method returns a ModelAndView object containing Model and View. These will be covered in more detail later.

 

Define a Controller Controller using @controller

Example 1 shows that @Controller is used to mark a class, and the class it marks is a SpringMVC Controller object. The distribution handler will scan the method of the class that uses the annotation and check if the method uses the @RequestMapping annotation. @Controller just defines a Controller class, and the @requestMapping annotation is the handler that actually handles the request, which is covered next.

Just using the @Controller tag on a class doesn’t really make it a SpringMVC Controller class, because Spring doesn’t know it yet. So how do you do Spring to recognize it? At this point we need to hand over the controller class to Spring to manage.

At this point, there are two ways to hand MyController over to Spring so that it can recognize the @Controller we’ve tagged.

The first is to define the Bean object of MyController in the SpringMVC configuration file.

<bean class=”com.host.app.web.controller.MyController”/>

The second way is to tell Spring in the SpringMVC configuration file where to find the Controller Controller labeled @Controller.

    < context:component-scan base-package = "com.host.app.web.controller" >
       < context:exclude-filter type = "annotation"
           expression = "org.springframework.stereotype.Service" />
    </ context:component-scan > 
Copy the code

Note:

Context :exclude-filter is a class that does not scan @service

Use @requestMapping to map Request requests to processors

Example 1: You can use @requestMapping to map urls to Controller classes or to Controller processing methods. When @requestMapping is in the Controller class, the address of the @requestMapping method is relative to that of the @requestMapping class. When there is no @requestMapping annotation on the Controller class, @requestMapping on methods is an absolute path. This combination of absolute and relative paths makes the final path relative to the root path /.

In this controller, MyController is not tagged with @requestMapping, so when you need to access the @requestMapping showView method, you can use the absolute path/showview. do request.

Case 2

@Controller @RequestMapping ( "/test" ) public class MyController { @RequestMapping ( "/showView" ) public ModelAndView showView() { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName( "viewName" ); Modelandview.addobject (" The name of the property that needs to be placed in the model ", "the corresponding property value, which is an object"); return modelAndView; }}Copy the code

Example 2: Add @requestMapping annotation to controller MyController = MyController = MyController = MyController = MyController = MyController = MyController = MyController = MyController = MyController = MyController The/test/showView. Do.

(1) Use URI templates

A URI template is given a variable in a URI and dynamically assigned to that variable during mapping. For example, the URI template http://localhost/app/{variable1}/index.html contains a variable variable1, So when we request to http://localhost/app/hello/index.html, the URL as template matching, just put in the template variable1 to replace with hello. In SpringMVC, the values that replace the variables defined in the template can also be used by processor methods, which makes it very easy to implement a RestFul style of URL. This variable is marked in SpringMVC using @pathVariable. In SpringMVC, we can mark a Controller’s handler parameter with @pathvariable, indicating that the value of the parameter will be assigned to the corresponding variable in the URI template.

Example 3

@Controller @RequestMapping ( "/test/{variable1}" ) public class MyController { @RequestMapping ( "/showView/{variable2}" ) public ModelAndView showView( @PathVariable String variable1, @PathVariable ( "variable2" ) int variable2) { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName( "viewName" ); Modelandview.addobject (" The name of the property that needs to be placed in the model ", "the corresponding property value, which is an object"); return modelAndView; }}Copy the code

In example 3 we define two URI variables, variable1 on the controller class and variable2 on the showView method, and then use the @pathVariable tag in the arguments to the showView method. So when we use the/test/hello/showView / 2. When the do come to request can access to the MyController showView method, this time variable1 is given value hello, variable2 given value 2, Then we mark the showView method arguments variable1 and variable2 as path variables from the access path, so the method arguments variable1 and variable2 are given Hello and 2 respectively. Method arguments variable1 are defined as strings, and variable2 as ints. Spring automatically converts simple types like this when they are assigned. We’ll talk about how to convert complex types in a later article.

In the above code we can see that we use @pathvariable to mark variable1 as a path variable and @pathvariable (” variable2 “) to mark variable2. What’s the difference between the two? In the first case, the default is to find a variable with the same parameter name in the URI template, but this is only possible when compiling in debug mode, while in the second case, the URI template variable2 variable is explicitly used. The second method is used to specify which variable in the URI template is used when compiling in other than Debug mode, or when the variable name is not the same as the parameter name.

In addition to using URI templates in request paths and defining variables, @RequestMapping also supports the wildcard “*” character. I can use the code below/myTest/whatever/wildcard. Do testWildcard method of access to the Controller.

@Controller @RequestMapping ( "/myTest" ) public class MyController { @RequestMapping ( "*/wildcard" ) public String testWildcard() { System. out .println( "wildcard------------" ); return "wildcard" ; }}Copy the code

 

(2) Bind HttpServletRequest request parameters to controller method parameters using @requestParam

Example 4

    @RequestMapping ( "requestParam" )
   public String testRequestParam( @RequestParam(required=false) String name, @RequestParam ( "age" ) int age) {
       return "requestParam" ;
    } 
Copy the code

RequestParam binds the HttpServletRequest parameter name to the controller method parameter name and the controller method parameter age to the controller method parameter age. It is worth noting that, like @pathvariable, when you do not specify which argument to take from the request, Spring will default to a parameter with the same name as the method argument if the code is compiled by debug, and will raise an error if the code is not compiled by DEBUG. In addition, @requestParam also needs to specify which parameter to bind to when the parameter name from request is different from the parameter name of the method. In the above code if I call/requestparam.do? Name =hello&age=1 Spring will assign the request request name value Hello to the corresponding handler parameter name and the age value 1 to the corresponding handler parameter age.

In addition to specifying which parameter value to bind to, there is a required attribute in @requestParam, which indicates whether the specified parameter must exist in the Request attribute. The default is true, indicating that the specified parameter must exist, and an error is reported when it does not exist. If /requestParam.do is accessed without passing the required parameter, an exception will be raised. Because the age argument must exist, and we didn’t specify it. And if we call/requestparam.do? Age =1 is ok because we passed the required age parameter, but the name parameter is optional.

(3) Use @cookievalue to bind the value of cookie to the Controller method parameter

Case 5

    @RequestMapping ( "cookieValue" )
    public String testCookieValue( @CookieValue ( "hello" ) String cookieValue, @CookieValue String hello) {
       System. out .println(cookieValue + "-----------" + hello);
       return "cookieValue" ;
    } 
Copy the code

In the above code we bind the cookie value to the method parameter using @cookievalue. The value of the cookie named Hello is explicitly bound, and the value is not specified. Using a rule with no specified form is the same as @pathVariable and @requestParam, that is, the cookie value with the same name as the method parameter is automatically retrieved in debug compilation mode.

Bind the HttpServletRequest header to the Controller method parameter using the @requestheader annotation

Case 6

@RequestMapping ( "testRequestHeader" )
public String testRequestHeader( @RequestHeader ( "Host" ) String hostAddr, @RequestHeader String Host, @RequestHeader String host ) {
    System. out .println(hostAddr + "-----" + Host + "-----" + host );
    return "requestHeader" ;
} 
Copy the code

In the code above we used @requesTheader to bind the HttpServletRequest header host to the Controller method parameter. The three parameters of the above method will be given the same value, so we can know that the rule of binding request header parameter to method parameter is the same as @pathVariable, @requestParam and @Cookievalue, that is, when no parameter is specified to bind to method parameter, In debug compilation mode, the method parameter name is used as the parameter to bind. However, unlike the other three binding methods, @RequesTheader is case-insensitive when used with @RequesTheader, That is, @requestheader (” Host “) and @requestheader (” Host “) are both bound to the Host header. Remember that @PathVariable, @RequestParam, and @Cookievalue are case sensitive.

(5) Some advanced applications of @requestMapping

In RequestMapping, you can specify other attributes besides the request path value attribute, such as params, method, and headers. These attributes can then be used to narrow down the mapping of the request.

1. The params attribute

Example 7

@RequestMapping (value= "testParams" , params={ "param1=value1" , "param2" , "! param3" }) public String testParams() { System. out .println( "test Params..........." ); return "testParams" ; }Copy the code

Param1 must be equal to value1, param2 must exist, and the param2 parameter does not matter. The param3 parameter must not exist and can only be accessed if/testparams.do is requested and the specified three parameter conditions are met. So when requesting/testparams.do? Param1 =value1&param2=value2 Can correctly access the testParams method. When/testparams.do? Param1 =value1&param2=value2&param3=value3 cannot be accessed because param3 specified in the params parameter of @requestMapping does not exist.

2. The method attribute

Example 8

    @RequestMapping (value= "testMethod" , method={RequestMethod. GET , RequestMethod. DELETE })
    public String testMethod() {
       return "method" ;
    } 
Copy the code

In the code above, the method argument limits access to the Controller’s testMethod method only when/testmethod.do is requested by GET or DELETE methods.

3. The headers attribute

Example 9

    @RequestMapping (value= "testHeaders" , headers={ "host=localhost" , "Accept" })
    public String testHeaders() {
       return "headers" ;
    } 
Copy the code

The usage and functionality of the HEADERS attribute are similar to that of the Params attribute. In the above code, the testHeaders method can only be accessed when the request header contains Accept and the host is localhost.

(6) Method parameters and return types supported by the @requestMapping handler methods

1. Supported method parameter types

(1) HttpServlet objects, mainly including HttpServletRequest, HttpServletResponse and HttpSession objects. Spring assigns these parameters automatically when calling handler methods, so when you need to use these objects in a handler method, you can simply give a method parameter declaration on the method and use it in the method body. One thing to note, however, is that when using the HttpSession object, there is a problem if the HttpSession object has not yet been established.

(2) Spring’s own WebRequest object. Use this object to access property values stored in HttpServletRequest and HttpSession.

(3) InputStream, OutputStream, Reader and Writer InputStream and Reader are for HttpServletRequest and can fetch data from them; OutputStream and Writer are for HttpServletResponse, to which data can be written.

(4) Use arguments tagged with @pathVariable, @requestParam, @Cookievalue and @Requestheader.

(5) Parameters using the @modelAttribute tag.

(6) Java.util. Map, Spring-wrapped Model and ModelMap. These can be used to encapsulate model data and present it to the view.

(7) Entity class. Parameters that can be used to receive uploads.

(8) Spring packaged MultipartFile. It’s used to receive uploaded files.

(9) Errors and BindingResult objects that Spring encapsulates. These two object parameters must be immediately after the entity object parameter to be validated, which contains the validation result of the entity object.

2. Supported return types

(1) a ModelAndView object containing the ModelAndView.

(2) a Model object, which mainly includes the Spring packaging good Model and ModelMap, and Java. Util. Map, when no view back view name will be determined by RequestToViewNameTranslator.

(3) A View object. If the model is being rendered, you can define a model parameter for the processor method, and then add values to the model in the method body.

(4) A String. This usually represents a view name. If you need a model to render the view, you can give the handler a model parameter, and then add values to the model in the method body.

(5) Return void. This kind of situation usually we write return results directly in the HttpServletResponse, if there is no written, the Spring will use RequestToViewNameTranslator to return to a corresponding view name. If a model is needed in the view, it is handled in the same way as if a string is returned.

(6) If the handler method is annotated with @responseBody, then any return type of the handler method will be written to HttpServletResponse via HttpMessageConverters. It is not treated as a view or model as in the above cases.

(7) in addition to the above several circumstances of any return type will be as a property in the model to deal with, and return to view or determined by RequestToViewNameTranslator, Attribute names added to the model can be defined on this method with @ModelAttribute(” attributeName “), otherwise the class name of the return type will be lowercase. Methods using the @ModelAttribute tag are executed before methods using the @requestMapping tag.

7. Use @modelAttribute and @sessionAttributes to pass and save data

SpringMVC supports sharing data between different models and controllers using @ModelAttribute and @sessionAttributes. There are two main ways to use @modelAttribute. One is to tag methods and the other is to tag Controller method parameters.

When the @ModelAttribute tag is on a method, the method is executed before the processor method is executed, and the returned object is stored in session or model properties, The attributeName can be specified when the method is tagged using @modelattribute (” attributeName “). If it is not specified, the class name of the return type (lowercase) is used as the attributeName. Let’s do an experiment on whether the @modelAttribute attribute is stored in session or in the model when it comes to methods.

@Controller @RequestMapping ( "/myTest" ) public class MyController { @ModelAttribute ( "hello" ) public String getModel() { System. out .println( "-------------Hello---------" ); return "world" ; } @ModelAttribute ( "intValue" ) public int getInteger() { System. out .println( "-------------intValue---------------" ); return 10; } @RequestMapping ( "sayHello" ) public void sayHello( @ModelAttribute ( "hello" ) String hello, @ModelAttribute ( "intValue" ) int num, @ModelAttribute ( "user2" ) User user, Writer writer, HttpSession session) throws IOException { writer.write( "Hello " + hello + " , Hello " + user.getUsername() + num); writer.write( "\r" ); Enumeration enume = session.getAttributeNames(); while (enume.hasMoreElements()) writer.write(enume.nextElement() + "\r" ); } @ModelAttribute ( "user2" ) public User getUser() { System. out .println( "---------getUser-------------" ); return new User(3, "user2" ); }}Copy the code

Methods using the @modelAttribute tag are executed when we request /myTest/ sayhello.do, and the objects they return are stored in the model. When the sayHello method is finally accessed, all method parameters using the @modelAttribute tag are correctly injected. The following information is displayed:

 Hello world,Hello user210

We can see from the result that the session contains no properties, that is, the above objects are stored in the model property, not in the session property. So how do you store it in the session property? We’ll introduce a new concept called @sessionAttributes, whose usage will be explained after we talk about @modelAttribute, so we’ll use it here. We add @sessionAttributes to the MyController class to mark what needs to be stored in the session. Look at the following code:

@Controller @RequestMapping ( "/myTest" ) @SessionAttributes (value={ "intValue" , "stringValue" }, types={User. class }) public class MyController { @ModelAttribute ( "hello" ) public String getModel() { System. out .println( "-------------Hello---------" ); return "world" ; } @ModelAttribute ( "intValue" ) public int getInteger() { System. out .println( "-------------intValue---------------" ); return 10; } @RequestMapping ( "sayHello" ) public void sayHello(Map<String, Object> map, @ModelAttribute ( "hello" ) String hello, @ModelAttribute ( "intValue" ) int num, @ModelAttribute ( "user2" ) User user, Writer writer, HttpServletRequest request) throws IOException { map.put( "stringValue" , "String" ); writer.write( "Hello " + hello + " , Hello " + user.getUsername() + num); writer.write( "\r" ); HttpSession session = request.getSession(); Enumeration enume = session.getAttributeNames(); while (enume.hasMoreElements()) writer.write(enume.nextElement() + "\r" ); System. out .println(session); } @ModelAttribute ( "user2" ) public User getUser() { System. out .println( "---------getUser-------------" ); return new User(3, "user2" ); }}Copy the code

In the above code we specify that intValue or stringValue or User will be added to the Session. When we call /myTest/ sayhello. do, the result is as follows:

 Hello world,Hello user210

There are still no session attributes printed. What’s going on here? How can we define an object in the model with the attribute intValue and an object of type User to be stored in the session, but not actually added? Are we wrong? @sessionAttributes defines attributes that need to be stored in the session during the first call to /myTest/ sayhello. do. There are attributes in the model that need to be stored in the session, but they are not yet added to the session. So there are no properties in the session, and Spring will only add the corresponding properties from the model to the session after the handler method completes execution. So when the request is made a second time, the result is as follows:

 Hello world,Hello user210

user2

intValue

stringValue

When the @modelAttribute tag is on a processor method parameter, it indicates that the value of the parameter will be the attribute value of the corresponding name from the model or Session. The name can be specified by @modelAttribute (” attributeName “). The class name (lowercase) of the parameter type is used as the attribute name.