spirng data binding

Posted by nonexistentera on Sun, 19 Dec 2021 10:26:29 +0100

Data binding

Introduction to data binding

When executing the program, Spring MVC will convert and bind the information in the request message to the method parameters of the controller class in a certain way according to the different request parameters of the client. This process of connecting request message data with background method parameters is data binding in Spring MVC.
In the process of data binding, the Spring MVC framework will type convert the content of the request parameter string through the data binding component, and then assign the converted value to the formal parameters of the methods in the controller class, so that the background methods can correctly bind and obtain the parameters carried by the client request.
1) Spring MVC passes the ServletRequest object to DataBinder.
2) Pass the input parameter object of the processing method to the DataBinder.
3) DataBinder calls the ConversionService component to perform data type conversion and data formatting, and fills the message in the ServletRequest object into the parameter object.
4) Call the Validator component to verify the data validity of the parameter object that has bound the request message data.
5) After verification, a data binding result BindingResult object will be generated, and Spring MVC will assign the contents of the BindingResult object to the corresponding parameters of the processing method.
According to the type and number of client request parameters, we mainly divide the data binding in Spring MVC into simple data binding and complex data binding

Simple data binding

Bind default data type

When the parameters requested by the current side are relatively simple, you can directly use the default parameter type provided by Spring MVC in the formal parameters of the background method for data binding.
Common default parameter types
1. HttpServletRequest: obtain the request information through the request object
2. HttpServletResponse: process response information through response
3. HttpSession: get the objects stored in the session through the of the session object
4. Model/ModelMap: model is an interface and ModelMap is an interface implementation, which is used to fill model data into the request field.
1) In Eclipse, create a Web project named chapter13, then add the Spring MVC related JAR package to the lib directory of the project and publish it to the classpath. lib directory after adding JAR package.
2) On the web XML, configure the front-end controller of Spring MVC and other information.
3) In the src directory, create the spring MVC core configuration file, SpringMVC config XML, in which the component scanner and view parser are configured.
springmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
	<context:component-scan base-package="com.ex.controller"/>
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/jsp/"/>
	<property name="suffix" value=".jsp"/>
</bean>
</beans>

4) In the src directory, create a com Ex.controller package, under which a controller class UserController for user operation is created

package com.ex.controller;

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {
	@RequestMapping("/selectUser")
	public String selectUser(HttpServletRequest request){
		String id=request.getParameter("id");
		System.out.println("id="+id);
		return "success";
	}
}

5) In the WEB-INF directory, create a folder named jsp, and then create the page file success,jsp in the folder. The interface is only used as the response page after the correct operation, without other business logic

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
  ok
</body>
</html>

6) Publish the project to Tomcat and start it, and visit it in the browser.

Bind simple data type

The binding of simple data types refers to the binding of several basic data types in Java, such as int, String, Double and so on.
1) First, modify the controller class and modify the parameters of the methods in the controller to use simple data types

	@RequestMapping("/selectUser")
	public String selectUser(int id){
		System.out.println("id="+id);
		return "success";
	}

Compared with the selectUser() method in the default data type case, this method only replaces the HttpServletRequest parameter with the Integer type.
Start the project and open it with a browser

It should be noted that sometimes the parameter name in the front-end request is different from the formal parameter name in the background controller class method, which will cause the background to not bind and receive the parameters requested by the front-end correctly. To this end, Spring MVC provides the RequestParam annotation for indirect data binding.
@The RequestParam annotation is mainly used to define the parameters in the request, and its four attributes can be specified when used

attributeexplain
valueThe alias of the name attribute. Here, it refers to the name of the parameter, that is, the name of the request parameter entering the parameter. For example, value="item_id" indicates that the name of the request parameter is item_ The value of the parameter ID will be passed in. If only the value attribute is used, the value attribute name can be omitted
nameSpecifies the name of the request header binding, the same as value
requireIt is used to specify whether the parameter must be. The default is true, indicating that there must be corresponding parameters in the request
defaultValueDefault value indicates the default value if there is no parameter with the same name in the request
	@RequestMapping("/selectUser")
	public String selectUser(@RequestParam(value="user_id")Integer id){
		System.out.println("id="+id);
		return "success";
	}

Binding POJO type

When using simple data type binding, you can easily define the type and number of terrain parameters in the method according to specific requirements. However, in practical application, the client request may pass multiple parameter data of different types. If you also use simple data type binding, you need to manually write multiple parameters of different types, This operation is obviously cumbersome. At this point, you can use POJO type for data binding.
POJO type data binding is to encapsulate all associated request parameters in a POJO, and then directly use the POJO as a formal parameter in the method to complete data binding.
1) In the src directory, create a com Ex.po package, create a User class under the package to encapsulate the information parameters of User registration
User.java

package com.ex.po;
public class User {
	private Integer id;
	private String username;
	private Integer password;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public Integer getPassword() {
		return password;
	}
	public void setPassword(Integer password) {
		this.password = password;
	}
}

2) In the controller UserController class, write methods that accept user registration information and jump to the registration page

	@RequestMapping("/toRegister")
	public String toRegister(){
		return "register";
	}
	@RequestMapping("/registerUser")
	public String registerUser(User user){
		String username=user.getUsername();
		Integer password=user.getPassword();
		System.out.println("username="+username);
		System.out.println("password="+password);
		return "success";
	}

3) In the / WEB-INF/jsp directory, create a user registration page register JSP, write the user registration form in this interface. The form needs to be submitted in POST mode, and a request message ending with "/ registerUser" will be sent when submitting.
register.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="${pageContext.request.contextPath}/registerUser" method="post">
		user name:<input type="text name="username"/><br/> 
		password:<input type="password" name="password"/><br/>
		<input type="submit" value="register"/>
	</form>
</body>
</html>

4) Publish the project to the Tomcat server and start the browser to access it



Solve the Chinese garbled code of request parameters


You can see that the password information has been displayed correctly, but the user name is garbled.
In order to prevent the Chinese input from the front end from being garbled, we can use the encoding filter provided by Spring to uniformly encode. The encoding filter should be used and executed on the web Add the following code to the XML

<filter>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<filter-class>
  		org.springframework.web.filter.CharacterEncodingFilter
  	</filter-class>
  	<init-param>
  		<param-name>encoding</param-name>
  		<param-value>UTF-8</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>CharacterEncodingFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

Through the configuration of the < filter mapping > element, the above code will intercept all requests in the front-end page and submit them to the encoding filter class named characterencoding filter for processing. In the < Filter > element, first configure the encoding filter class org springframework. web. filter. Characterencoding filter, and then set the unified encoding to UTF-8 through initialization parameters, so that all request information contents will be parsed in UTF-8 encoding format.

Binding packaging POJO

Most data binding has been done using simple POJO types, but sometimes the parameters passed in client requests are complex. For example, when a user queries an order, the parameters passed on the page may include the order number, user name and other information, which includes the information of the order and the user. If all the query conditions of the order and the user are encapsulated in a simple POJO, it will obviously be confusing. At this time, you can consider using data binding of wrapped POJO type.
1) At chapter13 project's com In the ex.po package, create an order class, Orders, which is used to encapsulate Orders and user information
Orders.java

package com.ex.po;
public class Orders {
	private Integer ordersId;
	private User user;
	public Integer getOrdersId() {
		return ordersId;
	}
	public void setOrdersId(Integer ordersId) {
		this.ordersId = ordersId;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
}

In the POJO class installed in the above package, the order number, attributes for POJO and their corresponding getter/setter methods are defined. In this way, the order class can encapsulate not only the basic attribute parameters of the order, but also the attribute parameters of User type.
2) On COM In the ex.controller package, create an order controller class OrdersController, and write a method to jump to the order query page and a method to query the order and user information in this class
OrdersController.java

	@RequestMapping("findOrdersWithUser")
	public String findOrdersWithUser(Orders orders){
		Integer orderId=orders.getOrdersId();
		User user=orders.getUser();
		String username=user.getUsername();
		System.out.println("ordersId="+ordersId);
		System.out.println("username="+username);
		return "success";
	}

3) In the / WEB-INF/jsp directory, create a user order query page orders JSP, write the code to query the order information through the order number and the user as the query criteria

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="${pageContext.request.contextPath }/findOrdersWithUser" method="post">
		Order No.:<input type="text" name="ordersId"/><br>
		User:<input type="text" name="user.username"/><br>
		<input type="submit" value="query">
	</form>
</body>
</html>

4) Browser access

Custom data binding

In general, basic data type and POJO type parameter data are used. However, some special types of parameters cannot be directly converted in the background. For example, date data needs to be developed into a custom converter or formatted for data binding.
1,Converter
The Spring framework provides a Converter for converting objects of one type into objects of another type. For example, the Date entered by the user may be in the form of a string of "2017-04-08" or "2017 / 04 / 08". To bind the entered Date to the day after tomorrow, Spring needs to convert the string into a Date. At this time, you can customize a Converter class to convert the Date.
The custom converter class needs to implement org springframework. core. convert. converter. Converter interface

public interface Converter<S,T>{
	T convert (S source);
}

In the above interface code, S in the generic type represents the source type, T represents the target type, and convert(S source) represents the method in the interface.
In the src directory, create a com Ex.convert package, create a Date conversion class DataConverter under this package, and write the code to convert String type into Date type in this class interface,
DateConverter.java

package com.ex.convert;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
public class DateConverter implements Converter<String,Date>{
	private String datePattern="yyyy-MM-dd HH:mm:ss";
	@Override
	public Date convert(String source) {
		SimpleDateFormat sdf=new SimpleDateFormat(datePattern);
		try{
			return sdf.parse(source);
		}catch (ParseException e){
			throw new IllegalArgumentException("Invalid date format, please use this format:"+datePattern);
		}
	}
	
}

In the above code, the DateConverter class implements the Converter interface. In this interface, the first type String represents the data type to be converted, and the second type Date represents the target type to be converted.
In order for Spring MVC to know and use this converter class, you also need to write a Bean with id conversionService in its configuration file
springmvc-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
	<context:component-scan base-package="com.ex.controller"/>
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/jsp/"/>
	<property name="suffix" value=".jsp"/>
</bean>
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
	<property name="conversion">
		<set>
			<bean class="com.ex.convert.DateConverter"/>
		</set>
	</property>
</bean>
</beans>

Firstly, the schema information of three MVCs is added; Then the component scanner and view parser are defined; Next, it shows that the custom type Converter is assembled; Finally, the configuration of custom type Converter is written, in which the class name of Bean must be org springframework. context. support. Conversionservicefactorybean, and the Bean also needs to contain a converters attribute, which lists all converters customized in the program.
To test the use of the converter, you can Create a date control class DateController in the ex.controller package, and write methods to bind date data in the class.

package com.ex.controller;

import java.util.Date;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class DateController {
	@RequestMapping("/customDate")
	public String CustomDate(Date date){
		System.out.println("date="+date);
		return "success";
	}
}


Note: spaces between date data.
2,Formatter
In addition to using Converter for conversion, we can also use formatter for type conversion. Formatter has the same function as Converter, except that the source type of formatter must be a String type, and Converter can be any type.
Using formatter to customize the converter class requires the implementation of org springframework. format. Formatter interface

public interface Formatter<T> extends Printer<T>,Parser<T>{}

In the above code, the Formatter interface inherits the Printer and Parser interfaces, and its generic T represents the target type to be converted by the input string. The Print and Parser interfaces include a print() and Parse() method respectively, and all implementation classes must override these two methods.
On COM In the ex.convert package, create a date conversion class DateFormatter, in which the Formatter is used to customize the date converter
DateFormatter.java

package com.ex.controller;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.springframework.format.Formatter;
public class DateFormatter implements Formatter<Date>{
	private String datePattern="yyyy-MM-dd HH:mm:ss";
	private SimpleDateFormat simpleDateFormat;
	@Override
	public String print(Date date, Locale locale) {
		return new SimpleDateFormat().format(date);
	}

	@Override
	public Date parse(String source, Locale locale) throws ParseException {
		simpleDateFormat=new SimpleDateFormat(datePattern);
		return simpleDateFormat.parse(source);
	}
}

The datefirmutter class implements the Formatter interface and two methods in the interface. The print() method returns the String of the target object, and the parse() method parses a String into the target type using the specified Locale.
To use the date converter customized by Formatter, you also need to register in the Spring MVC configuration file

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
	<property name="formatters">
		<set>
			<bean class="com.ex.convert.DateFormatter"/>
		</set>
	</property>
</bean>

Complex data binding

Bind array

In actual development, you may encounter the situation that the front-end request needs to be passed to one or more parameters with the same name in the background (such as batch deletion). In this case, the simple data binding method described above is obviously inappropriate. At this point, you can use the method of binding array to complete the actual requirements.
1) In the / WEB-INF/jsp directory of chapter13 project, create a list page showing user information, user jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="${pageContext.request.contextPath }/deleteUsers" method="post">
		<table width="20%" border=1>
			<tr>
				<td>choice</td>
				<td>user name</td>
			</tr>
			<tr>
				<td><input name="ids" value=1 type="checkbox"></td>
				<td>tom</td>
			</tr>
			<tr>
				<td><input name="ids" value=2 type="checkbox"></td>
				<td>jack</td>
			</tr>
			<tr>
				<td><input name="ids" value=3 type="checkbox"></td>
				<td>lucy</td>
			</tr>
		</table>
	</form>
</body>
</html>

2) In the control class UserController, write a method to accept batch deletion of users

	@RequestMapping("/toUser")
	public String selectUsers(){
		return "user";
	}
	@RequestMapping("/deleteUsers")
	public String deleteUsers(Integer[] ids){
		if(ids!=null){
			for(Integer id:ids){
				System.out.println("Deleted id by"+id+"User!");
			}
		}else{
			System.out.println("ids=null");
		}
		return "success";
	}

3) Browser access

Binding collection

The data passed from the front end may contain various types of data, such as Integer, String, etc. In this case, we can use collection data binding. That is, define a collection of user information classes in the wrapper class, and then define the parameter type as the collection of the wrapper class in the acceptance method.
1) In the src directory, create a com Ex.vo package, and create a wrapper class UserVO in the package to encapsulate the user collection attributes
UserVO.java

package com.ex.vo;

import java.util.List;

import com.ex.po.User;

public class UserVO {
	private List<User> users;

	public List<User> getUsers() {
		return users;
	}

	public void setUsers(List<User> users) {
		this.users = users;
	}
}

2) In the controller class UserController, write a method to accept batch modification of users and a method to jump to the user modification page

	@RequestMapping("/toUserEdit")
	public String toUserEdit(){
		return "user_edit";
	}
	@RequestMapping("/editUsers")
	public String editUsers(UserVO userList){
		List<User> users=userList.getUsers();
		for(User user:users){
			if(user.getId()!=null){
				System.out.println("Modified id by"+user.getId()+"Your user name is:"+user.getUsername());
			}
		}
		return "success";
	}

Note: when using set data binding, the background method does not support data binding directly with binding parameters, so you need to use the wrapped POJO as the formal parameter, and then wrap a set attribute in the POJO.
3) In the / WEB-INF/jsp directory of the project, create the page file user_edit.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
		<form action="${pageContext.request.contextPath }/editUsers" method="post">
		<table width="20%" border=1>
			<tr>
				<td>choice</td>
				<td>user name</td>
			</tr>
			<tr>
				<td><input name="user[0].id" value=1 type="checkbox"></td>
				<td><input name="user[0].username" value="tome" type="text"></td>
			</tr>
			<tr>
				<td><input name="user[1].id" value=2 type="checkbox"></td>
				<td><input name="user[1].username" value="jack" type="text"></td>
			</tr>
		</table>
		<input type="submit" value="modify"/>
	</form>
</body>
</html>

4) Browser view


Topics: Java Spring mvc