Make writing a habit together! This is the 11th day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

Learning is a step by step process. After understanding the background and concepts of SpringMVC, we will learn more about SpringMVC. As we know, SpringMVC is based on a set of MVC annotations that turn ordinary POJO classes into controllers without implementing any interfaces, so annotations are unshakable in SpringMVC. Here is an analysis of annotations in SpringMVC.

@RequestMapping

Let’s start with RequestMapping. This is an important API that we used when we wrote our introductory case, which can annotate other methods and specify request paths. Of course, RequestMapping doesn’t just modify methods. It can also modify classes, as in this example:

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {

	@RequestMapping("/test")
	public String hello(a) {
		System.out.println("hello world");
		return "success"; }}Copy the code

If you want to access the hello() method of this class from a URL, what should you say? The url is /springmvc/test.

From this we know:

  • Class definition: Provides preliminary request mapping information relative to the Web application root directory
  • Method definition: provides further mapping information relative to the URL at the class definition. If the class definition is not marked with @requestMapping, the URL marked at the method is relative to the root directory of the Web application

Obviously, @RequestMapping does a lot more than that, or I wouldn’t have bothered to write about it, so let’s look at its next function: mapping request parameters, request methods, or request headers

1. Map request parameters, request methods, or request headers

In addition to mapping requests using request URLS, @requestMapping can also map requests using request methods, request parameters, and request headers. Valie, Method, Params, and HEADS of @requestMapping represent request URLS, request methods, request parameters, and request headers, respectively. Look at an example:

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {

	@RequestMapping(value = "/testMethod", method = RequestMethod.POST)
	public String testMethod(a) {
		System.out.println();
		return "success"; }}Copy the code

Here we set the mapping path to/springMVC /testMethod, which is made up of both class and method annotations, and set the request to Post. Test page:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"% > <! DOCTYPE html> <html> <head> <meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<form action="springmvc/testMethod" method="post">
		<input type="submit" value="submit">
	</form>
	
</body>
</html>
Copy the code

Running results:

Note, however, that since you set the request mode to Post, if it is not Post the requester will report an error and will not work properly. This is a very common configuration in real development.

RequestMapping also supports setting request parameters and headers. RequestMapping supports simple expressions such as:

  • Param1: indicates that the request must contain the request parameter named param1
  • ! Param1: indicates that the request cannot contain request parameters named param1
  • param! =value1: Indicates that the request contains the request parameter named param1, but the value cannot be value1
  • {“param1=value1″,”param2”} : The request must contain param1 and param2, and the value of param1 must be value1

The request header is similar.

RequestMapping addresses with @requestMapping also support wildcards, but the wildcards must be in the Ant style. Ant style resource addresses support three matching cards:

  1. ? : Matches a character in the file name
  2. * : matches any character in the file name
  3. ** : matches multi-level paths

Let’s take an example:

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {

	@RequestMapping("testAntPath/*/abc")
	public String testAntPath(a) {
		System.out.println("testAntPath");
		return "success"; }}Copy the code

/testAntPath/test/ ABC, /testAntPath/test2/ ABC, etc. The other two wildcards are similar and won’t be repeated.

2.@PathVariable

@pathvariable maps placeholders for URL bindings. Placeholder urls are a new feature in Spring3.0, which is a milestone in SpringMVC’s evolution toward REST goals. Placeholder parameters in urls can be bound to controller method parameters with @pathvariable: {XXX} placeholders in urls can be bound to action method parameters with @pathvariable {” XXX “}. Look at an example:

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {

	@RequestMapping("testPathVariable/{id}")
	public String testPathVariable(@PathVariable("id") Integer id) {
		System.out.println("testPathVariable" + id);
		return "success"; }}Copy the code

With this configuration we can get the placeholder parameter of the URL and bind it to the parameter of the processing method. Let’s test it:

While we’re on the subject of REST, let’s talk briefly. REST: Representational State Transfer. (Resource) presentation layer state transformation is the most popular Internet software architecture. It has a clear structure, meets standards, is easy to understand, easy to expand, so more and more sites are using it.

  • Resources: An entity on the Network, or a specific piece of information on the network. It can be a piece of text, a picture, a song, a service, or a specific existence. You can point to it with a URI(uniform resource Locator), each resource has a specific URI, and to access the resource, you need to access its URI, so the URI is a unique identifier for each resource.
  • Representation layers: A Representation of a resource is called its Representation layer.
  • State Transfer: Each request represents an interaction between the client and the server. HTTP is a stateless protocol, that is, all states are stored on the server side. Therefore, if the client wants to operate the server, it must somehow make the server “state transition”, and this transition is built on top of the presentation layer, so it is “presentation layer transition”. GET, POST, PUT, and DELETE correspond to four basic operations. GET is used to obtain resources. POST is used to create a resource. PUT updates resources. DELETE Deletes a resource.

Example:

  • /order/1 HTTP GET: GET order with id = 1
  • /order/1 HTTP DELETE: DELETE the order whose id is 1
  • /order/1 HTTP PUT: Updates the order with id = 1
  • /order HTTP POST: Adds an order

This is a REST style add, delete, change query example. But the fact that browser forms only support GET and POST requests, and DELETE and PUT requests don’t, Spring3.0 adds a filter (HiddenHttpMethodFilter) that converts these requests to standard HTTP methods. Make browsers indirectly support GET, POST, PUT, and DELETE requests.

Let’s use this filter with an example that doesn’t make more sense than an actual case. First configure the filter in the web.xml file:

<! - configuration org. Springframework. Web. Filter. HiddenHttpMethodFilter: can post requests to delete or put request -- -- >
	<filter>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<url-pattern>/ *</url-pattern>
	</filter-mapping>
Copy the code

Next we create four forms in the JSP page for each of the four request types:


	<form action="springmvc/testRest/1" method="post">
		<input type="hidden" name="_method" value="PUT"> 
		<input type="submit" value="TestRest PUT">
	</form>
	<br>
	
	<form action="springmvc/testRest/1" method="post">
		<input type="hidden" name="_method" value="DELETE"> 
		<input type="submit" value="TestRest DELETE">
	</form>
	<br>
	
	<form action="springmvc/testRest" method="post">
		<input type="submit" value="TestRest POST">
	</form>
	<br>
	
	<form action="springmvc/testRest/1" method="get">
		<input type="submit" value="TestRest GET">
	</form>
	<br>
	
</body>
</html>
Copy the code

Then write the corresponding four test methods in the controller:

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {
	
	@RequestMapping(value = "/testRest/{id}", method = RequestMethod.PUT)
	public String testRestPut(@PathVariable Integer id) {
		System.out.println("testRest PUT: " + id);
		return "success";
	}
	
	@RequestMapping(value = "/testRest/{id}", method = RequestMethod.DELETE)
	public String testRestDelete(@PathVariable Integer id) {
		System.out.println("testRest DELETE: " + id);
		return "success";
	}
	
	@RequestMapping(value = "/testRest", method = RequestMethod.POST)
	public String testRestPost(a) {
		System.out.println("testRest POST");
		return "success";
	}

	@RequestMapping(value = "/testRest/{id}", method = RequestMethod.GET)
	public String testRestGet(@PathVariable Integer id) {
		System.out.println("testRest GET: " + id);
		return "success"; }}Copy the code

As mentioned earlier, an error will be reported if the client actually requests a different method than the @RequestMapping method, so if all four methods are successfully accessed, then the HiddenHttpMethodFilter has successfully converted the request method. Run to see the result:

There is no problem with the result, but there are some points to note here, I also encountered a lot of pits, and share with you:

  1. PUT and DELETE requests are not recognized, so they are assisted by a hidden field. The name of the hidden field must be “_method” and valueI must be the request method name, as determined by the underlying filter.
  2. If you encounter the following problems, then you have three solutions

C.<% @page language=” Java “contentType=”text/ HTML”; Charset =UTF-8″ pageEncoding=”UTF-8″ isErrorPage=”true”%> set isErrorPage to true

Those are the only two problems I’ve had so far.

@RequestParam

This is a Rest style URL that uses a placeholder to carry a parameter, but it is not really a request parameter. We should use @requestParam to handle request parameters.

Bind request parameters using @requestParam

Using @requestParam in the parameters of the processing method can pass the request parameters to the request method

  • Value: indicates the parameter name
  • Required: Indicates whether the request is required. The default value is true, indicating that the request parameter must contain the corresponding parameter. If not, an exception will be thrown

Look at an example:

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {

	/ * * *@RequestParamRequired specifies whether the request parameter is required. Default is true. DefaultValue specifies the defaultValue of the request parameter@param username
	 * @param age
	 * @return* /
	@RequestMapping(value = "/testRequestParam")
	public String testRequestParam(@RequestParam(value = "username") String username,
			@RequestParam(value = "age") int age) {
		System.out.println("testRequestParam,username = " + username + "--- age = " + age);
		return "success"; }}Copy the code

At this point we visit a URL like this:

http://localhost:8080/SpringMVC/springmvc/testRequestParam?username=abc&age=20
Copy the code

The running results are as follows:

testRequestParam,username = abc--- age = 20
Copy the code

As mentioned earlier, required defaults to true, so parameters configured with @requestParam must be carried when sending the request or an exception will be thrown, so if you want to set a parameter that is not required to be accessed successfully without it, Simply set the required attribute of this parameter to false.

	@RequestMapping(value = "/testRequestParam")
	public String testRequestParam(@RequestParam(value = "username") String username,
			@RequestParam(value = "age", required = false) int age) {
		System.out.println("testRequestParam,username = " + username + "--- age = " + age);
		return "success";
	}
Copy the code

@RequestHeader

@requestheader is used in the same way as @requestparam. It takes information from the RequestHeader and injects it into the target method’s parameters.

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {

	@RequestMapping(value = "/testRequestHeader")
	public String testRequestHeader(@RequestHeader(value="Accept-Language") String al) {
		System.out.println("testRequestHeader,Accept-Language: " + al);
		return "success"; }}Copy the code

Visit http://localhost:8080/SpringMVC/springmvc/testRequestHeader for testing, the result is as follows:

testRequestHeader,Accept-Language: zh-CN
Copy the code

@CookieValue

The @cookievalue annotation, as its name suggests, is used to fetch the cookie value and inject it into the target method’s parameters. Here’s an example:

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {
	
	@RequestMapping(value = "/testCookieValue")
	public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
		System.out.println("testCookieValue,sessionId: " + sessionId);
		return "success"; }}Copy the code

Visit http://localhost:8080/SpringMVC/springmvc/testCookieValue for testing, the result is as follows:

testCookieValue,sessionId: B7EB860C3764C4BAB0C1F526B830C1FF
Copy the code

Request parameter values are bound using POJO objects

We know that a form contains a lot of information, and it is usually too expensive to wrap this data into an object, so we can use an object as a request parameter. SpringMVC automatically matches request parameter names and POJO attribute names, automatically populates the object with attribute values. It also supports cascading properties such as dept.deptId, dept.adress.tel, etc. Let’s look at an example. Write the form first:

<form action="springmvc/testPojo" method="post">
		username:<input type="text" name="username">
		<br>
		password:<input type="password" name="password">
		<br>
		email:<input type="text" name="email">
		<br>
		age:<input type="text" name="age">
		<br>
		city:<input type="text" name="address.city">
		<br>
		province:<input type="text" name="address.province">
		<br>
		<input type="submit" value="submit">
	</form>
Copy the code

Then create two Bean classes:

public class User {

	private String username;
	private String password;
	private String email;
	private int age;

	private Address address;

	public Address getAddress(a) {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public String getUsername(a) {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword(a) {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getEmail(a) {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public int getAge(a) {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString(a) {
		return "User [username=" + username + ", password=" + password + ", email=" + email + ", age=" + age
				+ ", address=" + address + "]"; }}Copy the code
public class Address {
	
	private String province;
	private String city;
	public String getProvince(a) {
		return province;
	}
	public void setProvince(String province) {
		this.province = province;
	}
	public String getCity(a) {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	
	@Override
	public String toString(a) {
		return "Address [province=" + province + ", city=" + city + "]"; }}Copy the code

Because it supports cascading properties, address.city and address.province are fine in the form. Test method:

@RequestMapping("/springmvc")
@Controller
public class HelloWorld {
	
	@RequestMapping("/testPojo")
	public String testPojo(User user) {
		System.out.println("testPojo: " + user);
		return "success"; }}Copy the code

Visit http://localhost:8080/SpringMVC/springmvc/testPojo for testing, the result is as follows:

testPojo: User [username=admin, password=123456, [email protected], age=20, address=Address [province=ZheJiang, city=HangZhou]]
Copy the code

This method of injecting form parameters is often used, so be sure to master it.