SpringBoot(05) -- Web development -- request parameter processing

SpringBoot2 study notes

source address

4. Web development

4.3) Request parameter processing

4.3.1) The use and principle of rest

Rest [@RequestMapping] style support ( using HTTP request verbs to represent operations on resources )

  • Before: /getUser get user /deleteUser delete user /editUser modify user /saveUser save user

  • Now: /user GET - get user DELETE - delete user PUT - **modify user POST -** save user

  • Core Filter; HiddenHttpMethodFilter

  • Usage: form method=post, hidden field _method=put

  • Manually open in SpringBoot

4.3.1.1) Request mapping example

Modify HelloController.java in the project SpringBootDemo3, the code is as follows:

@RestController
public class HelloController {
    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public String getUser() {
        return "GET-张三";
    }
​
    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public String saveUser() {
        return "POST-张三";
    }
​
​
    @RequestMapping(value = "/user", method = RequestMethod.PUT)
    public String putUser() {
        return "PUT-张三";
    }
​
    @RequestMapping(value = "/user", method = RequestMethod.DELETE)
    public String deleteUser() {
        return "DELETE-张三";
    }
}

Modify the configuration file application.yaml, the code is as follows:

spring:
  mvc:
    # 开启 HiddenHttpMethodFilter
    hiddenmethod:
      filter:
      #开启页面表单的Rest功能,选择性开启,无页面交互即可关闭【前后端分离】
        enabled: true

Modify the home page index.html, the code is as follows:

测试REST风格;
<form action="/user" method="get">
    <input value="REST-GET 提交" type="submit"/>
</form>
<form action="/user" method="post">
    <input value="REST-POST 提交" type="submit"/>
</form>
<form action="/user" method="post">
    <input name="_method" type="hidden" value="delete"/>
    <input value="REST-DELETE 提交" type="submit"/>
</form>
<form action="/user" method="post">
    <input name="_method" type="hidden" value="PUT"/>
    <input value="REST-PUT 提交" type="submit"/>
</form>

Test, start the project, and visit the home page with a browser: http://localhost:8080/ ,

 4.3.1.2) Rest principle

The relevant source code is as follows:

The OrderedHiddenHttpMethodFilter method in WebMvcAutoConfiguration.java, the source code is as follows:

    @Bean
    @ConditionalOnMissingBean({HiddenHttpMethodFilter.class})
    @ConditionalOnProperty(
        prefix = "spring.mvc.hiddenmethod.filter",
        name = {"enabled"},
        matchIfMissing = false
    )
    public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new OrderedHiddenHttpMethodFilter();
    }

The doFilterInternal method in HiddenHttpMethodFilter.java, the source code is as follows:

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        HttpServletRequest requestToUse = request;
        if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
            String paramValue = request.getParameter(this.methodParam);
            if (StringUtils.hasLength(paramValue)) {
                String method = paramValue.toUpperCase(Locale.ENGLISH);
                if (ALLOWED_METHODS.contains(method)) {
                    requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
                }
            }
        }
​
        filterChain.doFilter((ServletRequest)requestToUse, response);
    }

Rest principle (when submitting a form using REST):

Form submission will bring _method=PUT

The request is intercepted by HiddenHttpMethodFilter, and the following operations are performed:

Whether the request is normal and is POST

Get the value of _method

Compatible with the following requests [PUT . DELETE . PATCH]

Native request (post), the packaging mode requestsWrapper rewrites the getMethod method, and returns the passed in value;

When the filter chain is released, wrapper is used, and the subsequent method calls getMethod to call requesWrapper

The execution process is as follows:

 Rest uses client tools, such as PostMan to directly send Put, delete, etc. requests, so there is no need for Filter

Extension point: How to modify _method to a custom one?

Create a new configuration class WebConfig.java, the code is as follows:

@Configuration
public class WebConfig {
​
    @Bean
    // 开发者实现 HiddenHttpMethodFilter()方法,将 _method修改为 _m
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        methodFilter.setMethodParam("_m");
        return methodFilter;
    }
}

Modify the home page index.html, the code is as follows:

<form action="/user" method="post">
    <input name="_method" type="hidden" value="delete"/>
    <input name="_m" type="hidden" value="delete"/>
    <input value="REST-DELETE 提交" type="submit"/>
</form>
<form action="/user" method="post">
    <input name="_method" type="hidden" value="PUT"/>
    <input value="REST-PUT 提交" type="submit"/>
</form>

Test: delete adds " m", it can be executed; put does not add " m", it cannot be executed, the page is as follows

 4.3.2) Principle of request mapping

SpringMVC functional analysis starts from org.springframework.web.servlet.DispatcherServlet-"doDispatch()

The calling sequence in SpingBoot is as follows:

 The source code of doDispatch() in DispatcherServlet.java is as follows:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
​
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
​
        try {
            ModelAndView mv = null;
            Exception dispatchException = null;
​
            try {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);
​
                // 找到当前请求使用哪个Handler(Controller的方法)处理
                mappedHandler = getHandler(processedRequest);
                
                //HandlerMapping:处理器映射。/xxx->>xxxx
                ...

The source code of getHandler() is as follows:

    @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            Iterator var2 = this.handlerMappings.iterator();
​
            while(var2.hasNext()) {
                HandlerMapping mapping = (HandlerMapping)var2.next();
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
​
        return null;
    }

During execution, this.handlerMappings [there are 5 processor mappings], as shown in the figure below:

 RequestMappingHandlerMapping : Saves all @RequestMapping and handler mapping rules.

 All request mappings [who is responsible for processing each request] are in HandlerMapping:

  1. SpringBoot automatically configures the WelcomePageHandlerMapping of the welcome page, and accesses/can access index.html;

  2. SpringBoot automatically configures the default RequestMappingHandlerMapping

  3. When the request comes in, try all HandlerMapping one by one to see if there is any request information:

    • If there is, find the handler corresponding to this request

    • If not, it is the next HandlerMapping

4.3.3) SpringMVC handles web requests

4.3.3.1) Notes

4.3.3.1.1)@PathVariable

@PathVariable: Get the value of the variable in the path

Modify ParameterTestController.java in the project SpringBootDemo3, the code is as follows:

@RestController
public class ParameterTestController {
​
    // @PathVariable:获取到路径中变量的值
    //  car/3/owner/lisi
    @GetMapping("/car/{id}/owner/{username}")
    public Map<String, Object> getCar(@PathVariable("id") Integer id,
                                      @PathVariable("username") String name,
                                      @PathVariable Map<String, String> pv) {
        Map<String, Object> map = new HashMap<>();
        map.put("路径中变量id ",id);
        map.put("路径中变量name ",name);
        map.put("路径中所有变量Map",pv);
        return map;
    }

Modify the home page index.html, the code is as follows:

测试基本注解:
<ul>
    <a href="car/3/owner/lisi">car/{id}/owner/{username}</a>
    <li>@PathVariable(路径变量)</li>
</ul>

Test: The project starts, the browser visits the home page http://localhost:8080/ , clicks the hyperlink "car/{id}/owner/{username}", and the page jumps to: http://localhost:8080/car/ 3/owner/lisi , the page looks like this:

4.3.3.1.2)@RequestHeader

@RequestHeader: Get the value in the request header information

Modify ParameterTestController.java, the code is as follows:

@GetMapping("/car/{id}/owner/{username}")
    public Map<String, Object> getCar(@PathVariable("id") Integer id,
                                      @PathVariable("username") String name,
                                      @PathVariable Map<String, String> pv,
                                      @RequestHeader("User-Agent") String userAgent,
                                      @RequestHeader Map<String, String> header) {
        Map<String, Object> map = new HashMap<>();
        map.put("路径中变量id ", id);
        map.put("路径中变量name ", name);
        map.put("路径中所有变量Map", pv);
        map.put("请求头中变量userAgent", userAgent);
        map.put("请求头中所有变量Map", header);
        return map;
    }
修改首页i
index.html, the code is as follows:
测试基本注解:
<ul>
    <a href="car/3/owner/lisi">car/{id}/owner/{username}</a>
    <li>@PathVariable(路径变量)</li>
    <li>@RequestHeader(获取请求头)</li>
</ul>

Test: The project starts, the browser visits the home page http://localhost:8080/ , clicks the hyperlink "car/{id}/owner/{username}", and the page jumps to: http://localhost:8080/car/ 3/owner/lisi , the page looks like this:

 4.3.3.1.3)@RequestParam

@RequestParam: Get the value in the request parameter information

Modify ParameterTestController.java, the code is as follows:

    @GetMapping("/car/{id}/owner/{username}")
    public Map<String, Object> getCar(@RequestParam("age") Integer age,
                                      @RequestParam("inters") List<String> inters,
                                      @RequestParam Map<String, String> params) {
        Map<String, Object> map = new HashMap<>();
        map.put("请求参数中变量age", age);
        map.put("请求参数中集合inters", inters);
        map.put("请求参数中所有变量Map", params);
        return map;
    }

Modify the home page index.html, the code is as follows:

测试基本注解:
<ul>
    <a href="car/3/owner/lisi?age=18&inters=basketball&inters=game">car/{id}/owner/{username}</a>
    <li>@PathVariable(路径变量)</li>
    <li>@RequestHeader(获取请求头)</li>
    <li>@RequestParam(获取请求参数)</li>
</ul>

Test: The project starts, the browser visits the home page http://localhost:8080/ , clicks the hyperlink "car/{id}/owner/{username}", and the page jumps to: http://localhost:8080/car/ 3/owner/lisi?age=18&inters=basketball&inters=game , the page looks like this:

 4.3.3.1.4)@CookieValue

@CookieValue: Get the value in the cookie information

Modify ParameterTestController.java, the code is as follows:

    @GetMapping("/car/{id}/owner/{username}")
    public Map<String, Object> getCar( @CookieValue("_ga") String _ga,
                                       @CookieValue("_ga") Cookie cookie) {
        Map<String, Object> map = new HashMap<>();
        map.put("cookie信息中变量_ga", _ga);
        map.put("cookie信息的所有内容", cookie);
        System.out.println(cookie.getName() + "===>" + cookie.getValue());
        return map;
    }

Modify the home page index.html, the code is as follows:

测试基本注解:
<ul>
    <a href="car/3/owner/lisi?age=18&inters=basketball&inters=game">car/{id}/owner/{username}</a>
    <li>@PathVariable(路径变量)</li>
    <li>@RequestHeader(获取请求头)</li>
    <li>@RequestParam(获取请求参数)</li>
    <li>@CookieValue(获取cookie值)</li>
</ul>

Test: The project starts, the browser visits the home page http://localhost:8080/ , clicks the hyperlink "car/{id}/owner/{username}", and the page jumps to: http://localhost:8080/car/ 3/owner/lisi?age=18&inters=basketball&inters=game , the page looks like this:

 Console output:

_ga===>GA1.1.1657823623.1653548910

4.3.3.1.5)@RequestBody

@RequestBody: Get the value in the request body information

Modify ParameterTestController.java, the code is as follows:

    // @RequestBody:获取请求体信息中的值
    @PostMapping("/save")
    public Map postMethod(@RequestBody String content) {
        Map<String, Object> map = new HashMap<>();
        map.put("请求体信息的所有内容", content);
        return map;
    }

Modify the home page index.html, the code is as follows:

<br/>
<form action="/save" method="post">
    测试@RequestBody获取数据 <br/>
    用户名:<input name="userName"/> <br>
    邮箱:<input name="email"/>
    <input type="submit" value="提交"/>
</form>

Test: The project starts, the browser visits the home page http://localhost:8080/ , enters the user name and email information, and the page jumps to: http://localhost:8080/save , the page is as follows:

4.3.3.1.6)@RequestAttribute

@RequestAttribute: Obtain the attributes saved in the request domain [the attribute set in the request domain can be used to obtain the data of the current request when the page is forwarded]

Create a new RequestController.java with the following code:

@Controller
public class RequestController {
​
    // request域中保存属性
    @GetMapping("/goto")
    public String goToPage(HttpServletRequest request){
        request.setAttribute("msg","成功了...");
        request.setAttribute("code",200);
        //转发到  /success请求
        return "forward:/success";
    }
​
    @ResponseBody
    @GetMapping("/success")
    public Map success(@RequestAttribute(value = "msg",required = false) String msg,
                       @RequestAttribute(value = "code",required = false)Integer code,
                       HttpServletRequest request){
        Object msg1 = request.getAttribute("msg");
        Map<String,Object> map = new HashMap<>();
        // 方式一:@RequestAttribute获取request中的属性值
        map.put("@RequestAttribute获取request",msg1);
        // 方式二:原生HttpServletRequest获取request中的属性值
        map.put("原生HttpServletRequest获取request",msg);
        return map;
    }
}

Test: The project starts, and the browser accesses the jump page: http://localhost:8080/goto , the page is as follows:

 4.3.3.1.7)@MatrixVariable

@MatrixVariable: matrix variable

Get the variable value in the request:

  1. @RequestParam:/cars/{path}?xxx=xxx&aaa=ccc;

  2. Matrix variable [; means matrix variable]: /cars/sell;low=34;brand=byd,audi,yd

Matrix variables need to be manually enabled in SpringBoot

According to the specification of RFC3986, matrix variables should be bound in path variables

If there are multiple matrix variables, English symbols should be used; for separation

If a matrix variable has multiple values, English symbols should be used for separation, or multiple repeated keys can be named

Manually enable matrix variables

  1. Method 1: Implement the WebMvcConfigurer interface, rewrite the configurePathMatch method, and set RemoveSemicolonContent to false; modify the configuration class WebConfig.java, the code is as follows:

@Configuration(proxyBeanMethods = false)
public class WebConfig implements WebMvcConfigurer {
​
    // 手动开启矩阵变量方式一:实现WebMvcConfigurer接口,重写configurePathMatch方法,设置RemoveSemicolonContent为false
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        // 不移除;后面的内容。矩阵变量功能就可以生效【手动开启矩阵变量】
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}
  1. Method 2: Rewrite the WebMvcConfigurer method to customize the functions of SpringMVC, set RemoveSemicolonContent to false, and modify the configuration class WebConfig.java, the code is as follows:

@Configuration(proxyBeanMethods = false)
public class WebConfig {
    // 手动开启矩阵变量方式二:重写WebMvcConfigurer方法定制化SpringMVC的功能,设置RemoveSemicolonContent为false
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                // 不移除;后面的内容。矩阵变量功能就可以生效
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
        };
    }
}    

Modify ParameterTestController.java, the code is as follows:

    @GetMapping("/cars/{path}")
    public Map carsSell(@MatrixVariable("low") Integer low,
                        @MatrixVariable("brand") List<String> brand,
                        @PathVariable("path") String path) {
        Map<String, Object> map = new HashMap<>();
        map.put("矩阵变量中的变量low", low);
        map.put("矩阵变量中的变量brand", brand);
        map.put("路径中变量path", path);
        return map;
    }

Modify the home page index.html, the code is as follows:

测试基本注解:
<ul>
    <a href="car/3/owner/lisi?age=18&inters=basketball&inters=game">car/{id}/owner/{username}</a>
    <li>@PathVariable(路径变量)</li>
    <li>@RequestHeader(获取请求头)</li>
    <li>@RequestParam(获取请求参数)</li>
    <li>@CookieValue(获取cookie值)</li>
    <li>@RequestBody(获取请求体[POST])</li>
    <li>@RequestAttribute(获取request域属性)</li>
    <li>@MatrixVariable(矩阵变量)</li>
</ul>
<br/>
<a href="/cars/sell;low=34;brand=byd,audi,yd">@MatrixVariable(矩阵变量)</a><br/>
<a href="/cars/sell;low=34;brand=byd;brand=audi;brand=yd">@MatrixVariable(矩阵变量)</a><br/>

Test: The project is started, the browser visits the home page: http://localhost:8080/ , click the hyperlink "1) @MatrixVariable (matrix variable)", the page jumps to: http://localhost:8080/cars/sell; low=34;brand=byd,audi,yd , click the hyperlink "2) @MatrixVariable (matrix variable)", the page jumps to: http://localhost:8080/cars/sell;low=34;brand=byd ;brand=audi;brand=yd , the page looks like this:

 If there are multiple access requests, how do you determine which request corresponds to the parameters in the request? [pathVar is used to distinguish different requests]

Modify ParameterTestController.java, the code is as follows:

    @GetMapping("/boss/{bossId}/{empId}")
    public Map boss(@MatrixVariable(value = "age", pathVar = "bossId") Integer bossAge,
                    @MatrixVariable(value = "age", pathVar = "empId") Integer empAge) {
        Map<String, Object> map = new HashMap<>();
        map.put("bossAge", bossAge);
        map.put("empAge", empAge);
        return map;
    }

Modify the home page index.html, the code is as follows:

<a href="/cars/sell;low=34;brand=byd,audi,yd">1)@MatrixVariable(矩阵变量)</a><br/>
<a href="/cars/sell;low=34;brand=byd;brand=audi;brand=yd">2)@MatrixVariable(矩阵变量)</a><br/>
<a href="/boss/1;age=20/2;age=10">@MatrixVariable(矩阵变量)/boss/{bossId}/{empId}</a><br/>

Test: The project starts, the browser visits the home page: http://localhost:8080/ , clicks the hyperlink "@MatrixVariable (matrix variable)/boss/{bossId}/{empId}", the page jumps to: http:// localhost:8080/ localhost:8080/boss/1;age=20/2;age=10 , the page is as follows:

 

4.3.3.2)Servlet API

WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId

Some parameters above ServletRequestMethodArgumentResolver

@Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> paramType = parameter.getParameterType();
        return (WebRequest.class.isAssignableFrom(paramType) ||
                ServletRequest.class.isAssignableFrom(paramType) ||
                MultipartRequest.class.isAssignableFrom(paramType) ||
                HttpSession.class.isAssignableFrom(paramType) ||
                (pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) ||
                Principal.class.isAssignableFrom(paramType) ||
                InputStream.class.isAssignableFrom(paramType) ||
                Reader.class.isAssignableFrom(paramType) ||
                HttpMethod.class == paramType ||
                Locale.class == paramType ||
                TimeZone.class == paramType ||
                ZoneId.class == paramType);
    }

4.3.3.3) Complex parameters

Map , Model (data in map and model will be placed in the request field request.setAttribute), Errors/BindingResult, RedirectAttributes (redirection carries data) , ServletResponse (response) , SessionStatus, UriComponentsBuilder, ServletUriComponentsBuilder

Modify RequestController.java, the code is as follows:

    @ResponseBody
    @GetMapping("/success")
    public Map success(@RequestAttribute(value = "msg", required = false) String msg,
                       @RequestAttribute(value = "code", required = false) Integer code,
                       HttpServletRequest request) {
        Object msg1 = request.getAttribute("msg");
        Map<String, Object> map = new HashMap<>();
        // 方式一:@RequestAttribute获取request中的属性值
        map.put("@RequestAttribute获取request", msg1);
        // 方式二:原生HttpServletRequest获取request中的属性值
        map.put("原生HttpServletRequest获取request", msg);
​
        Object hello = request.getAttribute("hello");
        Object world = request.getAttribute("world");
        Object message = request.getAttribute("message");
        map.put("hello",hello);
        map.put("world",world);
        map.put("message",message);
        return map;
    }
​
    @GetMapping("/params")
    public String testParam(Map<String, Object> map,
                            Model model,
                            HttpServletRequest request,
                            HttpServletResponse response) {
        map.put("hello", "world666");
        model.addAttribute("world", "hello666");
        request.setAttribute("message", "HelloWorld");
​
        Cookie cookie = new Cookie("c1", "v1");
        response.addCookie(cookie);
        return "forward:/success";
    }

Test: The project starts, and the browser visits the homepage: http://localhost:8080/params , the page is as follows:

 Map and Model type parameters will return mavContainer.getModel(); ---> BindingAwareModelMap is a Model and a Map

The source code of ModelAndViewContainer.java is as follows:

public class ModelAndViewContainer {
    private boolean ignoreDefaultModelOnRedirect = false;
    @Nullable
    private Object view;
    private final ModelMap defaultModel = new BindingAwareModelMap();
    @Nullable
    private ModelMap redirectModel;
    private boolean redirectModelScenario = false;
    ...        
    }

mavContainer .getModel(); get the value

    public ModelMap getModel() {
        if (this.useDefaultModel()) {
            return this.defaultModel;
        } else {
            if (this.redirectModel == null) {
                this.redirectModel = new ModelMap();
            }
            return this.redirectModel;
        }
    }

As shown below:

 4.3.3.4) Custom object parameters

Automatic type conversion and formatting are possible, and cascade encapsulation is possible.

Create a new Bean object Person.java, the code is as follows:

@Data
public class Person {
    private String userName;
    private Integer age;
    private Date birth;
    private Pet pet;
}

Create a new Bean object Pet.java, the code is as follows:

@Data
public class Pet {
    private String name;
    private Integer age;
}

Modify ParameterTestController.java, the code is as follows:

    @PostMapping("/saveuser")
    public Person saveuser(Person person) {
        return person;
    }

Modify the home page index.html, the code is as follows:

测试封装POJO;
<form action="/saveuser" method="post">
    姓名: <input name="userName" value="zhangsan"/> <br/>
    年龄: <input name="age" value="18"/> <br/>
    生日: <input name="birth" value="2019/12/10"/> <br/>
    <!--级联属性-->
    宠物姓名:<input name="pet.name" value="阿猫"/><br/>
    宠物年龄:<input name="pet.age" value="5"/>
    <input type="submit" value="保存"/>
</form>

Test: The project starts, the browser visits the home page: http://localhost:8080/ , clicks the "Save" button, and the page jumps to: http://localhost:8080/saveuser ; the page is as follows:

 Customize Converter without cascading properties

Modify the home page index.html, the code is as follows: [Clicking the "Save" button directly will report error 400]

测试封装POJO;
<form action="/saveuser" method="post">
    姓名: <input name="userName" value="zhangsan"/> <br/>
    年龄: <input name="age" value="18"/> <br/>
    生日: <input name="birth" value="2019/12/10"/> <br/>
    <!--自定义Converter-->
    宠物: <input name="pet" value="啊猫,3"/>
    <input type="submit" value="保存"/>
</form>

Customize Converter, modify the configuration file WebConfig.java, the code is as follows:

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            // 自定义对象参数 --》自定义Converter,不使用级联属性
            @Override
            public void addFormatters(FormatterRegistry registry) {
                registry.addConverter(new Converter<String, Pet>() {
                    @Override
                    public Pet convert(String source) {
                        // 啊猫,3
                        if (!StringUtils.isEmpty(source)) {
                            Pet pet = new Pet();
                            String[] split = source.split(",");
                            pet.setName(split[0]);
                            pet.setAge(Integer.parseInt(split[1]));
                            return pet;
                        }
                        return null;
                    }
                });
            }
        };
    }

Test: The project starts, the browser visits the home page: http://localhost:8080/ , clicks the "Save" button, and the page jumps to: http://localhost:8080/saveuser ; the page is as follows:

 

Guess you like

Origin blog.csdn.net/jianghao233/article/details/125125005