【Java_EE】Spring MVC
目录
Spring Web MVC
编辑注解
@RestController
@RequestMapping
@RequestParam
@RequestParam
@RequestBody
@PathVariable
@RequestPart
参数传递
注意事项
编辑参数重命名
@RequestParam
编辑编辑传递集合
@RequestParam
传递JSON数据
编辑@RequestBody
编辑获取URL中的参数
@PathVariable
编辑上传文件
@RequestPart
Cookie和Session
Cookie和Session的区别
Cookie和Session的关系
设置session(2种方式)
获取session(3种方式)
获取header(2种方式)
返回响应
响应静态页面
响应html代码片段
响应JSON对象
设置Connect-Type
小结练习:
登录练习和留言练习
API的实现
进行前后端交互
Spring Web MVC
Spring Web MVC:是基于Servlet API构建的原始web框架,实现了mvc设计模式的思想,通常被称为spring mvc
Servlet:是一套Java Web开发的规范(技术标准),是一种实现动态页面的技术
MVC的定义:Model Controller View
注解
@RestController
这是一个类注解,加了这个注解,spring才会对该类进行扫描。@RestController = @Controller(返回视图) + @ResponseBody(返回数据),所以最后返回的就是数据
@RequestMapping
URL路由映射,是用来注册接口的路由映射的
访问路径=类路径+方法路径,路径不能重复
可以修饰类,也可以修饰方法
支持GET请求,也支持POST请求
@RequestParam
@RequestParam进行参数重命名时,参数就变成了必传参数(required默认为true),将required改为false就为非必传了(方法参数)
@RequestParam
传递集合参数和传递数组类似,只是集合需要使用@RequestParam绑定参数关系。默认情况下,请求中参数名相同的多个值,封装到数组;要封装到集合,则需要使用@RequestParam绑定参数关系(集合)
@RequestBody
@RequestBody 作用在请求正文的数据绑定,请求参数必须秀在请求正文中(json)
@PathVariable
@PathVariable 路径变量,作用在请求URL路径上的数据绑定,默认传递参数写在URL上,SpringMVC就可以获取到(url)
@RequestPart
@RequestPart 可用于文件重命名(文件)
参数传递
接收参数。对于包装类型,如果不传对应参数,Spring接收到的数据则是null;对于基本类型,如果不传对应参数,会报500错误
注意事项
使用基本类型接收参数时,参数必须传(除了boolean类型),否则会报500错误,类型不匹配时会报400错误
参数重命名
@RequestParam
@RequestParam进行参数重命名时,参数就变成了必传参数(required默认为true),将required改为false就为非必传了

传递集合
@RequestParam
传递集合参数和传递数组类似,只是集合需要使用@RequestParam绑定参数关系。默认情况下,请求中参数名相同的多个值,封装到数组;要封装到集合,则需要使用@RequestParam绑定参数关系
传递JSON数据
JSON:是一种轻量级的数据交互格式,JSON本质是字符串,主要负责在不同的语言中数据传递和交换
JSON字符串和Java对象互转:可以通过jackson、fastjson1、fastjson2、gson...在Spring MVC框架中集成了JSON转换工具jackson
jackson工具:使用ObjectMapper对象提供的两个方法,JSON和Java对象可以互转
writeValueAsString():把对象转为JSON字符串
readValue():把JSON字符串转为对象(需要有无参构造方法)
@RequestBody
@RequestBody 作用在请求正文的数据绑定,请求参数必须在请求正文中
获取URL中的参数
@PathVariable
@PathVariable 路径变量,作用在请求URL路径上的数据绑定,默认传递参数写在URL上,SpringMVC就可以获取到
上传文件
@RequestPart
@RequestPart 可用于文件重命名
Cookie和Session
Cookie和Session的区别
Cookie是保存在客户端的用户信息的一种机制,Session是保存在服务器端的用户信息一种机制,sessionId是两者之间的桥梁。
cookie是不安全的,可以伪造cookie;session是安全的。
session默认是保存在内存中,如果重启服务器session数据就会丢失。
Cookie和Session的关系
设置session(2种方式)
// 设置Session
@RequestMapping("/setSession1")public String setSession1(HttpServletRequest request) {HttpSession session = request.getSession();session.setAttribute("name", "value1");session.setAttribute("age", 200);return "设置session成功 key1:value1 key2:200";}// 设置Session@RequestMapping("/setSession2")public String setSession2(HttpServletRequest request, String value3, Integer value4) {HttpSession session = request.getSession();session.setAttribute("name", value3);session.setAttribute("age", value4);return "设置session成功! name:" + value3 + " age:" + value4;}// 设置Session@RequestMapping("/setSession3")public String setSession3(HttpSession session, String name, Integer age) {session.setAttribute("name", name);session.setAttribute("age", age);return "设置session成功! name:" + name + " age:" + age;}
设置完一条Session就会自动生成一个Cookie
获取cookie(2种方式)
1:通过接口HttpServletRequest
2:通过注解@CookieValue
@RequestMapping("/getCookie1")public String getCookie1(HttpServletRequest request) {Cookie[] cookies = request.getCookies();if(cookies == null) {System.out.println("没有Cookie");return "没有Cookie";}for (Cookie cookie : cookies) {System.out.println("getCookie-》" + cookie.getName() + ":" + cookie.getValue());}return "获取Cookie成功";}
@RequestMapping("/getCookie2")public String getCookie2(@CookieValue("key3") String value) {return "获取Cookie成功! key:" + value;}
获取session(3种方式)
1:通过接口HttpServletRequest
2:通过接口HttpSession
3:通过注解SessionAttribute
此处获取需要进行对象转换,将Object对象转换成替他类型(String、Integer)
// 获取Session@RequestMapping("/getSession1")public String getSession1(HttpServletRequest request) {HttpSession session = request.getSession();String name = (String)session.getAttribute("name");Integer age = (Integer)session.getAttribute("age");return "获取session成功 key1:" + name + " key2:" + age;}// 获取Session@RequestMapping("/getSession2")public String getSession2(HttpSession session) {String name = (String)session.getAttribute("name");Integer age = (Integer)session.getAttribute("age");return "获取session成功 key1:" + name + " key2:" + age;}// 获取Session@RequestMapping("/getSession3")public String getSession3(@SessionAttribute("name") String name, @SessionAttribute("age") Integer age) {return "获取session成功 key1:" + name + " key2:" + age;}
获取header(2种方式)
// 获取header@RequestMapping("/getHeader1")public String getHeader1(HttpServletRequest request) {String connection = request.getHeader("Connection");return "获取header成功! header:" + connection;}// 获取header@RequestMapping("/getHeader2")public String getHeader2(@RequestHeader("Connection") String connection) {return "获取header成功! header:" + connection;}
返回响应
响应静态页面
@RestController = @Controller(返回视图) + @ResponseBody(返回数据),所以最后返回的就是数据
@ResponseBody 作用在类上,该类上的所有方法返回都是数据;作用在方法上返回的都是数据
@RequestMapping("/data")public String response() {return "index.html"; // 这是一个相对路径,就找不到这个页面}@RequestMapping("/static_page_data")public String responseStaticPage() {return "/index.html"; // 但是此处被是被为了字符串,原因是加了@RestController// @RestController = @Controller(返回视图) + @ResponseBody(返回数据),所以返回的是字符串,而不是视图,所以会找不到这个页面// 在类上使用@Controller注解,就会返回视图,就可以找到这个页面了}
响应html代码片段
// 响应html代码片段@RequestMapping("/responseHtml")@ResponseBody// 不加@ResponseBody就找不到这个字符串// 因为@Controller返回的是视图// @RestController(返回数据) = @Controller(返回视图) + @ResponseBody(返回数据)public String responseHtml() {return "<h1>Hello World</h1>";}
响应JSON对象
// 响应JSON对象@RequestMapping("/json")@ResponseBodypublic Person responseJSON() {Person person = new Person();person.setName("张三");person.setAge(20);person.setGender("男");return person;}
设置Connect-Type
// 设置connect-type@ResponseBody@RequestMapping("/connect_type")public void setConnectType1(HttpServletResponse response) throws IOException {response.setContentType("text/plain"); // text/plain,返回的是纯文本response.getOutputStream().write("<h1>Hello World</h1>".getBytes(StandardCharsets.UTF_8));}// 设置connect-type@ResponseBody@RequestMapping(value = "/setConnectType" , produces = "text/plain") public String setConnectType2 (HttpServletResponse response) throws IOException {// response.getOutputStream().write("<h1>Hello World</h1>".getBytes(StandardCharsets.UTF_8));return "<h1>hello word</h1>";}
小结练习:
登录练习和留言练习
API的实现
@RestController
@RequestMapping("/test")
public class TestController {@PostMapping("/login")public Boolean login(@RequestBody User user, HttpSession session) {System.out.println("参数到达后端:user " + user.toString());/*** 校验参数* TODO 校验密码是否正确*/if(!StringUtils.hasLength(user.getUserName()) || !StringUtils.hasLength(user.getPassword())) {System.out.println("用户名或密码不规范");return false;}if("admin".equals(user.getUserName()) && "admin".equals(user.getPassword())) {// 存储用户session.setAttribute("userName", user.getUserName());session.setAttribute("password", user.getPassword());return true;}return false;}@GetMapping("/loginUser")public String loginUser(HttpServletRequest request) {System.out.println("登录用户的获取!");HttpSession session = request.getSession(false);// 判断Session是否有数据if(session != null) {String userName = (String)session.getAttribute("userName");return "登录用户:" + userName;}return "没用用户登录";}List<Message> messages = new ArrayList<>();@PostMapping("publishMessage")public Boolean publishMessage(@RequestBody Message message) {System.out.println("留言参数到达后端 message:" + message);/*** 校验参数* 存储数据*/if(!StringUtils.hasLength(message.getContent())|| !StringUtils.hasLength(message.getReceiver())|| !StringUtils.hasLength(message.getContent())) {System.out.println("请正确填写留言板!");return false;}messages.add(message); // 存储数据return true;}@GetMapping("/messageList")public List<Message> messageList() {System.out.println("所有留言展现!");return messages;}
}
进行前后端交互
<body><div class="container"><h1 style="color: #333;">留言板</h1><p class="grey">输入后点击提交, 会将信息显示下方空白处</p><div class="row"><span>谁:</span> <input type="text" name="" id="from"></div><div class="row"><span>对谁:</span> <input type="text" name="" id="to"></div><div class="row"><span>说什么:</span> <input type="text" name="" id="say"></div><input type="button" value="提交" id="submit" onclick="submit()"><!-- <div>A 对 B 说: hello</div> --></div><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script><script>$.ajax({url:"/test/messageList",type:"get",success:function (messages) {// 遍历结果数组,将每个留言显示在页面上for(let message of messages) {var msg = message.commenter + " 对 " + message.receiver + " 说: " + message.content;var messageElement = $("<div>" + msg + "</div>");$(".container").append(messageElement);}}});function submit() {// 获取数据var commenter = $('#from').val();var receiver = $('#to').val();var content = $('#say').val();// 调用后端接口$.ajax({url:"/test/publishMessage",type:"post",contentType:"application/json",data:JSON.stringify({commenter:commenter,receiver:receiver,content:content}),success:function (result) {if(result) {// 在留言板上显示留言var message = commenter + " 对 " + receiver + " 说: " + content;var messageElement = $("<div>" + message + "</div>");$(".container").append(messageElement);// 清空输入框的值$('#from').val("");$('#to').val("");$('#say').val("");} else {alert("留言失败!")}}});}</script>
</body>