数据绑定
springmvc作为web层技术,要接受页面传递过来的参数值,以下几种方式都是获取参数值
绑定servlet内置对象
@RequestMapping("show1") @ResponseStatus(HttpStatus.OK) //返回void 没有页面返回,给出响应状态为200 public void test1(HttpServletRequest request , HttpServletResponse response , HttpSession session){ //有了这些对象,之前怎么用,这里怎么用 System.out.println(request); System.out.println(response); System.out.println(session); }
@PathVariable
@RequestMapping(“show2/{id}/{name}”)
@PathVariable(“id”) 指定获取请求路径中的参数值
@RequestMapping("show2/{id}/{name}")//@PathVariable("xx")参数可以省略,建议指定获取 public String test2(@PathVariable int id ,@PathVariable String name){ System.out.println("id:"+id); System.out.println("name:"+name); //返回String return "hello";//可以直接跳到视图解析器下找hello.jsp }
@RequestParam
属性名 | 属性值 |
value | 参数名 |
required | true(默认) false |
defaultValue | 默认值,如果不给参数值,就走默认值 |
- 普通serlvet获取参数值
//通过绑定servlet对象,获取请求参数 @RequestMapping("show3") @ResponseStatus(HttpStatus.OK) public void test3(HttpServletRequest request){ System.out.println(request.getParameter("id")); System.out.println(request.getParameter("name")); }
- @RequestParam获取参数值
/** * 获取请求携带的参数 show4.do?id=33&name=jack * 1、@RequestParam 获取请求指定参数 * 2、value 参数据 * 3、required 参数是否必须,默认true * true: 必须 * false:可以不写 * 4、 defaultValue 如果没有传值,默认给出一个值 defaultValue = "jack" */ @RequestMapping("show4") @ResponseStatus(HttpStatus.OK) public void test4( @RequestParam(value = "id",required = true) int id, @RequestParam(value = "name",required = false, defaultValue = "jack") String name ){ System.out.println("id:"+id); System.out.println("name:"+name); }
@CookieValue
/** * 通过后台跳转到cookie视图 * @return */ @RequestMapping("toCookie") public ModelAndView toCookie(){ ModelAndView mv = new ModelAndView(); mv.setViewName("cookie"); return mv; } /** * 获取cookie的值 * @param name */ @RequestMapping("show5") @ResponseStatus(HttpStatus.OK) public void test5(@CookieValue(value = "name",required = false) String name){ System.out.println("cookie的值为:"+name); }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <a href="/hello/show5.do">测试cookie</a> <script> document.cookie = "name=jack"; </script> </body> </html>
POJO对象绑定参数
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency>
@Data public class User { private Integer id; private String name; private Integer age; }
/** * 接收绑定的pojo对象 * @param user * @return */ @RequestMapping("show6") public ModelAndView test6(User user){ System.out.println(user); ModelAndView mv = new ModelAndView(); mv.addObject("msg",user); mv.setViewName("hello"); return mv; }
基本数据类型绑定
/** * 通过后台跳转到user视图 * @return */ @RequestMapping("toUser") public ModelAndView toUser(){ ModelAndView mv = new ModelAndView(); mv.setViewName("user"); return mv; }
<form action="http://localhost:8080/springmvc-test02/hello2/show18.do" method="post"> <div>姓名:</div> <div><input name="name" value="张三"/></div> <div class="clear"></div> <div>年龄:</div> <div><input name="age" value="20"/></div> <div class="clear"></div> <div>收入:</div> <div><input name="income" value="100000"/></div> <div class="clear"></div> <div>结婚:</div> <div> <input type="radio" name="isMarried" value="true" checked="checked"/>是 <input type="radio" name="isMarried" value="false"/>否</div> <div class="clear"></div> <div>兴趣:</div> <div> <input type="checkbox" name="interests" value="听歌" checked="checked"/>听歌 <input type="checkbox" name="interests" value="书法" checked="checked"/>书法 <input type="checkbox" name="interests" value="看电影" checked="checked"/>看电影 </div> <div class="clear"></div> <div><input type="submit" value="提交表单"/></div> </form>
/** * 接收基本数据类型 */ @PostMapping("show8") @ResponseStatus(HttpStatus.OK) public void test7( @RequestParam("name") String name, @RequestParam("age") Integer age, @RequestParam("income") Double income, @RequestParam("isMarried") Boolean isMarried, @RequestParam("interests") String[] interests){ System.out.println("name: "+name); System.out.println("age: "+age); System.out.println("income: "+income); System.out.println("isMarried: "+isMarried); for(String str : interests){ System.out.println("interests: "+str); } }
解决乱码问题
springmvc提供了编码过滤器
只解post中文乱码问题,注意解析源码
配置位置 web.xml
<!--编码过滤器--> <filter> <!--注意这里是filter,不要配置成servlet--> <filter-name>encodingFilter</filter-name> <!--过滤器名称--> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!--过滤器的完整类名--> <init-param> <!--初始化参数--> <param-name>encoding</param-name> <!--参数名称--> <param-value>utf-8</param-value> <!--参数值--> </init-param> </filter> <filter-mapping> <!--过滤器映射--> <filter-name>encodingFilter</filter-name><!--过滤器名称--> <url-pattern>/*</url-pattern><!--URL映射,给所有页面处理乱码--> </filter-mapping>
通用页面跳转
我们发现上面我们写了很多次页面跳转的方法,其实我们可以抽取统一
@RequestMapping("to") @Controller public class Topage { /** * 通用页面跳转---视图解析器 http://localhost:8080/rest/to/hello */ @RequestMapping("{page}") public String toPage1(@PathVariable("page") String page){ return page; } /** * 通用页面跳转---webapp下视图--写着玩 */ @RequestMapping("wp/{page}") public String toPage2(@PathVariable("page") String page){ return "forward:/"+page+".html"; } }
<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping>
数组类型
<form action="/hello/show9.do" method="post"> <input type="checkbox" name="addr" value="郑州"> 郑州 <br> <input type="checkbox" name="addr" value="上海"> 上海 <br> <input type="checkbox" name="addr" value="杭州"> 杭州 <br> <input type="checkbox" name="addr" value="北京"> 北京 <br> <input type="checkbox" name="addr" value="曹县"> 曹县 <br> <input type="submit" value="数组类型"> </form>
/** * 接收数组 * @param addr */ @PostMapping("show9") @ResponseStatus(HttpStatus.OK) public void show9(String[] addr){ for (String str : addr){ System.out.println(str); } }
绑定复杂类型
如果提交的是一个集合的数据,SpringMVC的方法形参是无法接收的,我们必须通过实体类进行包装才行
@Data public class UserVO { private String name; private Integer age; private User user; private List<User> list; private Map<String,User> map; private String[] addr; }
<form action="/hello/show10.do" method="post"> 姓名: <input type="text" name="name"> 年龄: <input type="text" name="age"> <br/> user属性中的姓名:<input type="text" name="user.name"><br/> user属性中的年龄:<input type="text" name="user.age"> <br/> list中第一个user对象的年龄:<input type="text" name="list[0].age"> <br/> list中第一个user对象的姓名:<input type="text" name="list[0].name"> <br/> list中第二个user对象的年龄: <input type="text" name="list[1].age"> <br/> list中第二个user对象的姓名: <input type="text" name="list[1].name"> <br/> map中第一个键值对中值user对象的年龄: <input type="text" name="map['one'].age"> <br/> map中第一个键值对中值user对象的姓名: <input type="text" name="map['one'].name"> <br/> map中第二个键值对中值user对象的年龄: <input type="text" name="map['two'].age"> <br/> map中第二个键值对中值user对象的姓名: <input type="text" name="map['two'].name"><br/> 请选择喜欢的城市: <input type="checkbox" name="addr" value="郑州"> 郑州 <br> <input type="checkbox" name="addr" value="上海"> 上海 <br> <input type="checkbox" name="addr" value="杭州"> 杭州 <br> <input type="checkbox" name="addr" value="北京"> 北京 <br> <input type="checkbox" name="addr" value="曹县"> 曹县 <br> <input type="submit" value="复杂类型"> </form>
/** * 接受复杂类型 * @param userVO */ @PostMapping("show10") @ResponseStatus(HttpStatus.OK) public void show10(UserVO userVO){ System.out.println(userVO); }
日期类型
@DateTimeFormat(pattern = "yyyy-MM-dd") private Date birth;
jsp和jstl视图解析器
<dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
/** * 把数据转发到jsp页面中进行显示 */ @GetMapping("show20") public ModelAndView test20(){ ModelAndView mv = new ModelAndView(); Person person = new Person(); person.setId(11); person.setName("戈尔丹"); person.setAge(22); Person person2 = new Person(); person2.setId(11); person2.setName("赵日天"); person2.setAge(33); Person person3 = new Person(); person3.setId(11); person3.setName("叶良晨"); person3.setAge(44); List<Person> list = new ArrayList<>(); list.add(person); list.add(person2); list.add(person3); mv.addObject("list",list); mv.setViewName("list"); return mv; }
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Title</title> </head> <body> <table border="1px" cellpadding="8px" cellspacing="0px" width="80%"> <thead> <tr> <th>ID</th> <th>Name</th> <th>Age</th> </tr> </thead> <tbody> <c:forEach items="${list}" var="person"> <tr> <td>${person.id}</td> <td>${person.name}</td> <td>${person.age}</td> </tr> </c:forEach> </tbody> </table> </body> </html>
SpringMVC异步交互
在之前我们讲的请求响应都是同步的,但是在实际开发中我们都是使用异步请求,所以下面我们使用ajax发送异步请求!
在异步请求中数据传输的格式我们都是使用josn来进行传输,速度快,小巧,使用方便!!
在响应的同时,我们也是响应json字符串,在前端解析json字符串即可!
- 回顾ajax
- 发送ajax请求:.ajax()/.ajax() / .get() / $.post()
- 响应json数据:new ObjectMapper().writeValueAsString()
我们学习完SpringMVC之后,就不用像之前那么麻烦了,还要创建ObjectMapper对象来转换成josn数据进行响应。
SpringMVC已经帮我们做这些事情了。SpringMVC提供了两个注解@RequestBody和@ResponseBody实现josn数据的转换
@ResponseBody
用于将controller方法返回的对象通过转换器转换为指定的格式(通常为json)之后,写入到response对象的响应体中。
添加依赖
<!-- Jackson Json处理工具包 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.5</version> </dependency>
引入jq文件
<script src="js/jquery-3.4.1.js"></script>
编写ajax代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/jquery-3.4.1.js"></script> </head> <body> <table border="1"> <tr> <td>name</td> <td>age</td> </tr> </table> <script> $.ajax({ url: 'UserController/ajaxResponse.do', type: 'POST', dataType:"json", success: function (data) { var str = ''; $(data).each(function (i) { str += ` <tr> <td>${data.name}</td> <td>${data.age}</td> <td></td> </tr> `; }); $("table").append(str); } }); </script> </body> </html>
编写Controller
@Controller @RequestMapping("UserController") public class UserController { /** * 响应json串 * @return */ @PostMapping("ajaxResponse") @ResponseBody //返回的对象以json的形式响应 {"name":"jack","age":99} public User getUser(){ User user = new User(); user.setName("jack"); user.setAge(99); return user; } }
@RestController用法
@RequestMapping("UserController") @RestController //@RestController == @Controller 和 @ResponseBody public class UserController { /** * 响应json串 * @return */ @PostMapping("ajaxResponse") public User getUser(){ User user = new User(); user.setName("jack"); user.setAge(99); return user; } }
@RequestBody
用于接收前端请求体中的json数据,使用@RequestBody注解就可以自动的封装指定的对象中
引入jq文件
<script src="js/jquery-3.4.1.js"></script>
编写ajax代码
- 使用: $.ajax() 函数
- 规则:
- ajax提交的数据必须是一个标准的json字符串
- ajax提交的方式必须为post,数据必须在请求体中
- ajax提交的MIME类型必须为:application/json;charset=utf-8
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/jquery-3.4.1.js"></script> </head> <body> <script> $(function () { $.ajax({ url: '/UserController/ajaxRequest.do', type: 'POST', data: '{"name":"jack","age":99}', contentType:'application/json;charset=utf-8', success: function (data) { } }); }); </script> </body> </html>
编写Controller
/** * 接受json串 * @param user */ @PostMapping("ajaxRequest") public void test(@RequestBody User user){ //User(name=jack, age=99) System.out.println(user); }
小结
@RequestBody
:将请求体中的json字符串,转为指定类型的java对象
@ResponseBody
:将java对象转为json字符串,再设置到响应体中,返回到浏览器(客户端)
处理静态资源
测试前端代码
当点击按钮时,发现没有任何反应,这是因为SpringMVC在默认情况下,所有的静态资源都会被拦截(js,css。html,图片、视频、音频),在web.xml文件中,我们配置的拦截路径是/
这种形式除了jsp都会被拦截
<servlet-mapping> <servlet-name>springmvc</servlet-name> <!--拦截webapp下所有静态资源,除了jsp--> <url-pattern>/</url-pattern> </servlet-mapping>
把拦截路径设置为 / 时,会发现连html静态页面都无法访问
三种方式解决
对于静态资源,需要手动配置静态资源过滤。有三种形式可以选择:
- web.xml配置 方式一
<servlet-mapping> <servlet-name>springmvc</servlet-name> <!--拦截webapp下所有资源,除了jsp--> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 处理静态资源拦截--> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping>
- springmvc-servlet.xml 配置文件
<!-- 静态资源手动映射 mapping="/img/**" 浏览器发送请求 location="/img/" 静态资源的路径 --> <mvc:resources mapping="/html/**" location="/html/"/> <mvc:resources mapping="/img/**" location="/img/" /> <mvc:resources mapping="/js/**" location="/js/" /> <mvc:resources mapping="/css/**" location="/css/"/>
- springmvc-servlet.xml 配置文件【简化方式】
<!-- 处理静态资源拦截--> <!--配置tomcat默认的静态资源处理--> <mvc:default-servlet-handler/>