SpringMVC学习笔记

简单说两句

作者:后端小知识

CSDN个人主页后端小知识

🔎GZH后端小知识

🎉欢迎关注🔎点赞👍收藏⭐️留言📝

SpringMVC

说明下【本文是在网上听课做的笔记,代码是自己敲的,有些文字是复制的老师发的】

SpringMVC概述

使用SpringMVC替换Servlet

Servlet的问题:

1、需要判断调用哪个方法。(逻辑需要自己编写)

2、需要获得request的数据,并且需要手动封装,还要进行类型转换。

3、跳转和转发数据的代码太繁琐。

4、通过ajax请求的对象,需要通过fastjson进行转换,并使用相应对象的输出流写出。

以上问题SpringMVC都给出了解决方案。

1、添加依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>4.3.18.RELEASE</version>
</dependency>

2、在web.xml中配置前端控制器

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!--
     前端控制器
  -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springMVC-Servlet.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!--
      /表示拦截了除了jsp之外所有的请求
    -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

3、编写SpringMVC的配置文件(结构和Spring配置文件一致)

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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">
    <!--
          映射器
      -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
    <!--
           适配器
       -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!--
         视图解析器
     -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/" />
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--
            配置Controller
        -->
<!--    <bean id="/user" class="com.woniu.controller.UserController"></bean>-->
        <bean id="/user" class="cn.cqie.controller.UserController"/>
</beans>

4、添加Controller

package cn.cqie.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
public class UserController implements Controller {
    @Override
    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
        System.out.println("UserController.handleRequest");

        return null;
    }
}

5、通过浏览器访问Controller

image-20211123213830829

image-20211123214002728

SpringMVC的工作机制

image-20211124185840300

DispatcherServlet

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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">
    <!--
        映射器
        BeanNameUrlHandlerMapping
        在浏览器中发送/user
        通过/user在Spring容器中找到id对应的实例

        SimpleUrlHandlerMapping
        声明一个映射关系
        Properties
    -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/user">userController</prop>
            </props>
        </property>
    </bean>
    <!--
        适配器
        SimpleControllerHandlerAdapter
        可以执行实现了Controller接口的控制器

        HttpRequestHandlerAdapter
        可以执行实现了HttpRequestHandler接口的控制器
    -->
    <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" ></bean>
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" ></bean>
    <!--
        视图解析器
        prefix 从webapp根目录指定
        suffix 是后缀
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!--
        配置Controller
    -->
    <bean id="userController" class="cn.cqie.controller.UserController"></bean>
</beans>

Controller的实现

使用注解配置Controller

package cn.cqie.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController2  {

    @RequestMapping("userSave")
    public ModelAndView save(){
        System.out.println("UserController2.save");
        return new ModelAndView("index");
    }
}
<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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="cn.cqie"/>
    <mvc:annotation-driven></mvc:annotation-driven> <!--这个可以替换掉下面的两个 bean,甚至更多 -->
<!--    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>-->
<!--    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>-->
    <!--
         视图解析器
     -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/" />
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--
            配置Controller
        -->
    <!--    <bean id="/user" class="com.woniu.controller.UserController"></bean>-->
    <bean id="userController" class="cn.cqie.controller.UserController"/>
</beans>

ModelAndView类

package cn.cqie.controller;

import cn.cqie.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.ArrayList;
import java.util.List;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController2  {
//    @RequestMapping("testList")  就是在浏览器输入 testList  和以前的servlet一样
    @RequestMapping("testList")
    public ModelAndView list(){
        System.out.println("UserController2.save");
        List<User> list =new ArrayList<>();
        list.add(new User("yx",26));
        list.add(new User("wls",20));
        list.add(new User("tcx",20));
        //                                          /list.jsp
        ModelAndView ma = new ModelAndView("list");

        //request.setAttribute();
        ma.addObject("msg","66666");

        return ma;
    }

    @RequestMapping("testList2")
    public ModelAndView list2(){
        System.out.println("UserController2.save");
        List<User> list =new ArrayList<>();
        list.add(new User("yx",26));
        list.add(new User("wls",20));
        list.add(new User("tcx",20));
        ModelAndView ma = new ModelAndView("list2");
        ma.addObject("msg",list);
        return ma;
    }

    @RequestMapping("testList3")
    public ModelAndView list3(){
        System.out.println("UserController2.save");
        List<User> list =new ArrayList<>();
        list.add(new User("yx",26));
        list.add(new User("wls",20));
        list.add(new User("tcx",20));
        ModelAndView ma = new ModelAndView("list2");
        //request.setAttribute(); 名字默认为类型与泛型的组合 userList
        ma.addObject(list);
        return ma;
    }


    @RequestMapping("testList4")
    public String list4(Model model){
        System.out.println("UserController2.save");
        List<User> list =new ArrayList<>();
        list.add(new User("yx",26));
        list.add(new User("wls",20));
        list.add(new User("tcx",20));

        model.addAttribute(list);
        return "list2"; // /list.jsp
    }


    @RequestMapping("testList5")
    public String list5(Model model){
            //重定向
        return "redirect:list.jsp";
    }
}

相关的jsp页面

list.jsp

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2021/11/24
  Time: 21:08
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${msg}
</body>
</html>

list2.jsp

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2021/11/24
  Time: 21:15
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <ul>
        <c:forEach items="${userList}" var="user">
            <li>${user.name}</li>
        </c:forEach>
    </ul>
</body>
</html>

jstl需要导入的依赖

<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

视图解析器概述

将Controller的返回值进行解析,到浏览器。

在SpringMVC中也有很多视图解析器

image-20211125151828208

这时通过视图解析器解析handler返回的值(逻辑视图,转发数据)

InternalResourceViewResolver会将逻辑视图与prefix和suffix组合成物理视图名,
如果逻辑视图返回值中包含redirect:,则进行重定向操作,如果是forward:或者没有前缀,则转发操作。

编写一个视图

package cn.cqie.controller.a_view;

import org.springframework.web.servlet.View;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/25 15:02
 */
public class MyView implements View {
    @Override
    public String getContentType() {
        return null;
    }

    @Override
    public void render(Map<String, ?> map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //map就是model中添加的数据
        for (Map.Entry<String, ?> entry : map.entrySet()) {
            httpServletRequest.setAttribute(entry.getKey(), entry.getValue());
            System.out.println("  "+entry.getKey()+" :  " +entry.getValue());
        }
        System.out.println("MyView.render");
        httpServletRequest.getRequestDispatcher("abc.jsp").forward(httpServletRequest, httpServletResponse);
    }
}
<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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="cn.cqie.controller.a_view"/>
    <mvc:annotation-driven/>
    <!--
      BeanNameViewResolver是当前项目的中视图解析器
      MyView声明了跳转的方式和数据转发
  -->
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"></bean>
    <bean id="myView" class="cn.cqie.controller.a_view.MyView"></bean>


</beans>
package cn.cqie.controller.a_view;

import cn.cqie.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController {
   @RequestMapping("save")
    public String save(Model model){
       System.out.println("UserController.save");
       User xy = new User("xy", 30);
       model.addAttribute("a",xy);
       return "myView";
    }
}

请求映射

1、RequestMapping可以声明在类和方法上

RequestMapping

可以声明在类上,如果要访问方法,需要将类的RequestMapping的值与方法上的RequestMapping的值组合访问。

http://localhost:8080/项目名称/类上注解/方法上注解

为了防止直接通过浏览器访问jsp页面,将所有页面放到WEB-INF下。只能通过控制器跳转。在视图解析器中的前缀添加WEB-INF。

2、可以根据不同的请求方式来控制哪种请求可以访问

//method = RequestMethod.POST只有页面通过post传参,才可以访问到这个方法
@RequestMapping(value = "save",method = RequestMethod.POST)
public String save(){
    System.out.println("UserController.save");
    return "b";
}

浏览器地址栏访问 都是Get请求

3、在RequestMapping中添加params

//页面需要传递params中声明的参数,且值必须相等,这时才可以访问该方法
@RequestMapping(value = "login",params = {"uname=admin","pwd=123"})
public String login(String uname,String pwd){//这里要和 地址栏里面的参数一致才行  uname与uname对应  要对应
    System.out.println("UserController.save2");
    System.out.println(uname+"  "+pwd);
    return "b";
}

4、在RequestMapping中添加Headers

//可以在RequestMapping中声明headers,获得页面传递的请求头,从请求头中获得对应的信息,如果该信息相等,允许访问该方法
@RequestMapping(value = "list",headers = "host=localhost:8080")
//headers = "host=localhost:8080"只允许本机访问 。 【注意】 127.0.0.1 也不行必须 localhost
public String list(){
    System.out.println("UserController.list");
    return "b";
}

5、在RequestMapping中添加占位符

@RequestMapping(value = "login2/{uname}/{pwd}")
//需要使用注解
public String login2(@PathVariable("uname") String uname,@PathVariable("pwd") String pwd){
    System.out.println("UserController.save2");
    System.out.println(uname+"  "+pwd);
    return "b";
}

相应的配置文件

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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="cn.cqie.controller.b_request_mapping"/>
    <mvc:annotation-driven/>
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/WEB-INF/"></property>
       <property name="suffix" value=".jsp"></property>
   </bean>

</beans>

相关内容

image-20211125164930644

控制器方法入参

1、基本数据类型的自动转化

2、自动封装数据

package cn.cqie.controller.c_param;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import java.util.Arrays;
import java.util.List;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController {
    /**
     * 在SpringMVC的Controller中不再需要request.getParameter(),直接在方法的参数中声明即可,要求参数名与表单控件的name一致
     * 如果非要不一致,则需要添加注解@RequestParam("表单的name值")
     */
    @RequestMapping("save1")
    public String save1(String name,@RequestParam("pwd") String password){
        System.out.println("UserController.save1:"+name+" : "+password);
        return null;
    }

    //SpringMVC的Controller,可以对数据进行自动转换
    @RequestMapping("save2")
    public String save2(Integer age){
        System.out.println("UserController.save2: "+(2021-age));//输出年份

        return null;
    }

    //可以将表单的数据自动封装成对象(参数中指定的类型)
    @RequestMapping("save3")
    public String save3(User user){
        System.out.println("UserController.save3: "+user);
        return  null;
    }

    //复选框的值可以直接获得为字符串数据,整型数组,如果需要List<Integer>类型,则需要添加注解@RequestParam
//    @RequestMapping("save4")
//    public String save4(String[] ids){
//        System.out.println("UserController.save4: ");
//        System.out.println(Arrays.toString(ids));
//        return null;
//    }
    @RequestMapping("save4")
    public String save4(@RequestParam List<Integer> ids){
        System.out.println("UserController.save4: ");
        System.out.println(ids);
        return null;
    }
}
<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2021/11/25
  Time: 17:18
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>传递参数到Controller</h3>
    <form action="save1" method="post">
        <input name="name">
        <input name="pwd">
        <button>submit</button>
    </form>
    <hr>
    <h3>传递整型数据</h3>
    <form action="save2">
        <input name="age">
        <button>submit</button>
    </form>
    <hr>
    <h3>传递对象数据</h3>
    <form action="save3">
        <input name="name">
        <input name="age">
        <button>submit</button>
    </form>
    <hr>
    <h3>传递复选框数据</h3>
    <form action="save4">
        <input type="checkbox" name="ids" value="1">
        <input type="checkbox" name="ids" value="2">
        <input type="checkbox" name="ids" value="3">
        <button>submit</button>
    </form>
</body>
</html>

时间类型参数

SpringMVC中默认识别日期格式为yyyy/MM/dd

其他格式需要自己编写转换类

package cn.cqie.controller.d_convert;


import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/25 21:31
 */
public class DateConverter implements Converter<String, Date> {


    @Override
    public Date convert(String s) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        //还可以转换其他的,  比如 yyyy.MM.dd
        Date date = null;
        try {
            //将日期转换成字符串
            date= simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

将转换类配置到SpringMVC框架中

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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="cn.cqie.controller.d_convert"/>
    <mvc:annotation-driven conversion-service="conversionService"/>

   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/"/>
       <property name="suffix" value=".jsp"/>
   </bean>
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="cn.cqie.controller.d_convert.DateConverter"></bean>
            </set>
        </property>
    </bean>

</beans>

Controller里面的代码

package cn.cqie.controller.d_convert;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Date;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController {
    @RequestMapping("save1")
    public String save(Date date){
        System.out.println(date);
        return null;
    }
}

使用ServletAPI

HttpServletRequest

HttpServletResponse

HttpSession

ServletContext

HttpServletRequest,HttpServletResponse,HttpSession对象都可以从方法参数中获取

@RequestMapping("login")
public String login(HttpServletRequest req, HttpServletResponse resp, HttpSession session){
    System.out.println("HttpServletRequest"+req);
    System.out.println("HttpServletResponse"+resp);
    System.out.println("HttpSession"+session);
    return  null;
}

SpringMVC数据校验

正则表达式

​ 电话号码格式

​ 邮箱格式

​ 身份证格式等等

前端数据校验 (可以减轻服务器压力)

后端数据校验

1、添加依赖

<dependency>
  <groupId>org.hibernate.validator</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>6.0.20.Final</version>
</dependency>

2、定义校验规则

在封装类上定义校验规则,JSR303

package cn.cqie.controller.e_validator;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/24 21:04
 */
public class User implements Serializable {
    //null ""
//    在封装类上定义校验规则,JSR303
//    @NotBlank(message = "uname 不能为空!")
    @NotBlank(message = "name 不能为空")
    private String name;
    @NotNull(message = "age 不能为空")
    private Integer age;

    public User() {
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3、对需要校验的数据添加注解 @Validated

package cn.cqie.controller.e_validator;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController {

    @RequestMapping("save")
    public String save(@Validated User user, Errors errors, Model model){
        System.out.println("UserController.save");
        List<FieldError> fieldErrors = errors.getFieldErrors();
        for( FieldError fieldError:fieldErrors){
            System.out.println(fieldError.getField()+" "+fieldError.getDefaultMessage());
            model.addAttribute(fieldError.getField()+"msg",fieldError.getDefaultMessage());
        }
        if(fieldErrors.size()!=0) return "e";
        return null;
    }

}

4、在SpringMVC中注册校验器

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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="cn.cqie.controller.e_validator"/>
    <mvc:annotation-driven validator="validator" />

   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/"/>
       <property name="suffix" value=".jsp"/>
   </bean>
   <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
       <property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
   </bean>

</beans>

SpringMVC集成JSON

1、添加依赖

将对象或者集合转换成json

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>

2、在方法上添加注解@ResponseBody

package cn.cqie.controller.f_ajax;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.util.ArrayList;
import java.util.List;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController{
    @RequestMapping("list")
    @ResponseBody  //返回的对象交给jackson-databind进行转json并输出的操作
    public List<User> list(){
        System.out.println("UserController.list");
        List<User> list = new ArrayList<>();
        list.add(new User("yx",26));
        list.add(new User("tcx",20));

        return list;
    }

    @RequestMapping("save")
    @ResponseBody
    public  String save(@RequestBody User user){
        System.out.println("UserController.save");
        System.out.println(user);
        return "ok";
    }


}

要求页面传递数据格式为json

  • data:JSON.stringify(jsonStr)

在Controller方法上添加注解@RequestBody

  • public String save(@RequestBody User user)

因为默认按照键值对解析数据

  • contentType:“application/json”

可以使用POSTMAN进行测试

f.jsp

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2021/11/25
  Time: 17:18
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

</head>
<body>

    <form >
        <input type="text" name="name" id="name">
        <input type="text" name="age"  id="age">
        <button id="btnSave">btnSave</button>
    </form>
</body>

<script>
    $(document).ready(function (){
        $('#btnSave').click(function (){
            var jsonStr = {'name':$('#name').val(),'age':$('#age').val()}
            alert(JSON.stringify(jsonStr))
            $.ajax({
                url : "save",
                type : "post",
                contentType : "application/json",
                data:JSON.stringify(jsonStr),
                success:function(data){
                    alert(data);
                }
            });
        });
    });


</script>
</html>

image-20211127203124794

postMan工具的使用

image-20211128163125528

RESTful

RESTful概念

REST(英文:Representational State Transfer,简称REST)

表述性状态转移; 表现状态传输;

描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,Roy Fielding是 HTTP 规范的主要编写者之一。

在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。

特点

RESTFUL特点包括:

1、每一个URI代表1种资源;

2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;

3、通过操作资源的表现形式来操作资源;

4、资源的表现形式是XML或者HTML;

5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。

RESTful资源设计规则

URI
URI 表示资源,资源一般对应服务器端领域模型中的实体类。

URI规范
不用大写;
用中杠-不用下杠_;
参数列表要encode;
URI中的名词表示资源集合,使用复数形式。

资源集合 vs 单个资源
URI表示资源的两种方式:资源集合、单个资源。

资源集合:

/zoos //所有动物园
/zoos/1/animals //id为1的动物园中的所有动物

单个资源:

/zoos/1 //id为1的动物园
/zoos/1;2;3 //id为1,2,3的动物园

避免层级过深的URI
/在url中表达层级,用于按实体关联关系进行对象导航,一般根据id导航。

过深的导航容易导致url膨胀,不易维护,如 GET /zoos/1/areas/3/animals/4,尽量使用查询参数代替路径中的实体导航,如GET /animals?zoo=1&area=3;

对Composite资源的访问
服务器端的组合实体必须在uri中通过父实体的id导航访问。

组合实体不是first-class的实体,它的生命周期完全依赖父实体,无法独立存在,在实现上通常是对数据库表中某些列的抽象,不直接对应表,也无id。一个常见的例子是 User — Address,Address是对User表中zipCode/country/city三个字段的简单抽象,无法独立于User存在。必须通过User索引到Address:GET /user/1/addresses

  1. Request
    HTTP方法
    通过标准HTTP方法对资源CRUD:

GET:查询

GET /zoos
GET /zoos/1
GET /zoos/1/employees

POST:创建单个资源。POST一般向“资源集合”型uri发起

POST /animals //新增动物
POST /zoos/1/employees //为id为1的动物园雇佣员工

PUT:更新单个资源(全量),客户端提供完整的更新后的资源。与之对应的是 PATCH,PATCH 负责部分更新,客户端提供要更新的那些字段。PUT/PATCH一般向“单个资源”型uri发起

PUT /animals/1
PUT /zoos/1

DELETE:删除

DELETE /zoos/1/employees/2
DELETE /zoos/1/employees/2;4;5
DELETE /zoos/1/animals //删除id为1的动物园内的所有动物

Controller.java

package cn.cqie.controller.g_rest;

import cn.cqie.controller.f_ajax.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
@RequestMapping("users")
public class UserController {
    //get请求都是做查询操作
    //使用get请求http://localhost:8080/projectname/users
//    @RequestMapping(method = RequestMethod.GET)
    @GetMapping
    public String findAll(){
        System.out.println("UserController.findAll");
        return null;
    }
    //使用get请求http://localhost:8080/projectname/users/1
//    @RequestMapping(value = "{id}",method = RequestMethod.GET)
    @GetMapping(value = "{id}")
    public String findOne(@PathVariable Integer id){
        System.out.println("UserController.findOne: "+id);
        return null;
    }

    //post请求做新增操作
//    @RequestMapping(method = RequestMethod.POST)
    @PostMapping
    public String save(User user){
        System.out.println("UserController.save: "+user);
        return null;
    }

    //put请求做修改操作
//    @RequestMapping(method = RequestMethod.PUT)
    @PutMapping
    public String update(User user){
        System.out.println("UserController.update: "+user);
        return null;
    }

    //delete请求做删除操作
//    @RequestMapping(value = "{id}",method = RequestMethod.DELETE)
    @DeleteMapping(value = "{id}")
    public String delete(@PathVariable Integer id){
        System.out.println("UserController.delete: "+id);
        return null;
    }

}

g.jsp

<%--
  Created by IntelliJ IDEA.
  User: admin
  Date: 2021/11/25
  Time: 17:18
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

</head>
<body>

    <form action="users" method="post">
        <input type="text" name="name">
        <input type="text" name="age">
        <button id="btnSave">btnSave</button>
    </form>
    <hr>

    <form action="users" method="post">
        <!--
           如果要做put请求:
           1.需要添加隐藏域,声明put请求
           2.使用一个过滤器读取隐藏域信息,完成put请求
        -->
        <input type="hidden" name="_method" value="put">
        <input type="text" name="name">
        <input type="text" name="age">
        <button id="update">update</button>
    </form>
    <hr>

    <form action="users/9" method="post">
        <input type="hidden" name="_method" value="delete">
        <button id="delete">delete</button>
    </form>
</body>
</html>

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!--
   RESTful风格中过滤请求方式(put,delete)
 -->
  <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>


  <!--
     前端控制器
  -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:g_rest/springMVC-Servlet.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!--
      /表示拦截了除了jsp之外所有的请求
    -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

要在web.xml中添加过滤器

 <!--
   RESTful风格中过滤请求方式(put,delete)
 -->
  <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>

小技巧:@RequestMapping 可以替换 (get post put update delete)

//    @RequestMapping(method = RequestMethod.GET)
   @GetMapping

//    @RequestMapping(value = "{id}",method = RequestMethod.GET)
   @GetMapping(value = "{id}")

//    @RequestMapping(value = "{id}",method = RequestMethod.DELETE)
   @DeleteMapping(value = "{id}")

技巧:

@Controller 替换成 @RestController 可以直接返回 JSON数据

image-20211128183115496

处理静态资源

1)采用<mvc:default-servlet-handler />

在springMVC-servlet.xml中配置<mvc:default-servlet-handler />后,会在Spring MVC上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它会像一个检查员,对进入DispatcherServlet的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。

一般Web应用服务器默认的Servlet名称是"default",因此DefaultServletHttpRequestHandler可以找到它。如果你所有的Web应用服务器的默认Servlet名称不是"default",则需要通过default-servlet-name属性显示指定:

<mvc:default-servlet-handler default-servlet-name=“所使用的Web服务器默认使用的Servlet名称” />

2)采用<mvc:resources />

<mvc:default-servlet-handler />将静态资源的处理经由Spring MVC框架交回Web应用服务器处理。而<mvc:resources />更进一步,由Spring MVC框架自己处理静态资源,并添加一些有用的附加值功能。

首先,<mvc:resources />允许静态资源放在任何地方,如WEB-INF目录下、类路径下等,你甚至可以将JavaScript等静态文件打到JAR包中。通过location属性指定静态资源的位置,由于location属性是Resources类型,因此可以使用诸如"classpath:"等的资源前缀指定资源位置。传统Web容器的静态资源只能放在Web容器的根路径下,<mvc:resources />完全打破了这个限制。

其次,<mvc:resources />依据当前著名的Page Speed、YSlow等浏览器优化原则对静态资源提供优化。你可以通过cacheSeconds属性指定静态资源在浏览器端的缓存时间,一般可将该时间设置为一年,以充分利用浏览器端的缓存。在输出静态资源时,会根据配置设置好响应报文头的Expires 和 Cache-Control值。

在接收到静态资源的获取请求时,会检查请求头的Last-Modified值,如果静态资源没有发生变化,则直接返回303相应状态码,提示客户端使用浏览器缓存的数据,而非将静态资源的内容输出到客户端,以充分节省带宽,提高程序性能。

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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="cn.cqie.controller.g_rest"/>
    <mvc:annotation-driven  />
<!--    <mvc:default-servlet-handler></mvc:default-servlet-handler>-->
    <mvc:resources mapping="/img/**" location="/img/"></mvc:resources>
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/"/>
       <property name="suffix" value=".jsp"/>
   </bean>


</beans>

SpringMVC拦截器

1、编写一个拦截器

package cn.cqie.controller.h_interceptor;


import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/29 20:52
 */
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 在handle执行之前
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("LoginInterceptor.preHandle");
        //如果return true则放行
        return true;
    }

    /**
     *  在handle执行之后
     */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("LoginInterceptor.postHandle");
    }
//    在视图解析之后
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("LoginInterceptor.afterCompletion");
    }
}

2、配置拦截器

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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="cn.cqie.controller.h_interceptor"/>
    <mvc:annotation-driven  />
    <!--
       配置拦截器栈
   -->
    <mvc:interceptors>
        <!--
           配置拦截器
       -->
        <mvc:interceptor>
            <!--
               配置拦截规则
           -->
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/login"/>
            <!--
             拦截器对象
         -->
            <bean class="cn.cqie.controller.h_interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/"/>
       <property name="suffix" value=".jsp"/>
   </bean>


</beans>

controller.java

package cn.cqie.controller.h_interceptor;

import org.springframework.web.bind.annotation.*;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@RestController
public class UserController {
    @RequestMapping("list")
    public String list(){

        System.out.println("UserController.list");
        return null;
    }

    @RequestMapping("login")
    public String login(){
        System.out.println("UserController.login");
        return null;
    }
}

SpringMVC文件上传

1、表单

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="photo">
    <button>uploade</button>
</form>
</body>
</html>

2、添加依赖

  <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>

3、上传的操作

 package cn.cqie.controller.i_upload;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController {
    @RequestMapping("upload")
    public String upload(MultipartFile photo,HttpServletRequest request){
        //声明一个指定目录,用来存放上传的文件
        String realPath = request.getServletContext().getRealPath("/upload");
        System.out.println("UserController.upload: "+realPath);
        File dir = new File(realPath);
        if(!dir.exists()){
            dir.mkdirs();
        }
        //每个上传的文件名不重复UUID, 当前时间的毫秒数
        String filename = photo.getOriginalFilename(); //getName获取的是控件的名字
        String suffix = filename.substring(filename.lastIndexOf("."));
         filename = UUID.randomUUID() + suffix;
        System.out.println("UserController.upload: "+photo.getName());
        try {
            photo.transferTo(new File(dir,filename));
        } catch (IOException e) {
            e.printStackTrace();
        }


        return null;
    }

}

4、上传解析器

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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="cn.cqie.controller.i_upload"/>
    <mvc:annotation-driven  />

   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/"/>
       <property name="suffix" value=".jsp"/>
   </bean>

    <!--必须添加id,否则会导致上传不成功-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"></property>
        <property name="maxUploadSize" value="20000000"></property>

    </bean>


</beans>

SpringMVC异常处理

1、编写异常处理类

package cn.cqie.controller.j_exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/30 11:44
 */
@ControllerAdvice

public class ExceptionHandlerDemo implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        System.out.println("ExceptionHandlerDemo.resolveException: "+o.getClass());
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("message",e.getMessage());
        return modelAndView;
    }
}

2、编写异常展示页面

<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

</head>
<body>
    ${message}
</body>


</html>

3、编写Controller生成异常

package cn.cqie.controller.j_exception;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * Description:
 * Author: tiancx
 * Date: Created in 2021/11/23 21:30
 */
@Controller
public class UserController {
    @RequestMapping("test/{num}")
    public String test(@PathVariable("num") Integer num){
        System.out.println("UserController.test: "+10/num);

        return null;
    }
}

【都看到这了,点点赞点点关注呗,爱你们】😚😚

抽象工厂  引导关注

结语

谢谢你的阅读,由于作者水平有限,难免有不足之处,若读者发现问题,还请批评,在留言区留言或者私信告知,我一定会尽快修改的。若各位大佬有什么好的解法,或者有意义的解法都可以在评论区展示额,万分谢谢。
写作不易,望各位老板点点赞,加个关注!😘😘😘

💬

作者:后端小知识

CSDN个人主页后端小知识

🔎GZH后端小知识

🎉欢迎关注🔎点赞👍收藏⭐️留言📝

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小叮当撩编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值