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>
相关推荐
BUG指挥官13 小时前
Sa-Token和Spring Security对比
java·后端·spring
geminigoth13 小时前
Spring AI Alibaba 入门开发一(备份)
java·人工智能·spring
xbgRS16 小时前
spring整合mybaits
java·spring·mybatis
ruleslol16 小时前
静态依赖注入 VS 动态依赖查询
spring
墨雨晨曦8818 小时前
Spring AI总结
java·人工智能·spring
用户31268748772020 小时前
Spring Boot 异常处理到底怎么玩的?从 DispatcherServlet 到全局兜底的全链路拆解
spring
不才不才不不才21 小时前
Spring 源码系列(17): HandlerMapping 与 HandlerAdapter 两大体系
java·后端·spring
(轻舟已过万重山)21 小时前
第40章 Spring AI 实战:企业级 AI 应用架构
人工智能·spring·架构
堕落年代2 天前
Ollama CPU 推理大提示词优化实测报告(细致化数据版)
java·后端·spring
cfm_29142 天前
基于OAuth2.0实现微服务SSO单点登录
后端·spring·微服务·架构