什么是Spring MVC
官方介绍
- Spring MVC是一个Web框架,具有http能力
- 构造在Servlet(API)之上的
什么是MVC
MVC是Model View Controller的缩写,他是一种设计模式,将软件系统分为模型,视图和控制器三部分。
Model:对请求进行处理
Controller:和用户进行交互,对用户请求合理性进行校验
View:返回一个页面给用户
MVC和Spring MVC的关系
MVC是一种设计思想,而Spring MVC是对MVC思想的具体实现。
总结:Spring MVC是一个实现了MVC模式,并继承了Servlet API的Web框架。
学习Spring MVC
学习Spring MVC重点掌握3个功能
- 连接功能: 将用户(浏览器)和Java程序连接起来,也就是访问一个地址就能调用我们的Spring程序
- 获取参数的功能: 用户访问的时候会带一些参数,在程序中想办法获取到参数
- 输出数据的功能: 执行业务逻辑之后,要把程序执行的结果返回给用户
Spring MVC的连接功能
在Spring MVC中使用@RequestMapping来实现URL的路由映射,也就是浏览器连接程序的作用。
java
@RequestMapping("/test") //一级路由地址
@Controller //让框架在启动的时候加载当前类,别人才能访问
@ResponseBody //让程序返回的是一个数据而不是页面
public class TestController {
@RequestMapping("/hi") //二级路由地址
public String sayHi() {
return "hi Spring MVC";
}
}
注意:以前没有前后端分离,所以需要Java程序员也要返回页面(也就是MVC中的视图),随着时代的进步,MVC中的视图被Spring MVC屏蔽了,使用@ResponseBody实现只返回数据的功能。
@RequestMapping 即是get请求也是post请求
在有些公司对隐私性要求比较高,就会要求不能使用get请求,统一使用post请求,这种情况要怎么处理呢?
java
@RequestMapping(value = "/hi", method = RequestMethod.POST)
表示当前方法只支持post请求
除了上面方法还可以通过@PostMapping来实现
获取参数
传递基础类型参数
java
@RequestMapping("/test") //路由地址
@Controller //让框架在启动的时候加载当前类,别人才能访问
@ResponseBody //让程序返回的是一个数据而不是页面
public class TestController {
//表示当前方法只支持post请求
@RequestMapping(value = "/hi")
public String sayHi(String name, Integer age) {
return "hi," + name + " age: " + age;
}
}
参数的位置不用对应,但是参数的名字要对应。
在Spring MVC中传参一定要使用包装类,而非基础类型
因为:当形参是一个基础类型,如果请求中忘记传递这个参数,使用基础类型就会报500错误,而类型包装不会报错,只是值为null
后端参数重命名@RequestParam
在某些情况下,前端传递的参数key和后端接收的key可以不一致,比如前端的命名为time,而后端要求要用createtime字段来接收。这样就会出现参数接收不到的情况,为此我们可以使用@RequestParam来重命名前后端的参数值
java
@RequestMapping("/test") //路由地址
@Controller //让框架在启动的时候加载当前类,别人才能访问
@ResponseBody //让程序返回的是一个数据而不是页面
public class TestController {
@RequestMapping("/show-time")
public String showTime(@RequestParam("t1") String start,
@RequestParam("t2") String end) {
return "开始时间:" + start + "| 结束时间:" + end;
}
}
非必传参数设置
如果我们的业务中前端的参数是一个非必传的参数,我们就可以通过设置@RequestParam中的 required=false来避免不传递时报错。
java
@RequestMapping("/test") //路由地址
@Controller //让框架在启动的时候加载当前类,别人才能访问
@ResponseBody //让程序返回的是一个数据而不是页面
public class TestController {
@RequestMapping("/show-time")
public String showTime(@RequestParam("t1",, required = false) String start,
@RequestParam("t2") String end) {
return "开始时间:" + start + "| 结束时间:" + end;
}
}
传递对象
如果前端需要传递多个参数,在使用上面的方法就很麻烦要写多个参数,就算你能写多个参数,此时需求要你增加或减少参数,参数那么多就可能造成参数多或参数少,很难发现。此时就需要传递参数来解决。将前端要传的参数包装成一个对象,此时参数就只有这个对象。至于这么多参数怎么变成一个对象是框架帮你完成
接收JSON对象
使用@RequestBody接收JSON对象,在和第三方系统通讯时的常见场景(双方使用的语言不同,需要通过JSON来进行交互)
java
@RequestMapping("/test") //路由地址
@Controller //让框架在启动的时候加载当前类,别人才能访问
@ResponseBody //让程序返回的是一个数据而不是页面
public class TestController {
@RequestMapping("/json")
public String showJson(@RequestBody User user) {
return user.toString();
}
}
获取URL的参数 @PathVariable
举个例子:localhost:8080/login?username=zhangsan&password=1234获取参数是从?开始根据key值来获取value。由于?后面的键值对动态改变的,SEO效果比较差.
SEO是一种搜索引擎优化的方式,利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。
而如果把上面的url写成localhost:8080/login/zhangsan/1234,搜索引擎就会认为这是一个固定地址,SEO效果更佳。那要怎么获取这个url的参数呢?
java
@RequestMapping("/login/{username}/{password}")//位置一定要正确
public String login(@PathVariable("username") String name,
@PathVariable("password") String password) {
return name + ": " + password;
}
上传文件 @RequestPart
java
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/upfile")
public String upfile(@RequestPart("myfile")MultipartFile file) throws IOException {
//根目录
String path = "D:\\javaee_advanced\\Test.2023.5.30\\";
//根目录 + 唯一的文件名(使用UUID生成随机数)
path += UUID.randomUUID().toString().replace("-", "");
//再加上文件的后缀
path += file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
//保存文件
file.transferTo(new File(path));
return path;
}
}
使用postman实现上传一个文件
获取Cookie
在servlet时期,我们是使用HttpServletRequest和HttpServletResponse来获取,在Spring MVC同样适用,可以直接使用。
java
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/getck")
public String getCookie(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for (Cookie item :
cookies) {
//通过日志来打印
log.error(item.getName() + ": " + item.getValue());
}
return "get cookie";
}
}
如果直接输入网址访问,会报空指针异常,所以需要自己造cookie
上面的代码是获取所有的cookie,在Spring mvc中可以使用**@CookieValue **来获取单个cookie
java
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/getSingleCookie")
public String getCookie(@CookieValue("zhangsan") String value) {
return "Cookie Value: " + value;
}
}
获取header
使用Servlet时期的HttpServletRequest来实现
java
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/header1")
public String getHeader1(HttpServletRequest request) {
String header = request.getHeader("User-Agent");
return header;
}
}
在Spring MVC中可以使用 @RequestHeader 实现获取header头。
java
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/header2")
public String getHeader2(@RequestHeader("User-Agent") String header) {
return header;
}
}
获取session
使用HttpServletRequest实现session的存和取
java
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/setsess")
public String setSession(HttpServletRequest request) {
HttpSession session = request.getSession(true);//没有session就新建
session.setAttribute("userinfo", "用户信息");//设置session的键值对
return "set session success";
}
}
java
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/getsess")
public String getSession(HttpServletRequest request) {
HttpSession session = request.getSession(false);//没有session不新建
if(session != null && session.getAttribute("userinfo") != null) {
return (String) session.getAttribute("userinfo");
}
return "暂无session信息";
}
}
在Spring MVC中可以使用 @SessionAttribute获取Session
java
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@RequestMapping("/getsess2")
public String getSession2(@SessionAttribute(value = "userinfo", required = false) //设置非必传,防止报500
String userinfo) {
return userinfo;
}
}
返回数据
返回静态页面
java
@Controller
@RequestMapping("/resp")
//不添加@Responsebody 表示返回的是页面
public class RespController {
@RequestMapping("/index")
public Object index() {
return "/index.html";
}
}
返回JSON对象
java
@Controller
@RequestMapping("/resp")
public class RespController {
@RequestMapping("/json")
@ResponseBody //表示返回的不是页面,是数据
public HashMap<String, String> returnJson() {
HashMap<String, String> map = new HashMap<>();
map.put("java", "java value");
map.put("mysql", "mysql value");
map.put("spring", "spring value");
return map;
}
}
从哈希表变成json格式的操作是框架帮我们完成的
我们使用Fiddler抓包看看,返回的格式是不是json
请求转发和请求重定向
- forward: 请求转发
- redirect: 请求重定向
java
@Controller
@RequestMapping("/resp")
//不添加@Responsebody 表示返回的是页面
public class RespController {
//请求重定向
@RequestMapping("/redirect")
public String index1() {
return "redirect:/index.html";
}
//请求转发
@RequestMapping("/forward")
public String index2() {
return "forward:/index.html";
}
}
请求转发是服务器帮你转发,转发的地址不发生改变,有可能造成外部资源不能访问的问题。
而请求重定向是重新定位访问资源,转发的地址会发生改变,和访问新地址效果一样。