当前位置: 首页 > news >正文

Spring Web MVC入门

一:了解Spring Web MVC

(1)关于Java开发

🌟Java开发大多数场景是业务开发


比如说京东的业务就是电商卖货、今日头条的业务就推送新闻;快手的业务就是短视频推荐

(2)Spring Web MVC的简单理解

💗Spring Web MVC:如何使用Spring去建网站

(我们知道既然Java是做业务开发就避免不了建网站)


💗 Spring Web MVC是⼀个Web框架;也可以简称为Spring MVC 

①Spring:Spring就是一个框架,能让我们更快速、便捷和高效的去完成Java开发


②Web:表示做的是网页、网站的开发


③MVC:MVC是Model View Controller的缩写,它是软件工程中的一种软件架构设计模式

(MVC就是把项目分为模型、视图和控制器三个基本部分 )

二:学习Spring Web MVC前提

(1)了解客户端和服务器的交互

💗通过客户端和服务器进行交互主要分为三个方面

(客户端:浏览器/用户程序)


①建立连接:将客户端(浏览器/用户程序)和服务器(Java程序)连接起来,也就是访问⼀个浏览器地址能够调用到我们Java写的的Spring程序


②请求:当建立完连接之后,客户端会向服务器发出一个请求,此时在服务器端就得获取到请求的参数;因此,总的来说请求这块的主要是服务器为了获取请求的参数


③响应:服务器获取请求参数后,然后执行业务逻辑,执行完毕就把执行的结果返回给客户端


💜对于Spring Web MVC来说,掌握了以上3个功能就相当于掌握了Spring Web MVC

(2)项目准备

🌟Spring MVC项目创建和SpringBoot创建项目相同,在创建的时候选择Spring Web就相当于创建了Spring MVC的项目

三:Spring Web MVC-建立连接

(1)@RequestMapping概念

①作用:实现URL路由映射,也就是实现客户端连接服务器的作用

(即浏览器连接Java后端它们通过@RequestMapping建立连接)


②访问:IP:端口号/类的路径+方法路径

(类的路径和方法路径其实就是@RequestMapping里的参数;区分方式主要看它写在类外还是类内)


③理解:表示服务器收到请求时,路径为XXX的请求就会调用XXX路径对应这个方法的代码

(2)@RequestMapping使用方式

1.使用方式和细节

💗@RequestMapping既可以修饰类,也可以修饰方法


🌟@RequestMapping参数里的“/”可以省略,但还是建议加上

2.方法路径

💙方法路径:写在类内;此时如果没有类的路径直接通过方法路径即可访问网址


🖤下列代码表示服务器收到请求时,路径为/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,方法名是sayHipublic String sayHi() {    return "hi,SpringBoot";}
}

3.类的路径

💙类的路径:写在类外;此时需要通过类的路径+方法路径才能访问网址


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";}
}

4.路径嵌套

💙路径也可以包含多层,即多层套娃


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";}
}

(3)@RequestMapping限制请求

 💗@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 Web MVC-请求

(1)明确请求部分的学习内容

💗学习Spring的请求,主要是学习如何传递参数到后端(服务器)以及后端(服务器)如何接收


💚原因就是当我们访问不同的路径,就会发送不同的请求,在发送请求时,可能会带⼀些参数,我们就要学习如何传参和接参

(2)传递单个参数的接收方法

1.方法

💗方法:接收单个参数,直接在Spring MVC的方法形参中声明参数数据类型和参数名即可


💛参数类型建议使用包装数据类型

(1)如果传的是基本数据类型,必须要传参传值,否则会报错

(2)如果传的是包装数据类型,不传参传值不会报错,而是返回null

2.后端代码
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;}
}
3. 利用Postman发送单个参数的请求

①当没有传递name参数的情况


②当传递了name参数的情况

4.注意事项

(3)传递多个参数的接收方法

1.方法

💗方法:接收多个参数,直接在Spring MVC的方法形参中声明多个参数数据类型和参数名即可


💛参数类型建议使用包装数据类型

(1)如果传的是基本数据类型,必须要传参传值,否则会报错

(2)如果传的是包装数据类型,不传参传值不会报错,而是返回null

2.后端代码
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;}
}
3. 利用Postman发送多个参数的请求

4.注意事项

 

(4)传递对象的接收方法

1.方法

💗方法

①先写一个类,把这些参数封装为一个对象,写上Getter和Setter以及toString方法

②在方法的形参部分写上类和对象名


(原因:当参数过多时,方法声明就要写很多的形参,形参太多既不雅观修改也不方便,不妨写个类封装成对象)

2.后端代码

①新建一个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;}@Overridepublic 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();}
}
 3.利用Postman发送请求

(5)后端参数重命名

1.方法

💗方法:@RequestParam来重命名前后端的参数值


①进行了重命名后,就一定要使用@RequestParam里写的名字来进行传参

②进行了重命名后,如果使用了其他名字来进行传参,要么报错要么为null

2.后端代码

🖤情况:某些特殊的情况下,前端传递的参数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;}
}
3. 利用Postman发送请求

①当用name作为字段来传参时,可以顺利的接收到请求


②当用username作为字段传参的时候,反而报错了

4.注意事项

💓①如果使用了@RequestParam且不加任何属性,那么它里面的参数就是必传参数了,如果使用了其它的字段来传参就会报错


💓(2)@RequestParam里如果添加了required属性,required为false则里面的参数就不是必传参数了,使用了其他字段传参不会报错只会变成null

(6)传递数组的接收方法

1.方法

💗方法:在方法形参中写个数组即可;因为Spring MVC可以自动绑定数组参数的赋值


💛当我们的请求中,同一个参数名的参数有多个时,浏览器会给我们封装成一个数组

2.后端代码
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);}
}
3.利用浏览器发送请求

🌟方式一:用浏览器发送多个相同参数名的参数,参数之间用&分割

(当请求中同一个参数名arrayParam的参数有多个时,浏览器会给我们封装成一个数组)


🌟方式二:用浏览器发送多个相同参数名的参数,参数之间用,分割

(当请求中同一个参数名arrayParam的参数有多个时,浏览器会给我们封装成一个数组)

(7)传递集合的接收方法

1.方法

💗方法:先使用@RequestParam绑定参数关系,然后写集合类和对象名即可


💛集合接收的方法和数组类似,只不过在默认情况下,请求中参数名相同的多个值,是封装到数组;如果要封装到集合,要使用@RequestParam绑定参数关系

2.后端代码
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<String> listParam){return "接收到的参数listParam:"+ listParam + "长度为:"+listParam.size();}
}
3.利用Postman发送请求

 (8)传递JSON数据的接收方法

1.JSON定义

JSON:JavaScriptObjectNotation 【JavaScript对象表示法】


💓①JSON就是⼀种数据格式,有自己的格式和语法,使用文本表示一个对象或数组的信息


💓②JSON本质是字符串;主要负责在不同的语言中数据传递和交换

2.JSON语法



3.JSON字符串和Java对象互转

🌟使用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());}
}
4.方法

💗方法:接收JSON对象,需要使用@RequestBody注解


🌟RequestBody:请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须写在请求正文中

5.后端代码

①创建一个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;}@Overridepublic 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();}
}
6.利用Postman发送JSON请求

(9)获取URL中的参数

1.方法

💗方法:使用到@PathVariable来拿到URL的参数


💛@PathVariable主要作用在请求URL路径上的数据绑定,默认传递参数写在URL上,SpringMVC就可以获取到

2.后端代码
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;}
}
3.利用Postman发送请求

4.注意事项

(10)上传文件

1.方法

💗方法:使用到@RequestPart


①文件我们一般用MultipartFile file来接收,因此方法的形参一般写@RequestPart MultipartFile file


②transferTo方法可以将文件上传且保存到指定路径

2.后端代码
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.注意事项

(11)获取Cookie/Session

1.为什么会出现Cookie与Session

💗原因:HTTP协议自身是属于"无状态"协议,即HTTP协议无记忆功能


💙"无状态"的含义指的是:默认情况下HTTP协议的客户端和服务器之间的这次通信,和下次通信之间没有直接的联系;但是实际开发中,我们很多时候是需要知道请求之间的关联关系的, 例如登录网站成功后,第⼆次访问的时候服务器就能知道该请求是否是已经登陆过了

2.区分Cookie与Session概念

 ①Cookie是浏览器存储(临时)数据的机制


②Session是服务器存储(临时)数据的机制

(作用:存储用户的详细信息;并给用户分配一个唯一值sessionid;后续再访问网站的其他页面时,HTTP请求就会自动带上sessionid,通过sessionid就能找到对应的Session即对应的用户)


③两者的区别


④两者的联系

3.详解Cookie

①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功能!

4.了解Session

 🌟①Sessionid保存在Cookie中,后面再去访问服务器的时候,我的Cookie就带着Sessionid去访问,然后服务器就可以根据这个Sessionid去返回对应的Session了

(但在服务器这边也需要记录SessionId,以及SessionId对应的用户信息Session)


🌟②Session的缺点:存在分布式问题


5.获取Cookie的普通方法

💗普通方法:需要用到HttpServletRequest,HttpServletResponse,它们是Servlet提供的两个类


💚①HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息


💚②HttpServletResponse对象代表服务器的响应,HTTP响应的信息都在这个对象中,比如向客户端发送的数据、响应头、状态码等;通过这个对象提供的方法,可以获得服务器响应的所有内容


🌟这两个类是Spring内置的对象,当你需要的时候,直接在方法声明加上即可

6.获取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("/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成功!";}
}
7.获取Cookie的简单方法

💗简单方法:使用@CookieValue即可


🌟使用简单的方法一个@CookieValue一次只能拿一个Cookie,要想拿多个Cookie,就得使用多个@CookieValue

💚(它不像普通方法那样一次性可以拿完全部的Cookie然后保存到数组中)

8.获取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;}
}
9.利用浏览器设置Cookie(普通版)

①右键浏览器,选择检查,选择Applicaition


②选择左侧栏Storage栏中的Cookies


③自主添加Name和Value,比如我添加如下图所示的


④此时再次刷新网页并观看IDEA控制台

10.利用浏览器设置Cookie(简单版)

💛当设置好Cookie后,直接就可以获取了

11.获取Session的普通方法

💗普通方法①:基于HttpServletRequest来存储和获取的


💗普通方法②:基于HttpSession来存储和获取的
HttpServletRequest、HttpServletResponse、HttpSession都是Spring内置对象

(内置对象:需要使用的时候直接方法声明即可)


🌟Session是服务器端的机制,我们需要先存储,才能再获取

12.获取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则放回nullHttpSession 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;}
}
13.观察浏览器(普通版)

①先输入setSession来观察浏览器效果

(因为session要先存储才能获取)


②再去观察Cookie的效果,可以看到多了一个JSESSIONID

14.获取Session的简单方法

💗方法:使用@SessionAttribute即可


🌟使用简单的方法一个@SessionAttribute一次只能拿一个Session,要想拿多个Session,就得使用多个@SessionAttribute


🌟使用@SessionAttribute的参数默认是必传参数,如果让required=false,就不是必传参数了

15.获取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";}@RequestMapping("/getsession2")public String m14(@SessionAttribute(required = false) String username){return "username:"+username;}
}
16.观察浏览器(简单版)

①依旧是输入先输入setSession来观察浏览器效果

(因为session要先存储才能获取)


②此时去观察简单方法的浏览器效果

(12)获取Header

1.获取Header的普通方法

💗普通方法:依旧使用内置对象HttpServletRequest,通过HttpServletRequest提供的getHeader方法来获取,参数对应HTTP请求报头的"Key"

2.后端代码(普通版)
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;}
}
3.观察浏览器效果(普通版)

4.获取Header的简单方法

💗简单方法:使用@RequestHeader;@RequestHeader的参数值为HTTP请求报头中的"Key",如果你想赋值给哪个变量,在后面写上即可

5.后端代码(简单版)
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;}
}
6.观察浏览器效果(简单版)

五:Spring Web MVC-响应

(1)返回静态页面

1.方法

💗方法:使用的是@Controller

(不是@RestController,跟上述的请求不一样,下文详细分析)


💚返回static目录下的静态页面,直接在return后面加上“/XXX.html”即可

(比如:return "/login.html")

2.前端代码

①先在static目录下创建一个名字为index的html文件


②因为是用来测试的,我们前端代码写得简单一点就行

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>index首页</title>
</head>
<body><h1>我是index页面</h1>
</body>
</html>

③重新启动服务器,访问index.html看看效果如何

(static目录下的静态页面可直接访问)

3.后端代码
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";}
}
4.观察浏览器效果

5.初次了解@RestController

💗①@RestController = @Controller + @ResponseBody

(1)@Controller : 定义⼀个控制器,Spring框架启动时加载,把这个对象交给Spring管理

(2)@ResponseBody : 定义返回的数据格式为非视图,返回⼀个text/html数据信息


💗②@Controller返回视图页面;@ResponseBody返回页面的数据


💗③如果想返回视图的话,只需要把@ResponseBody去掉就可以了,也就是@Controller

6.初次了解@Controller

💗作用:Spring框架启动时加载,把这个对象交给Spring管理;然后去找需要返回的视图,如果找到就返回例如HTML页面等等的视图,没找到就报错404

(即是说把整个代码交给Spring,告诉Spring帮我们去管理;后续我们访问时,才能访问到)


(2)返回数据

1.方法

💗方法:使用的是@ResponseBody;表示返回数据

(比如return "/index.html",@Controller会去查找index.html文件,但是如果加了@ResponseBody,就直接把"/index.html"当做⼀个文本数据返回给前端)


①@ResponseBody既是类注解,又是方法注解


②@ResponseBody如果作用在类上,表示该类的所有方法返回的都是数据

(1)在类上添加@ResponseBody就相当于在所有的方法上添加了@ResponseBody

(2)相同,如果类上有@RestController时,表示所有的方法上添加了@ResponseBody,也就是当前类下所有的方法返回值都为响应数据 


③@ResponseBody如果作用在方法上,表示该方法返回的是数据

2.后端代码
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,就直接返回一个文本数据}
}
3.观察浏览器效果

(3)返回HTML代码片段

1.方法

💗方法:使用@ResponseBody也可返回HTML的文本数据


💚原因:后端返回数据时,如果数据中有HTML代码,也会被浏览器解析

2.后端代码
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 "<h1>这是一个HTML片段</h1>";}
}
3.观察浏览器效果

(4)返回JSON

1.方法

💗方法:使用@ResponseBody;要想返回JSON则返回类型是对象或者Map即可

2.后端代码(示例一)
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;}
}
3.观察浏览器效果(示例一)

4.后端代码(示例二)
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<String,String> returnmap(){Map<String,String> kv = new HashMap<>();kv.put("k1","v1");kv.put("k2","v2");kv.put("k3","v3");return kv;}
}
5.观察浏览器效果(示例二)

6.注意事项

①当我们的返回类型是基本数据类型和包装类型时,Content-Type默认是text/html

(比如String、Integer等等)


②当我们的返回类型是对象和Map等等时,Content-Type自动设置为application/json

(只要返回类型是对象和Map时,要想返回json那啥都不用做,浏览器自动就搞好了)

(5)设置状态码

1.方法

💗方法:使用Spring MVC内置对象HttpServletResponse提供的setStatus方法进行设置


💛Spring MVC会根据我们方法的返回结果自动设置响应状态码,当然我们也可以手动指定状态码


💚注意这里的状态码并不影响页面的展示,就算你的状态码是401,也会显示你设置的内容

2.后端代码
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 "设置状态码";}
}
3.观察浏览器效果

(6)设置Content-Type

1.方法

💗方法:通过设置@RequestMapping里produces属性的值,来设置响应的报头Content-Type


2.后端代码
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}";}
}
3.观察浏览器效果

(7)自行设置Header

💗方法:通过内置对象HttpServletResponse里setHeader方法来设置响应的报头

相关文章:

Spring Web MVC入门

一&#xff1a;了解Spring Web MVC (1)关于Java开发 &#x1f31f;Java开发大多数场景是业务开发 比如说京东的业务就是电商卖货、今日头条的业务就推送新闻&#xff1b;快手的业务就是短视频推荐 (2)Spring Web MVC的简单理解 &#x1f497;Spring Web MVC&#xff1a;如何使…...

【C++】mapset的底层结构 -- AVL树(高度平衡二叉搜索树)

前面我们对 map / multimap / set / multiset 进行了简单的介绍&#xff0c;可以发现&#xff0c;这几个容器有个共同点是&#xff1a;其底层都是按照二叉搜索树来实现的。 但是二叉搜索树有其自身的缺陷&#xff0c;假如往树中插入的元素有序或者接近有序&#xff0c;二叉搜索…...

吴恩达《机器学习》1-4:无监督学习

一、无监督学习 无监督学习就像你拿到一堆未分类的东西&#xff0c;没有标签告诉你它们是什么&#xff0c;然后你的任务是自己找出它们之间的关系或者分成不同的组&#xff0c;而不依赖于任何人给你关于这些东西的指导。 以聚类为例&#xff0c;无监督学习算法可以将数据点分成…...

一个简单的注册页面,如有错误请指正(2.css)

这段CSS代码定义了页面的样式&#xff0c;让我逐个解释其功能&#xff1a; 1. * {}&#xff1a;通配符选择器&#xff0c;用于将页面中的所有元素设置统一的样式。这里将margins和paddings设置为0&#xff0c;以去除默认的边距。 2. div img {}&#xff1a;选择页面中所有div…...

【Unity精华一记】特殊文件夹

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…...

Node.js中的单线程服务器

为了解决多线程服务器在高并发的I/O密集型应用中的不足&#xff0c;同时避免早期简单单线程服务器的性能障碍&#xff0c;Node.js采用了基于"事件循环"的非阻塞式单线程模型&#xff0c;实现了如下两个目标&#xff1a; &#xff08;1&#xff09;保证每个请求都可以…...

如何删除数组中的某个元素?

如何删除数组中的某个元素&#xff1f; 例&#xff1a;给你一个数组 nums 和一个值 val&#xff0c;你需要移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 三种方法 1.元素前移&#xff08;时间复杂度&#xff1a;O(N^2)&#xff0c;空间复杂度&#x…...

Apache ActiveMQ RCE漏洞复现(CNVD-2023-69477)

0x01 产品简介 ActiveMQ是一个开源的消息代理和集成模式服务器&#xff0c;它支持Java消息服务(JMS) API。它是Apache Software Foundation下的一个项目&#xff0c;用于实现消息中间件&#xff0c;帮助不同的应用程序或系统之间进行通信。 0x02 漏洞概述 Apache ActiveMQ 中存…...

【BUG】Nginx转发失败解决方案

最近在做项目的时候出现了一个问题&#xff0c;琢磨了好久&#xff0c;来浅浅记录一下。 这个项目后端使用的是gateway网关和nacos实现动态的路由&#xff0c;前端使用nginx来管理前端资源&#xff0c;大体流程&#xff1a;浏览器发起请求&#xff0c;经过nginx代理&#xff0c…...

综合OA管理系统源码 OA系统源码

综合OA管理系统源码 OA系统源码 功能介绍&#xff1a; 编号&#xff1a;LQ10 一&#xff1a;系统管理 系统配置&#xff0c;功能模块&#xff0c;功能节点&#xff0c;权限角色&#xff0c;操作日志&#xff0c;备份数据&#xff0c;还原数据 二&#xff1a;基础数据 审批…...

9-MySQL提高数据管理效率(分库分表实践)

MySQL提高数据管理效率&#xff08;分库分表实践&#xff09; 在当今的互联网时代&#xff0c;随着业务规模的不断扩大&#xff0c;数据量也呈现出爆炸性的增长。如何有效地管理和存储这些数据&#xff0c;以及提高数据库的性能和可扩展性&#xff0c;成为了一个迫切需要解决的…...

经典卷积神经网络 - NIN

网络中的网络&#xff0c;NIN。 AlexNet和VGG都是先由卷积层构成的模块充分抽取空间特征&#xff0c;再由全连接层构成的模块来输出分类结果。但是其中的全连接层的参数量过于巨大&#xff0c;因此NiN提出用1*1卷积代替全连接层&#xff0c;串联多个由卷积层和“全连接”层构成…...

leetcode_2558 从数量最多的堆取走礼物

1. 题意 给定一个数组&#xff0c;每次从中取走最大的数&#xff0c;返回开根号向下取整送入堆中&#xff0c;最后计算总和。 从数量最多的堆取走礼物 2. 题解 直接用堆模拟即可 2.1 我的代码 用了额外的空间O( n ) priority_queue会自动调用make_heap() 、pop_heap() c…...

01. 嵌入式与人工智能是如何结合的?

CPU是Arm A57的 GPU是128cuda核 一.小车跟踪的需求和设计方法 比如有一个小车跟踪的项目。 需求是&#xff1a;小车识别出罪犯&#xff0c;然后去跟踪他。方法&#xff1a;摄像头采集到人之后传入到开发板&#xff0c;内部做一下识别&#xff0c;然后控制小车去跟随。在人工智…...

vue3.0运行npm run dev 报错Cannot find module node:url

vue3.0运行npm run dev 报错Cannot find module 问题背景 近期用vue3.0写项目&#xff0c;npm init vuelatest —> npm install 都正常,npm run dev的时候报错如下&#xff1a; failed to load config from F:\code\testVue\vue-demo\vite.config.js error when starting…...

26. 删除排序数组中的重复项、Leetcode的Python实现

博客主页&#xff1a;&#x1f3c6;看看是李XX还是李歘歘 &#x1f3c6; &#x1f33a;每天分享一些包括但不限于计算机基础、算法等相关的知识点&#x1f33a; &#x1f497;点关注不迷路&#xff0c;总有一些&#x1f4d6;知识点&#x1f4d6;是你想要的&#x1f497; ⛽️今…...

荣耀推送服务消息分类标准

前言 为了提升终端用户的推送体验、营造良好可持续的通知生态&#xff0c;荣耀推送服务将对推送消息进行分类管理。 消息分类 定义 荣耀推送服务将根据应用类型、消息内容和消息发送场景&#xff0c;将推送消息分成服务通讯和资讯营销两大类别。 服务通讯类&#xff0c;包…...

[数据结构]-二叉搜索树

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。 目录 一、二叉搜…...

力扣每日一题79:单词搜索

题目描述&#xff1a; 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格…...

ChatGPT如何应对用户提出的道德伦理困境?

ChatGPT在应对用户提出的道德伦理困境时&#xff0c;需要考虑众多复杂的因素。道德伦理问题涉及到价值观、原则、社会和文化背景&#xff0c;以及众多伦理理论。ChatGPT的设计和应用需要权衡各种考虑因素&#xff0c;以确保它不仅提供有用的信息&#xff0c;而且遵循伦理标准。…...

SpringBoot运行流程源码分析------阶段三(Spring Boot外化配置源码解析)

Spring Boot外化配置源码解析 外化配置简介 Spring Boot设计了非常特殊的加载指定属性文件&#xff08;PropertySouce&#xff09;的顺序&#xff0c;允许属性值合理的覆盖&#xff0c;属性值会以下面的优先级进行配置。home目录下的Devtool全局设置属性&#xff08;~/.sprin…...

环形链表-力扣

一、题目描述 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 二、题解 解题思路&#xff1a; 快慢指针&#xff0c;即慢指针一次走一步&#xff0c;快指针一次走两步&#xff0c;两个指针从链表起始位置开始运行&#xff0c;…...

人生岁月年华

人生很长吗&#xff1f;不知道。只知道高中坐在教室里&#xff0c;闹哄哄的很难受。也记得上班时无聊敲着代码也很难受。 可是人生也不长。你没有太多时间去试错&#xff0c;你没有无限的时间精力去追寻你认为的高大上。 人生是何体验呢&#xff1f;人生的感觉很多吧。大多数…...

电脑QQ如何录制视频文件?

听说QQ可以录制视频&#xff0c;还很方便&#xff0c;请问该如何录制呢&#xff1f;是需要先打开QQ才可以录制吗&#xff1f;还是可以直接使用快捷键进行录制呢&#xff1f;录制的质量又如何呢&#xff1f; 不要着急&#xff0c;既然都打开这篇文章看了&#xff0c;那小编今天…...

python:多波段遥感影像分离成单波段影像

作者:CSDN @ _养乐多_ 在遥感图像处理中,我们经常需要将多波段遥感影像拆分成多个单波段图像,以便进行各种分析和后续处理。本篇博客将介绍一个用Python编写的程序,该程序可以读取多波段遥感影像,将其拆分为单波段图像,并保存为单独的文件。本程序使用GDAL库来处理遥感影…...

天堂2游戏出错如何解决

运行游戏时出现以下提示&#xff1a;“the game may not be consistant because AGP is deactivated please activate AGP for consistancy” 这个问题的原因可能是由于您的显示卡的驱动或者主板的显示芯片组的驱动不是新开。或您虽然已经更新了您的显示卡的驱动程序&#xff0…...

『力扣刷题本』:合并两个有序链表(递归解法)

一、题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#x…...

C++设计模式_12_Singleton 单件模式

在之前的博文C57个入门知识点_44&#xff1a;单例的实现与理解中&#xff0c;已经详细介绍了单例模式&#xff0c;并且根据其中内容&#xff0c;单例模式已经可以在日常编码中被使用&#xff0c;本文将会再做梳理。 Singleton 单件模式可以说是最简单的设计模式&#xff0c;但由…...

67 内网安全-域横向smbwmi明文或hash传递

#知识点1: windows2012以上版本默认关闭wdigest&#xff0c;攻击者无法从内存中获取明文密码windows2012以下版本如安装KB2871997补丁&#xff0c;同样也会导致无法获取明文密码针对以上情况&#xff0c;我们提供了4种方式解决此类问题 1.利用哈希hash传递(pth&#xff0c;ptk等…...

面向对象(类/继承/封装/多态)详解

简介: 面向对象编程&#xff08;Object-Oriented Programming&#xff0c;OOP&#xff09;是一种广泛应用于软件开发的编程范式。它基于一系列核心概念&#xff0c;包括类、继承、封装和多态。在这篇详细的解释中&#xff0c;我们将探讨这些概念&#xff0c;并说明它们如何在P…...