如何通过SpringMVC获取前端请求数据并应用三个作用域?

摘要:获取请求数据 使用原生的Servlet API获取请求数据处理注册请求 @PostMapping("registeruser") public String register(
获取请求数据 使用原生的Servlet API获取请求数据 // 处理注册请求 @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的作用:将请求参数与方法上的形参映射 @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属性:给参数设置默认值,如果前端没传这个参数,则会使用默认值。 @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。 @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中的。 @PostMapping("/register/user/4") public String register4(User user) { // 这种方式要求请求参数的名称必须与User类的属性名称一致,Spring MVC会自动将请求参数绑定到User对象的属性上 return "success"; } RequestHeader注解 作用:将请求头信息映射到方法的形参上。 和@RequestParam注解功能相似。 对于RequestHeader注解来说,也有三个属性:value、required、defaultValue,和RequestParam一样。 @PostMapping("/register/user/4") public String register4(User user, @RequestHeader(value = "Referer",required = false,defaultValue = "") String referer) { return "success"; } CookieValue注解 作用:将提交的cookie数据映射到形参上。 同样有三个属性:value、required、defaultValue。 @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请求乱码 解决办法: // 这行代码必须在获取参数的代码之前执行,不能写在下面 request.setCharacterEncoding("UTF-8"); String username = request.getParameter("username"); 在tomcat10中,已经自动帮我们解决了乱码问题。 在tomcat9和以前的版本,会出现乱码问题,需要手动解决。 第一种方案:自己编写一个过滤器!过滤器Filter在Servlet执行之前执行。 编写过滤器类 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); } } 在web.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中配置如下: <!-- 使用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域对象中共享数据有以下几种方式: 使用原生的Servlet API方式 使用Model接口 使用Map接口 使用ModelMap类 使用ModelAndView类 使用原生的Servlet API方式 controller中的代码 @RequestMapping("/testServletAPI") public String testServletAPI(HttpServletRequest request) { // 将共享数据存入request域对象中 request.setAttribute("testRequestScope", "hello,servletAPI"); // 这个跳转视图默认是forward方式,request域对象中的数据可以共享到目标资源中 return "ok"; } html代码用来取数据 <body> <div th:text="${testRequestScope}"></div> </body> 使用Model接口 不使用Servlet API,所以单元测试时比较方便。 @RequestMapping("/testModel") public String testModel(Model model) { // 将共享数据存入model中 model.addAttribute("testRequestScope", "hello,Model"); return "ok"; } 使用Map接口 @RequestMapping("/testMap") public String testMap(Map<String, Object> map) { // 将共享数据存入map中 map.put("testRequestScope", "hello,Map"); return "ok"; } 使用ModelMap类 @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域数据共享。 @RequestMapping("/testModelAndView") public ModelAndView testModelAndView(ModelAndView modelAndView) { // 将共享数据存入modelAndView中 modelAndView.addObject("testRequestScope", "hello,ModelAndView"); // 设置视图名称 modelAndView.setViewName("ok"); return modelAndView; } 这里需要注意: 方法返回值类型不是String.而是ModelAndView对象。 ModelAndView不是出现在参数位置,而是在方法体中new出来的 需要调用addObject向域中存储数据 需要调用setViewName设置视图名称。 session域对象 使用原生Servlet API @RequestMapping("/testSessionScope") public String test(HttpSession session) { // 将共享数据存入session域对象中 session.setAttribute("testSessionScope", "hello,Session"); return "ok"; } html代码用来取数据 <body> <div th:text="${session.testSessionScope}"></div> </body> 使用SessionAttributes注解 使用SessionAttributes注解标注controller @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域对象 @RequestMapping("/testApplicationScope") public String test(HttpServletRequest request) { // 将共享数据存入application域对象中 ServletContext servletContext = request.getServletContext(); servletContext.setAttribute("testApplicationScope", "hello,Application"); return "ok"; } html代码。用来取数据 <body> <div th:text="${application.testApplicationScope}"></div> </body>