Java开发大多数场景是业务开发
比如说京东的业务就是电商卖货、今日头条的业务就推送新闻;快手的业务就是短视频推荐
Spring Web MVC:如何使用Spring去建网站
(我们知道既然Java是做业务开发就避免不了建网站)
Spring Web MVC是⼀个Web框架;也可以简称为Spring MVC
①Spring:Spring就是一个框架,能让我们更快速、便捷和高效的去完成Java开发
②Web:表示做的是网页、网站的开发
③MVC:MVC是Model View Controller的缩写,它是软件工程中的一种软件架构设计模式
(MVC就是把项目分为模型、视图和控制器三个基本部分 )
通过客户端和服务器进行交互主要分为三个方面
(客户端:浏览器/用户程序)
①建立连接:将客户端(浏览器/用户程序)和服务器(Java程序)连接起来,也就是访问⼀个浏览器地址能够调用到我们Java写的的Spring程序
②请求:当建立完连接之后,客户端会向服务器发出一个请求,此时在服务器端就得获取到请求的参数;因此,总的来说请求这块的主要是服务器为了获取请求的参数
③响应:服务器获取请求参数后,然后执行业务逻辑,执行完毕就把执行的结果返回给客户端
对于Spring Web MVC来说,掌握了以上3个功能就相当于掌握了Spring Web MVC
Spring MVC项目创建和SpringBoot创建项目相同,在创建的时候选择Spring Web就相当于创建了Spring MVC的项目
①作用:实现URL路由映射,也就是实现客户端连接服务器的作用
(即浏览器连接Java后端它们通过@RequestMapping建立连接)
②访问:IP:端口号/类的路径+方法路径
(类的路径和方法路径其实就是@RequestMapping里的参数;区分方式主要看它写在类外还是类内)
③理解:表示服务器收到请求时,路径为XXX的请求就会调用XXX路径对应这个方法的代码
@RequestMapping既可以修饰类,也可以修饰方法
@RequestMapping参数里的“/”可以省略,但还是建议加上
方法路径:写在类内;此时如果没有类的路径直接通过方法路径即可访问网址
下列代码表示服务器收到请求时,路径为/sayhi的请求就会调用sayHi这个方法里的代码
package com.example.demo.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; //此时没有类的路径,那么类的路径就为空,直接访问方法路径即可 @RestController public class HelloController { @RequestMapping("/sayhi") //方法路径 //sayHi()方法就是需要在网站上显示什么;方法名不要求与路径名相同 //例如我的路径名是sayhi,方法名是sayHi public String sayHi() { return "hi,SpringBoot"; } }
类的路径:写在类外;此时需要通过类的路径+方法路径才能访问网址
package com.example.demo.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/hlizoo") //类路径 @RestController public class HelloController { @RequestMapping("/sayhi") //方法路径 public String sayHi() { return "hi,SpringBoot"; } }
路径也可以包含多层,即多层套娃
package com.example.demo.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/hlizoo/cool") //类路径;多层路径 @RestController public class HelloController { @RequestMapping("/sayhi/no") //方法路径;多层路径 public String sayHi() { return "hi,SpringBoot"; } }
@RequestMapping支持所有的请求,比如GET、POST、PUT等等
@RequestMapping如果没有写属性,默认只有路径,此时可以写Method属性来限制请求的方法
(比如以下代码:说明路径是/hlizoo/sayhi和请求方法是GET时才调用sayHi方法)
package com.example.demo.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/hlizoo") //类路径 @RestController public class HelloController { //当你写了mehod,前面的路径就会默认加上value @RequestMapping(value = "/sayhi",method = RequestMethod.GET) //方法路径;此时指定是GET请求 public String sayHi() { return "hi,SpringBoot"; } }
学习Spring的请求,主要是学习如何传递参数到后端(服务器)以及后端(服务器)如何接收
原因就是当我们访问不同的路径,就会发送不同的请求,在发送请求时,可能会带⼀些参数,我们就要学习如何传参和接参
方法:接收单个参数,直接在Spring MVC的方法形参中声明参数数据类型和参数名即可
参数类型建议使用包装数据类型
(1)如果传的是基本数据类型,必须要传参传值,否则会报错
(2)如果传的是包装数据类型,不传参传值不会报错,而是返回null
package com.example.demo.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/m1") //此时就代表了接收了一个name参数 //至于这个name前端是如何给的,作为后端人员并不关心,我的要求只是一个name参数而已 //接收单个参数,直接在m1方法写参数数据类型和参数名即可 public String m1(String name){ return "接收到的参数name:"+name; } }
①当没有传递name参数的情况
②当传递了name参数的情况
方法:接收多个参数,直接在Spring MVC的方法形参中声明多个参数数据类型和参数名即可
参数类型建议使用包装数据类型
(1)如果传的是基本数据类型,必须要传参传值,否则会报错
(2)如果传的是包装数据类型,不传参传值不会报错,而是返回null
package com.example.demo.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/param") @RestController public class ParamController { //接收多个参数,直接在m2方法写多个参数数据类型和参数名即可 @RequestMapping("/m2") public String m2(String name,Integer age){ return "接收到的参数name:"+name+",age:"+age; } }
方法
①先写一个类,把这些参数封装为一个对象,写上Getter和Setter以及toString方法
②在方法的形参部分写上类和对象名
(原因:当参数过多时,方法声明就要写很多的形参,形参太多既不雅观修改也不方便,不妨写个类封装成对象)
①新建一个Person类
package com.example.demo; public class Person { Integer id; String name; Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
②方法的代码
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/m4") public String m4(Person person){ return "接收到的参数person:"+person.toString(); } }
方法:@RequestParam来重命名前后端的参数值
①进行了重命名后,就一定要使用@RequestParam里写的名字来进行传参
②进行了重命名后,如果使用了其他名字来进行传参,要么报错要么为null
情况:某些特殊的情况下,前端传递的参数key和我们后端接收的key可以不一致
比如后端是使用username字段来接收的,而前端却用了name字段来传递,这样就会出现参数接收不到的情况
package com.example.demo.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/m5") public String m5(@RequestParam("name") String username){ return "接收到的参数name:"+username; } }
①当用name作为字段来传参时,可以顺利的接收到请求
②当用username作为字段传参的时候,反而报错了
①如果使用了@RequestParam且不加任何属性,那么它里面的参数就是必传参数了,如果使用了其它的字段来传参就会报错
(2)@RequestParam里如果添加了required属性,required为false则里面的参数就不是必传参数了,使用了其他字段传参不会报错只会变成null
方法:在方法形参中写个数组即可;因为Spring MVC可以自动绑定数组参数的赋值
当我们的请求中,同一个参数名的参数有多个时,浏览器会给我们封装成一个数组
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Arrays; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/m6") public String m6(String []arrayParam){ return "接收到的参数arrayParam:"+ Arrays.toString(arrayParam); } }
方式一:用浏览器发送多个相同参数名的参数,参数之间用&分割
(当请求中同一个参数名arrayParam的参数有多个时,浏览器会给我们封装成一个数组)
方式二:用浏览器发送多个相同参数名的参数,参数之间用,分割
(当请求中同一个参数名arrayParam的参数有多个时,浏览器会给我们封装成一个数组)
方法:先使用@RequestParam绑定参数关系,然后写集合类和对象名即可
集合接收的方法和数组类似,只不过在默认情况下,请求中参数名相同的多个值,是封装到数组;如果要封装到集合,要使用@RequestParam绑定参数关系
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/m7") public String m7(@RequestParam List
listParam){ return "接收到的参数listParam:"+ listParam + "长度为:"+listParam.size(); } }
JSON:JavaScriptObjectNotation 【JavaScript对象表示法】
①JSON就是⼀种数据格式,有自己的格式和语法,使用文本表示一个对象或数组的信息
②JSON本质是字符串;主要负责在不同的语言中数据传递和交换
使用ObjectMapper对象提供的两个方法,可以完成对象和JSON字符串的互转
①writeValueAsString: 把Java对象转为JSON字符串
(参数写的是Java对象)
②readValue: 把JSON字符串转为Java对象
(第一个参数是JSON字符串;第二个参数是Java对象)
public class JSONUtils { private static ObjectMapper objectMapper = new ObjectMapper(); public static void main(String[] args) throws JsonProcessingException { Person person = new Person(); person.setId(5); person.setName("zhangsan"); person.setPassword("123456"); //Person对象转为JSON字符串 String jsonStr = objectMapper.writeValueAsString(person); System.out.println("JSON字符串为:"+jsonStr); //JSON字符串转为对象 Person p = objectMapper.readValue(jsonStr,Person.class); System.out.println("转换的对象 id:"+p.getId()+",name:"+p.getName()+",password:"+p.getPassword()); } }
方法:接收JSON对象,需要使用@RequestBody注解
RequestBody:请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须写在请求正文中
①创建一个Person对象
package com.example.demo; public class Person { Integer id; String name; Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
②方法的代码
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/m8") public String m8(@RequestBody Person person){ return "接收到的数据person:"+person.toString(); } }
方法:使用到@PathVariable来拿到URL的参数
@PathVariable主要作用在请求URL路径上的数据绑定,默认传递参数写在URL上,SpringMVC就可以获取到
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.web.bind.annotation.*; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { //注意@RequestMapping的参数 @RequestMapping("/m9/{userId}") public String m9(@PathVariable Integer userId) { return "userId:"+userId; } }
方法:使用到@RequestPart
①文件我们一般用MultipartFile file来接收,因此方法的形参一般写@RequestPart MultipartFile file
②transferTo方法可以将文件上传且保存到指定路径
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/m10") public String m10(@RequestPart MultipartFile file) throws IOException { //获取文件名称 String filename = file.getOriginalFilename(); //上传文件到指定路径 file.transferTo(new File("D:/test/"+file.getOriginalFilename())); return "success,"+"文件名称:"+filename; } }
3.利用Postman发送图片请求
4.注意事项
原因:HTTP协议自身是属于"无状态"协议,即HTTP协议无记忆功能
"无状态"的含义指的是:默认情况下HTTP协议的客户端和服务器之间的这次通信,和下次通信之间没有直接的联系;但是实际开发中,我们很多时候是需要知道请求之间的关联关系的, 例如登录网站成功后,第⼆次访问的时候服务器就能知道该请求是否是已经登陆过了
①Cookie是浏览器存储(临时)数据的机制
②Session是服务器存储(临时)数据的机制
(作用:存储用户的详细信息;并给用户分配一个唯一值sessionid;后续再访问网站的其他页面时,HTTP请求就会自动带上sessionid,通过sessionid就能找到对应的Session即对应的用户)
③两者的区别
④两者的联系
①Cookie是浏览器本地存储数据的一种机制
(此时在服务器这边就需要记录"令牌"信息,以及令牌对应的用户信息,这个就是Session机制所做的工作;下文详细说)
②作用:实现 "身份标识" 的功能;每个不同的域名下都可以有不同的Cookie, 不同网站之间的Cookie并不冲突
(Cookie会存储很多键值对,往往会有一个很重要的键值对是用来表示用户的“身份信息”,即标识当前请求是来自于哪个用户的;就会产生这么一种场景,比如你登陆一个网站,后续再访问这个网站页面,就无需登录了,而且就算关了电脑,第二天重开网页,依然不需要登录)
③Cookie的原理:Cookie是按键值对的形式来存储了一些字符串,这些键值对往往都是由服务器返回回来的,浏览器把这些键值对按照“域名”维度进行分类存储,意思就是说不同网站就有不同的Cookie,例如百度有百度的Cookie,搜狗有搜狗的Cookie,这些Cookie的内容都是由程序猿自己定义的
④Cookie的保存机制:
⑤总结:
(1)Cookie从哪来?
答:Cookie是从服务器返回给浏览器的
(2)Cookie是如何保存的?保存在哪?
答:浏览器按照不同的域名分别存储Cookie,域名与域名之间的Cookie是不能互相干扰的,即每一组域名都有自己的Cookie;Cookie保存在浏览器所在电脑的硬盘上,就算关机也不会影响到
(3)Cookie中的内容是啥?
答:Cookie中的内容是键值对结构的数据,这里的键值对是由程序猿自己定义的
(4)Cookie中的内容到哪里去?
答:后续访问该网站的各个页面时,就都会在请求中带上Cookie,服务器就可以进一步知道客户端用户的详细情况
⑥Cookie的缺点:
Cookie是可以伪造的
问:浏览器要保存数据为啥要先保存到Cookie再让Cookie保存到硬盘,而不能直接往硬盘写入一个文件保存?
答:往硬盘写入是绝对不行的!因为如果你让网页能够轻易的访问你的文件系统,这是一件非常危险的事情;想一下如果你上一种病毒网站,网站直接给你的电脑上下个病毒或者直接把你硬盘上已有的数据删除掉了,那不就完蛋了?
因此为了保证安全,浏览器会对网页的功能作出限制,禁止访问硬盘就是对网页的其中一个限制;所以为了既能保证安全也能保存数据,浏览器就提供了一个Cookie功能!
①Sessionid保存在Cookie中,后面再去访问服务器的时候,我的Cookie就带着Sessionid去访问,然后服务器就可以根据这个Sessionid去返回对应的Session了
(但在服务器这边也需要记录SessionId,以及SessionId对应的用户信息Session)
②Session的缺点:存在分布式问题
普通方法:需要用到HttpServletRequest,HttpServletResponse,它们是Servlet提供的两个类
①HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息
②HttpServletResponse对象代表服务器的响应,HTTP响应的信息都在这个对象中,比如向客户端发送的数据、响应头、状态码等;通过这个对象提供的方法,可以获得服务器响应的所有内容
这两个类是Spring内置的对象,当你需要的时候,直接在方法声明加上即可
package com.example.demo.Controller; import com.example.demo.Person; import com.sun.deploy.net.HttpResponse; import org.springframework.http.HttpRequest; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/getcookie") public String m11(HttpServletRequest request, HttpServletResponse response){ //拿到cookie的对象 Cookie[] cookies = request.getCookies(); //打印cookie的值 if(cookies!=null){ for (Cookie cookie : cookies) { System.out.println(cookie.getName()+":"+cookie.getValue()); } } return "获取cookie成功!"; } }
简单方法:使用@CookieValue即可
使用简单的方法一个@CookieValue一次只能拿一个Cookie,要想拿多个Cookie,就得使用多个@CookieValue
(它不像普通方法那样一次性可以拿完全部的Cookie然后保存到数组中)
package com.example.demo.Controller; import com.example.demo.Person; import com.sun.deploy.net.HttpResponse; import org.springframework.http.HttpRequest; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/getcookie2") public String m12(@CookieValue String bite,@CookieValue String aaa){ return "cookie存储的值bite:"+bite+",aaa:"+aaa; } }
①右键浏览器,选择检查,选择Applicaition
②选择左侧栏Storage栏中的Cookies
③自主添加Name和Value,比如我添加如下图所示的
④此时再次刷新网页并观看IDEA控制台
当设置好Cookie后,直接就可以获取了
普通方法①:基于HttpServletRequest来存储和获取的
普通方法②:基于HttpSession来存储和获取的
HttpServletRequest、HttpServletResponse、HttpSession都是Spring内置对象(内置对象:需要使用的时候直接方法声明即可)
Session是服务器端的机制,我们需要先存储,才能再获取
package com.example.demo.Controller; import com.example.demo.Person; import com.sun.deploy.net.HttpResponse; import org.springframework.http.HttpRequest; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { //session要先存储才能获取;并且session不像cookie那样可以设置 //这里先存储session @RequestMapping("/setSession") public String setSession(HttpServletRequest request){ HttpSession session = request.getSession(); session.setAttribute("username","zhangsan"); return "success"; } //第一种普通方法:使用Spring内置对象HttpServletRequest @RequestMapping("/getsession") public String m13(HttpServletRequest request){ //参数为true,没有session则创建session //参数为false,没有session则放回null HttpSession session = request.getSession(false); if (session!=null){ String username = (String) session.getAttribute("username"); return "登录用户:"+username; } return "session为空"; } //第二种普通方法:使用Spring内置对象HttpSession @RequestMapping("/getsession3") public String m15(HttpSession session){ String username = (String) session.getAttribute("username"); return "登录用户:"+username; } }
①先输入setSession来观察浏览器效果
(因为session要先存储才能获取)
②再去观察Cookie的效果,可以看到多了一个JSESSIONID
方法:使用@SessionAttribute即可
使用简单的方法一个@SessionAttribute一次只能拿一个Session,要想拿多个Session,就得使用多个@SessionAttribute
使用@SessionAttribute的参数默认是必传参数,如果让required=false,就不是必传参数了
package com.example.demo.Controller; import com.example.demo.Person; import com.sun.deploy.net.HttpResponse; import org.springframework.http.HttpRequest; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { //session要先存储才能获取;并且session不像cookie那样可以设置 //这里先存储session @RequestMapping("/setSession") public String setSession(HttpServletRequest request){ HttpSession session = request.getSession(); session.setAttribute("username","zhangsan"); return "success"; } @RequestMapping("/getsession2") public String m14(@SessionAttribute(required = false) String username){ return "username:"+username; } }
①依旧是输入先输入setSession来观察浏览器效果
(因为session要先存储才能获取)
②此时去观察简单方法的浏览器效果
普通方法:依旧使用内置对象HttpServletRequest,通过HttpServletRequest提供的getHeader方法来获取,参数对应HTTP请求报头的"Key"
package com.example.demo.Controller; import com.example.demo.Person; import com.sun.deploy.net.HttpResponse; import org.springframework.http.HttpRequest; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/getHeader") public String m16(HttpServletRequest request){ String UserAgent = request.getHeader("User-Agent"); return "User-Agent:"+UserAgent; } }
简单方法:使用@RequestHeader;@RequestHeader的参数值为HTTP请求报头中的"Key",如果你想赋值给哪个变量,在后面写上即可
package com.example.demo.Controller; import com.example.demo.Person; import com.sun.deploy.net.HttpResponse; import org.springframework.http.HttpRequest; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; @RequestMapping("/param") @RestController public class ParamController { @RequestMapping("/getHeader2") public String m17(@RequestHeader("User-Agent") String UserAgent){ return "User-Agent:"+UserAgent; } }
方法:使用的是@Controller
(不是@RestController,跟上述的请求不一样,下文详细分析)
返回static目录下的静态页面,直接在return后面加上“/XXX.html”即可
(比如:return "/login.html")
①先在static目录下创建一个名字为index的html文件
②因为是用来测试的,我们前端代码写得简单一点就行
index首页 我是index页面
③重新启动服务器,访问index.html看看效果如何
(static目录下的静态页面可直接访问)
package com.example.demo.Controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @RequestMapping("/return") @Controller //←注意这里用的是Controller public class ReturnController { @RequestMapping("/index") public String returnIndex(){ return "/index.html"; } }
①@RestController = @Controller + @ResponseBody
(1)@Controller : 定义⼀个控制器,Spring框架启动时加载,把这个对象交给Spring管理
(2)@ResponseBody : 定义返回的数据格式为非视图,返回⼀个text/html数据信息
②@Controller返回视图页面;@ResponseBody返回页面的数据
③如果想返回视图的话,只需要把@ResponseBody去掉就可以了,也就是@Controller
作用:Spring框架启动时加载,把这个对象交给Spring管理;然后去找需要返回的视图,如果找到就返回例如HTML页面等等的视图,没找到就报错404
(即是说把整个代码交给Spring,告诉Spring帮我们去管理;后续我们访问时,才能访问到)
方法:使用的是@ResponseBody;表示返回数据
(比如return "/index.html",@Controller会去查找index.html文件,但是如果加了@ResponseBody,就直接把"/index.html"当做⼀个文本数据返回给前端)
①@ResponseBody既是类注解,又是方法注解
②@ResponseBody如果作用在类上,表示该类的所有方法返回的都是数据
(1)在类上添加@ResponseBody就相当于在所有的方法上添加了@ResponseBody
(2)相同,如果类上有@RestController时,表示所有的方法上添加了@ResponseBody,也就是当前类下所有的方法返回值都为响应数据
③@ResponseBody如果作用在方法上,表示该方法返回的是数据
package com.example.demo.Controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @RequestMapping("/return") @Controller //←注意这里用的是Controller,下面如果要返回数据必须要加上@ResponseBody public class ReturnController { @ResponseBody //作用于方法上,表示returnData方法返回的是一个文本数据 @RequestMapping("/returndata") public String returnData(){ return "/index.html"; //此时加了@ResponseBody,就直接返回一个文本数据 } }
方法:使用@ResponseBody也可返回HTML的文本数据
原因:后端返回数据时,如果数据中有HTML代码,也会被浏览器解析
package com.example.demo.Controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @RequestMapping("/return") @Controller //←注意这里用的是Controller,下面如果要返回数据必须要加上@ResponseBody public class ReturnController { @ResponseBody @RequestMapping("/returnHTML") public String returnHTML(){ return "
这是一个HTML片段
"; } }
方法:使用@ResponseBody;要想返回JSON则返回类型是对象或者Map即可
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @RequestMapping("/return") @Controller //←注意这里用的是Controller,下面如果要返回数据必须要加上@ResponseBody public class ReturnController { @ResponseBody @RequestMapping("/returnJSON") public Person returnjson(){ //使用之前的Person类 Person person = new Person(); person.setId(7); person.setName("hlizoo"); person.setAge(20); return person; } }
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; import java.util.Map; @RequestMapping("/return") @Controller //←注意这里用的是Controller,下面如果要返回数据必须要加上@ResponseBody public class ReturnController { @ResponseBody @RequestMapping("/returnMAP") public Map
returnmap(){ Map kv = new HashMap<>(); kv.put("k1","v1"); kv.put("k2","v2"); kv.put("k3","v3"); return kv; } }
①当我们的返回类型是基本数据类型和包装类型时,Content-Type默认是text/html
(比如String、Integer等等)
②当我们的返回类型是对象和Map等等时,Content-Type自动设置为application/json
(只要返回类型是对象和Map时,要想返回json那啥都不用做,浏览器自动就搞好了)
方法:使用Spring MVC内置对象HttpServletResponse提供的setStatus方法进行设置
Spring MVC会根据我们方法的返回结果自动设置响应状态码,当然我们也可以手动指定状态码
注意这里的状态码并不影响页面的展示,就算你的状态码是401,也会显示你设置的内容
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map; @RequestMapping("/return") @Controller //←注意这里用的是Controller,下面如果要返回数据必须要加上@ResponseBody public class ReturnController { @ResponseBody @RequestMapping("/setStatus") public String setstatus(HttpServletResponse response){ response.setStatus(401); return "设置状态码"; } }
方法:通过设置@RequestMapping里produces属性的值,来设置响应的报头Content-Type
package com.example.demo.Controller; import com.example.demo.Person; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map; @RequestMapping("/return") @Controller //←注意这里用的是Controller,下面如果要返回数据必须要加上@ResponseBody public class ReturnController { @ResponseBody @RequestMapping(value = "/r1",produces = "application/json;charset=utf8") public String r1() { return "{'ok':200}"; } }
方法:通过内置对象HttpServletResponse里setHeader方法来设置响应的报头