SpringWebMVC是基于ServletAPI构建的原始Web框架,从⼀开始就包含在Spring框架中。
MVC是ModelViewController的缩写,它是软件⼯程中的⼀种软件架构设计模式,它把软件系统分为模型、视图和控制器三个基本部分
Spring在实现MVC时,也结合⾃⾝项⽬的特点,做了⼀些改变:
学习SpringMVC重点也就是学习如何通过浏览器和⽤⼾程序进⾏交互
主要分以下三个⽅⾯:
建⽴连接:将⽤⼾/浏览器和Java程序连接起来,也就是访问⼀个地址能够调⽤到我们的Spring程序
请求:⽤⼾请求的时候会带⼀些参数,在程序中要想办法获取到参数,所以请求这块主要是获取参数的功能
响应:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤⼾,也就是响应
在SpringMVC中使⽤ @RequestMapping 来实现URL路由映射
创建⼀个UserController类:
@RestController
public class HelloController {
@ResponseBody
@RequestMapping("/")
public String hello() {
return "Hello,world";
}
}
效果:
@RequestMapping 是⽤来注册接⼝的路由映射的
当⽤⼾访问⼀个URL时,将⽤⼾的请求对应到程序中某个类的某个⽅法的过程就叫路由映射
@RequestMapping即可修饰类,也可以修饰⽅法:
注意:
指定GET/POST⽅法类型:
@RequestMapping(value = "/getRequest",method= RequestMethod.GET)
@RequestMapping(value = "/postRequest",method= RequestMethod.POST)
接收单个参数,在SpringMVC中直接⽤⽅法中的参数就可以
@RestController
public class HelloController {
@ResponseBody
@RequestMapping("/")
public String hello(String name) {
return "Hello,world"+name;
}
}
注意:
和接收单个参数⼀样,直接使⽤⽅法的参数接收即可
@RestController
public class HelloController {
@ResponseBody
@RequestMapping("/")
public String hello(String name,int age) {
return "Hello,world"+name+age;
}
}
注意:
前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置是不影响后端获取参数的结果
如果参数⽐较多时,⽅法声明就需要有很多形参,并且后续每次新增⼀个参数,也需要修改⽅法声明,这样不利于代码的维护
可以将这些参数封装为⼀个对象,SpringMVC可以⾃动实现对象参数的赋值
@Data
public class Person {
String name;
String sex;
int age;
}
@RestController
public class HelloController {
@ResponseBody
@RequestMapping("/")
public String hello(Person person) {
return "Hello,world person:"+ person.getName()+person.getAge()+person.getSex();
}
}
注意:
Spring会根据参数名称⾃动绑定到对象的各个属性上,如果某个属性未传递,则赋值为null(基本类型则赋值为默认初识值,⽐如int类型的属性,会被赋值为0)
SpringMVC可以⾃动绑定数组参数的赋值
@RequestMapping("/m2")
public String m2(String[] str) {
return "Hello,world str:"+ Arrays.toString(str);
}
集合参数:和数组类似,需要使⽤ @RequestParam 绑定参数关系
默认情况下,请求中参数名相同的多个值,是封装到数组;如果要封装到集合,要使⽤@RequestParam 绑定参数关系
@RequestMapping("/m3")
public String m3(@RequestParam List<String> str) {
return "Hello,world str:"+ str;
}
JSON的语法:
JSON优点:
基于以上特点,JSON在Web应⽤程序中被⼴泛使⽤,如前后端数据交互、API接⼝数据传输等
接收JSON对象,需要使⽤ @RequestBody 注解:
@RequestMapping("/m4")
public String m4(@RequestBody Person person) {
return "Hello,world person:"+ person;
}
前端传递的参数key和我们后端接收的key可以不⼀致,可以使⽤ @RequestParam 来重命名前后端的参数值,进行构建映射关系
@ResponseBody
@RequestMapping("/m1")
public String m1(@RequestParam("name") String str) {
return "Hello,world name:"+ str;
}
注意:
分析注解:
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
@AliasFor("name")
String value() default "";
@AliasFor("value")//起别名
String name() default "";
boolean required() default true;//默认开启必传
String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";//默认数值
}
设置非必传参数:
@RequestMapping("/m1")
public String m1(@RequestParam(value = "name",required = false) String str) {
return "Hello,world name:"+ str;
}
pathvariable:路径变量
和字⾯表达的意思⼀样,这个注解主要作⽤在请求URL路径上的数据绑定
@RequestMapping("/m5/{name}/{id}")
public String m5(@PathVariable Integer id, @PathVariable("name") String username) {
return "Hello,world person:"+ id+username;
}
如果⽅法参数名称和需要绑定的URL中的变量名称⼀致时,可以简写,不⽤给@PathVariable的属性赋值,否则需要@PathVariable的属性value赋值
上传⽂件使用@RequestPart 注解
@RequestMapping("/m6")
public String m6(@RequestPart MultipartFile file) throws IOException {
String fileName = file.getOriginalFilename();
file.transferTo(new File("C:\\Users\\HP\\Desktop\\"+fileName));
return "接收文件名称:"+fileName;
}
Cookie和Session的区别:
传统获取Cookie:
@RequestMapping("/m8")
public String m8(HttpServletRequest request, HttpServletResponse response) {
Cookie[] cookies = request.getCookies();
StringBuilder builder = new StringBuilder();
if(cookies!=null) {
for (Cookie ck:cookies) {
builder.append(ck.getName()+":"+ck.getValue());
}
}
return "Cookie:"+builder;
}
简洁获取Cookie:
@RequestMapping("/m8")
public String m9(@CookieValue("test") String test) {
return "Cookie:"+test;
}
获取Session:
Session是服务器端的机制,我们需要先存储,才能再获取;Session也是基于HttpServletRequest来存储和获取的
@RequestMapping("/m9")
public String m9(HttpServletRequest request) {
HttpSession session = request.getSession();
if(session!=null) {
session.setAttribute("test","hello");
}
return "session set";
}
@RequestMapping("/m10")
public String m10(HttpSession session) {
return "session:"+session.getAttribute("test");
}
说明:
简洁获取Session:
@RequestMapping("/m11")
public String m11(@SessionAttribute(value = "username",required = false) String name) {//获取指定key
return "session:"+name;
}
public String m10(HttpSession session) {
return "session:"+session.getAttribute("test");
}
获取Header也是从 HttpServletRequest 中获取
@RequestMapping("/param10")
public String param10(HttpServletRequest request, HttpServletResponse response)
String userAgent = request.getHeader("User-Agent");
return name + ":"+userAgent;
}
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String userAgent) {
return "userAgent:"+userAgent;
}
Http响应结果可以是数据,也可以是静态⻚⾯,也可以针对响应设置状态码,Header信息等
@Controller
public class IndexController {
@RequestMapping("/index")
public Object index(){
//返回index.html
return "/index.html";
}
}
@RestController = @Controller + @ResponseBody
@Controller :定义⼀个控制器,Spring框架启动时加载,把这个对象交给Spring管理
@ResponseBody :定义返回的数据格式为⾮视图,返回⼀个text/html信息
如果想返回视图的话,只需要把 @ResponseBody 去掉就可以了,也就是 @Controller
@ResponseBody 表⽰返回数据
@ResponseBody 既是类注解,⼜是⽅法注解:
后端返回数据时,如果数据中有HTML代码,也会被浏览器解析
响应中的Content-Type常⻅取值有以下⼏种:
如果请求的是js⽂件,SpringMVC会⾃动设置Content-Type为 application/javascript
如果请求的是css⽂件,SpringMVC会⾃动设置Content-Type为 text/css
SpringMVC也可以返回JSON,后端⽅法返回结果为对象
@RequestMapping("/returnJson")
@ResponseBody
public HashMap<String, String> returnJson() {
HashMap<String, String> map = new HashMap<>();
map.put("Java", "Java Value");
map.put("MySQL", "MySQL Value");
map.put("Redis", "Redis Value");
return map;
}
SpringMVC会根据我们⽅法的返回结果⾃动设置响应状态码,程序员也可以⼿动指定状态码
通过SpringMVC的内置对象HttpServletResponse提供的⽅法来进⾏设置
@RequestMapping(value = "/setStatus")
@ResponseBody
public String setStatus(HttpServletResponse response) {
response.setStatus(401);
return "设置状态码成功";
}
状态码不影响⻚⾯的展⽰
Http响应报头也会向客⼾端传递⼀些附加信息,⽐如服务程序的名称,请求的资源已移动到新地址等,如:Content-Type,Local等
通过 @RequestMapping 注解的属性来实现
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
说明:
通过设置produces属性的值,设置响应的报头Content-Type
@RequestMapping(value = "/returnJson2",produces = "application/json")
@ResponseBody
public String returnJson2() {
return "{\"success\":true}";
}
如果不设置produces,⽅法返回结果为String时,SpringMVC默认返回类型,是text/html
@RequestMapping(value = "/returnJson2",produces = "application/json;charset=ut
@ResponseBody
public String returnJson2() {
return "{\"success\":true}";
}
使⽤SpringMVC的内置对象HttpServletResponse提供的⽅法来进⾏设置
@RequestMapping(value = "/setHeader")
@ResponseBody
public String setHeader(HttpServletResponse response) {
response.setHeader("MyHeader","MyHeaderValue");
return "设置Header成功";
}
设置⼀个带有给定的名称和值的header,如果name已经存在,则覆盖旧的值
返回类型,是text/html
@RequestMapping(value = "/returnJson2",produces = "application/json;charset=ut
@ResponseBody
public String returnJson2() {
return "{\"success\":true}";
}
使⽤SpringMVC的内置对象HttpServletResponse提供的⽅法来进⾏设置
@RequestMapping(value = "/setHeader")
@ResponseBody
public String setHeader(HttpServletResponse response) {
response.setHeader("MyHeader","MyHeaderValue");
return "设置Header成功";
}
设置⼀个带有给定的名称和值的header,如果name已经存在,则覆盖旧的值