springMVC-获取前端请求的数据与三个作用域

获取请求数据

使用原生的Servlet API获取请求数据

java 复制代码
// 处理注册请求
@PostMapping("/register/user")
public String register(HttpServletRequest request, HttpSession session, HttpServletResponse resp) {
    // 获取请求参数
    // HttpServletRequest\HttpSession\HttpServletResponse 都属于Servlet API,Spring MVC会自动将它们注入到方法参数中
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    return "success";
}

@RequestParam注解

@RequestParam的作用:将请求参数与方法上的形参映射

java 复制代码
@PostMapping("/register/user/2")
public String register2(
        // @RequestParam注解用于将请求参数绑定到方法参数上,value属性指定请求参数的名称,参数名可以和请求参数名不同
        // 可以自动将请求参数转换为方法参数的类型,例如将字符串转换为整数、日期等
        @RequestParam("username") String username,
        @RequestParam("password") String password) {

    return "success";
}

@RequestParam的required和defaultValue属性

required属性:设置该参数是否是必须的。默认true,默认参数是必须的,如果前端没有提交这个参数,则报错。如果设置为false。则不会报错。

defaultValue属性:给参数设置默认值,如果前端没传这个参数,则会使用默认值。

java 复制代码
@PostMapping("/register/user/2")
public String register2(
        // @RequestParam注解用于将请求参数绑定到方法参数上,value属性指定请求参数的名称,参数名可以和请求参数名不同
        // 可以自动将请求参数转换为方法参数的类型,例如将字符串转换为整数、日期等
        @RequestParam("username") String username,
        @RequestParam("password") String password,
        @RequestParam(value = "age",required = false,defaultValue = "20") Integer age) {
    return "success";
}

依靠控制器方法上的形参名接收

如果请求的参数名和控制器方法上的形参名保持一致。那么 @RequestParam注解可以省略。

如果没对应上,则值为null。

java 复制代码
@PostMapping("/register/user/3")
public String register3(String username, String password) {
    // 这种方式要求请求参数的名称必须与方法参数的名称一致,Spring MVC会自动将请求参数绑定到方法参数上
    return "success";
}

使用POJO类/JavaBean接收参数

要求:POJO类/JavaBean的属性名必须和请求参数的参数名保持一致。

底层原理使用反射机制。并且调用JavaBean的set方法,set方法的方法名是关键,springMVC是通过set方法的方法名将对应的参数注入到JavaBean中的。

java 复制代码
@PostMapping("/register/user/4")
public String register4(User user) {
    // 这种方式要求请求参数的名称必须与User类的属性名称一致,Spring MVC会自动将请求参数绑定到User对象的属性上
    return "success";
}

RequestHeader注解

作用:将请求头信息映射到方法的形参上。

和@RequestParam注解功能相似。

对于RequestHeader注解来说,也有三个属性:value、required、defaultValue,和RequestParam一样。

java 复制代码
@PostMapping("/register/user/4")
public String register4(User user, @RequestHeader(value = "Referer",required = false,defaultValue = "") String referer) {
    return "success";
}

CookieValue注解

作用:将提交的cookie数据映射到形参上。

同样有三个属性:value、required、defaultValue。

java 复制代码
@PostMapping("/register/user/4")
public String register4(User user,
                        @RequestHeader(value = "Referer",required = false,defaultValue = "") String referer,
                        @CookieValue(value = "JSESSIONID",required = false,defaultValue = "") String jsessionId) {
    // 这种方式要求请求参数的名称必须与User对象的属性名称一致,Spring MVC会自动将请求参数绑定到User对象的属性上
    // @RequestHeader注解用于将请求头信息绑定到方法参数上,value属性指定请求头的名称
    // @CookieValue注解用于将Cookie信息绑定到方法参数上,value属性指定Cookie的名称
    return "success";
}

请求的中文乱码问题

get请求乱码

解决方法:对URI进行编码设置,在Tomcat的配置CATALINA_HOME/conf/server.xml文件中:设置Connector 标签,添加 URIEncoding="UTF-8"

tomcat9和10 不会乱码。因为他们已经默认设置URI编码为UTF-8.

对于tomcat8.默认是ISO。所以需要设置为UTF-8。

post请求乱码

解决办法:

java 复制代码
// 这行代码必须在获取参数的代码之前执行,不能写在下面
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");

在tomcat10中,已经自动帮我们解决了乱码问题。

在tomcat9和以前的版本,会出现乱码问题,需要手动解决。

第一种方案:自己编写一个过滤器!过滤器Filter在Servlet执行之前执行。

  1. 编写过滤器类

    java 复制代码
    public class CharacterEncodingFilter implements Filter {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            // 设置请求和响应的字符编码为UTF-8,解决中文乱码问题
            servletRequest.setCharacterEncoding("UTF-8");
            servletResponse.setContentType("text/html;charset=UTF-8");
            // 将请求和响应对象传递给下一个过滤器或目标资源
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }
    1. 在web.xml配置过滤器

      xml 复制代码
      <!--    设置字符编码过滤器,解决post请求中文乱码问题-->
          <filter>
              <filter-name>characterEncodingFilter</filter-name>
              <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
          </filter>
          <filter-mapping>
              <filter-name>characterEncodingFilter</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>

第二种方案:使用内置过滤器解决,在web.xml中配置如下:

xml 复制代码
<!--    使用springmvc提供的字符编码过滤器,解决post请求中文乱码问题-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--        设置字符集为UTF-8-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
<!--        请求体和响应体都使用UTF-8字符集-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

三个域对象

请求域:request(作用于一个请求中)

会话域:session(作用于一个会话中,浏览器打开到浏览器关闭期间,保存用户登录状态)

应用域:application(作用于一个应用,服务器启动到服务器关闭期间,记录网站在线人数)

request域对象

在springMVC中,在request域对象中共享数据有以下几种方式:

  1. 使用原生的Servlet API方式
  2. 使用Model接口
  3. 使用Map接口
  4. 使用ModelMap类
  5. 使用ModelAndView类

使用原生的Servlet API方式

controller中的代码

java 复制代码
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request) {
    // 将共享数据存入request域对象中
    request.setAttribute("testRequestScope", "hello,servletAPI");
    // 这个跳转视图默认是forward方式,request域对象中的数据可以共享到目标资源中
    return "ok";
}

html代码用来取数据

html 复制代码
<body>
<div th:text="${testRequestScope}"></div>
</body>

使用Model接口

不使用Servlet API,所以单元测试时比较方便。

java 复制代码
@RequestMapping("/testModel")
public String testModel(Model model) {
    // 将共享数据存入model中
    model.addAttribute("testRequestScope", "hello,Model");
    return "ok";
}

使用Map接口

java 复制代码
@RequestMapping("/testMap")
public String testMap(Map<String, Object> map) {
    // 将共享数据存入map中
    map.put("testRequestScope", "hello,Map");
    return "ok";
}

使用ModelMap类

java 复制代码
@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap) {
    // 将共享数据存入modelMap中
    modelMap.addAttribute("testRequestScope", "hello,ModelMap");
    return "ok";
}

Model、Map、ModelMap三者之间的关系

表面上这三者是不同的类和接口,实际上底层都使用了同一个对象BindingAwareModelMap,。

这三者的方法表面上是返回了逻辑视图名称,是一个字符串,在底层实际上都是返回了ModelAndView对象。

使用ModelAndView类

ModelAndView类的实例封装了Model和View。也就是说它既封装了处理业务之后的数据,还封装跳转到哪个视图,使用它可以完成request域数据共享。

java 复制代码
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(ModelAndView modelAndView) {
    // 将共享数据存入modelAndView中
    modelAndView.addObject("testRequestScope", "hello,ModelAndView");
    // 设置视图名称
    modelAndView.setViewName("ok");
    return modelAndView;
}

这里需要注意:

  1. 方法返回值类型不是String.而是ModelAndView对象。
  2. ModelAndView不是出现在参数位置,而是在方法体中new出来的
  3. 需要调用addObject向域中存储数据
  4. 需要调用setViewName设置视图名称。

session域对象

使用原生Servlet API

java 复制代码
@RequestMapping("/testSessionScope")
public String test(HttpSession session) {
    // 将共享数据存入session域对象中
    session.setAttribute("testSessionScope", "hello,Session");
    return "ok";
}

html代码用来取数据

html 复制代码
<body>
<div th:text="${session.testSessionScope}"></div>
</body>

使用SessionAttributes注解

使用SessionAttributes注解标注controller

java 复制代码
@Controller
// @SessionAttributes注解:将指定的属性存储到session域对象中
// 表示 将modelMap中key为"x"和"y"的属性存储到session域对象中
@SessionAttributes(value = {"x", "y"})
public class SessionScopeTestController {
    
    @RequestMapping("/testSessionAttribute")
    public String testSessionAttribute(ModelMap modelMap) {
        // 将共享数据存入session域对象中
        modelMap.addAttribute("x", "hello,x");
        modelMap.addAttribute("y", "hello,y");
        return "ok";
    }
}

application域对象

java 复制代码
@RequestMapping("/testApplicationScope")
public String test(HttpServletRequest request) {
    // 将共享数据存入application域对象中
    ServletContext servletContext = request.getServletContext();
    servletContext.setAttribute("testApplicationScope", "hello,Application");
    return "ok";
}

html代码。用来取数据

html 复制代码
<body>
<div th:text="${application.testApplicationScope}"></div>
</body>
相关推荐
莫寒清2 小时前
Spring MVC:@PathVariable 注解详解
java·spring·mvc
-大头.3 小时前
从 0 开始理解 Spring 的核心思想 —— IoC 和 DI(1)
spring
莫寒清7 小时前
Apache Tika
java·人工智能·spring·apache·知识图谱
工业甲酰苯胺8 小时前
一文学习 Spring AOP 源码全过程
java·学习·spring
昱宸星光9 小时前
Xnio源码分析
java·jvm·spring
玄〤10 小时前
个人博客网站搭建day6--Spring Boot自定义RedisTemplate配置:优化序列化与Java8时间类型支持
java·spring boot·redis·后端·spring
知我Deja_Vu10 小时前
@Transactional 与 @Transactional(rollbackFor = Exception.class) 的区别详解
java·spring
三水不滴10 小时前
利用SpringCloud Gateway 重试 + 降级解决第三方接口频繁超时问题,提升性能
经验分享·笔记·后端·spring·spring cloud·gateway
葵续浅笑1 天前
从Spring拦截器到Filter过滤器:一次报文修改加解密的填坑经验
java·后端·spring