SpringMVC简介及实用接收请求方式
SpringMVC简介及实用接收请求方式
什么是MVC?
在 JavaEE 开发中,几乎全都是基于 B/S (浏览器服务器)架构的开发。那么在 B/S 架构中,系统标准的三层架构包括:表现层、业务层、持久层。而MVC在表现层!
SpringMVC
全名叫 Spring Web MVC,是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级
Web 框架,属于 SpringFrameWork 的后续产品。
Spring MVC和Struts2一样,都是 为了解决表现层问题 的web框架,它们都是基于 MVC 设计模
式的。这些表现层框架的主要职责就是处理前端HTTP请求。
作用:
1)接收请求
2)返回响应,跳转页面
RESTful风格
REST(Representational State Transfer)
Restful 的优点:它结构清晰、符合标准、易于理解、扩展⽅便。
原有的url设计
localhost:8080/user/queryUserById.action?id=3
有了RESTful 变成:
http://localhost:8080/user/3
RESTful风格即使请求路径相同,但状态操作(get,post,put,delete)不同,都可以请求到想要的接口。
通过项目讲解
一 springmvc-demo
1 传参方式和后台接
请求参数绑定:说白了SpringMVC如何接收请求参数?
- 单个或少数传参法
原servlet接收一个整型参数:
1)String ageStr = request.getParameter("age");
2) Integer age = Integer.parseInt(ageStr);
SpringMVC框架对Servlet的封装,简化了servlet的很多操作
SpringMVC在接收整型参数的时候,直接在Handler方法中声明形参即可
@RequestMapping("xxx")
public String handle(Integer age) {
System.out.println(age);
}
注意:
1 参数绑定:取出参数值绑定到handler方法的形参上,传递的参数名和声明的形参名称保持一致
2 对于布尔类型(Boolean)的参数, 请求的参数值只接收true或false,或者1或0
方法参数名和传递参数名不一致呢?
可以使用@RequestParam注解,如
/*
* SpringMVC 接收简单数据类型参数 url:/demo/handle03?id=1
*
* 注意:接收简单数据类型参数,直接在handler方法的形参中声明即可,框架会取出参数值然后绑定到对应参数上
* 要求:传递的参数名和声明的形参名称保持一致
*/
@RequestMapping("/handle03")
public ModelAndView handle03(@RequestParam("ids") Integer id,Boolean flag) {
Date date = new Date();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("date",date);
modelAndView.setViewName("success");
return modelAndView;
}
建议:使用包装类型,因为基础数据类型不可以为null
- url传参
@RequestMapping(value = "/handle/{id}",method ={RequestMethod.GET})
public ModelAndView handleGet(@PathVariable("id") Integer id) {
}
- 绑定Pojo类型参数
1 接收pojo类型参数,直接形参声明即可,类型就是Pojo的类型,形参名无所谓
2 但是要求传递的参数名必须和Pojo的属性名保持一致
前端代码
测试用例:SpringMVC接收pojo类型参数
<a href="/demo/handle04?id=1&name=zhangsan">点击测试</a>
后台 (注意:这里要加get set方法)
public class User {
private Integer id;
private String name;
}
public ModelAndView handle04(User user) {
Date date = new Date();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("date",date);
modelAndView.setViewName("success");
return modelAndView;
}
- SpringMVC接收pojo包装类型参数
前端代码
测试用例:SpringMVC接收pojo包装类型参数
<a href="/demo/handle05?user.id=1&user.name=zhangsan">点击测试</a>
后台(注意:这里要加get set方法)
public class QueryVo {
private String mail;
private String phone;
// 嵌套了另外的Pojo对象
private User user;
}
/\*
* SpringMVC接收pojo包装类型参数 url:/demo/handle05?user.id=1&user.username=zhangsan
* 不管包装Pojo与否,它首先是一个pojo,那么就可以按照上述pojo的要求来
* 1、绑定时候直接形参声明即可
* 2、传参参数名和pojo属性保持一致,如果不能够定位数据项,那么通过属性名 + "." 的方式进一步锁定数据
*
\*/
@RequestMapping("/handle05")
public ModelAndView handle05(QueryVo queryVo) {
Date date = new Date();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("date",date);
modelAndView.setViewName("success");
return modelAndView;
}
- @RequstBody @ResponseBody
用Ajax Json交互
1)前端到后台:前端ajax发送json格式字符串,后台直接接收为pojo参数,使用注解@RequstBody
2)后台到前端:后台直接返回pojo对象,前端直接接收为json对象或者字符串,使用注解
@ResponseBod
Spring MVC 使用 Json 交互所需jar包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
前端jsp及js代码
<h2>Ajax json交互
</h2>
$(function () {
$("#ajaxBtn").bind("click",function () {
// 发送ajax请求
$.ajax({
url: '/demo/handle07',
type: 'POST',
data: '{"id":"1","name":"李四"}',
contentType: 'application/json;charset=utf-8',
dataType: 'json',
success: function (data) {
alert(data.name);
}
})
})
})
后台controller代码
@RequestMapping("/handle07")
// 添加@ResponseBody之后,不再⾛视图解析器那个流程,⽽是等同于response直接输出
数据
public @ResponseBody User handle07(@RequestBody User user) {
// 业务逻辑处理,修改name为张三丰
user.setName("张三丰");
return user;
}
- 处理multipart形式的数据
文件上传
原生servlet处理上传的文件数据的,springmvc是对serlvet的封装
所需jar包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
1.3.1
配置文件上传解析器
前端form
<div>
<h2>multipart 文件上传</h2>
<fieldset>
<%--
1 method="post"
2 enctype="multipart/form-data"
3 type="file"
--%>
<form method="post" enctype="multipart/form-data" action="/demo/upload">
<input type="file" name="uploadFile"/>
<input type="submit" value="上传"/>
</form>
</fieldset>
</div>
注意
1 method="post" 必须是post
2 enctype="multipart/form-data"
3 type="file"
后台接收Handler
/**
* 文件上传
* @return
*/
@RequestMapping(value = "/upload")
public ModelAndView upload(MultipartFile uploadFile,HttpSession session) throws IOException {
// 处理上传文件
// 重命名,原名123.jpg ,获取后缀
String originalFilename = uploadFile.getOriginalFilename();// 原始名称
// 扩展名 jpg
String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1, originalFilename.length());
String newName = UUID.randomUUID().toString() + "." + ext;
// 存储,要存储到指定的文件夹,/uploads/yyyy-MM-dd,考虑文件过多的情况按照日期,生成一个子文件夹
String realPath = session.getServletContext().getRealPath("/uploads");
String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File folder = new File(realPath + "/" + datePath);
if(!folder.exists()) {
folder.mkdirs();
}
// 存储文件到目录
uploadFile.transferTo(new File(folder,newName));
// TODO 文件磁盘路径要更新到数据库字段
Date date = new Date();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("date",date);
modelAndView.setViewName("success");
return modelAndView;
}
- 基于Flash属性的跨重定向请求数据传递
重定向时请求参数会丢失,我们往往需要重新携带请求参数,我们可以进行动参数拼接如下:
return "redirect:handle01?name=" + name;
但是上述拼接参数的方法属于get请求,携带参数长度有限制,参数安全性也不够,此时,我们可以使用SpringMVC提供的flash属性机制,向上下行中添加flash属性,框架会在session中记录该属性值,当跳转到之后框架会自动删除flash属性,不需要我们手动删除,通过这种方式进行重定向参数传递,参数长度和安全性都得到了保障,如下:
/**
* SpringMVC 重定向时参数传递的问题
* 转发:A 找 B 借钱400,B没有钱但是悄悄的找到C借了400块钱给A
* url不会变,参数也不会丢失,一个请求
* 重定向:A 找 B 借钱400,B 说我没有钱,你找别人借去,那么A 又带着400块的借钱需求找到C
* url会变,参数会丢失需要重新携带参数,两个请求
*/
@RequestMapping("/handleRedirect")
public String handleRedirect(String name,RedirectAttributes redirectAttributes) {
//return "redirect:handle01?name=" + name; // 拼接参数安全性、参数长度都有局限
// addFlashAttribute方法设置了一个flash类型属性,该属性会被暂存到session中,在跳转到页面之后该属性销毁
redirectAttributes.addFlashAttribute("name",name);
return "redirect:handle01";
}
- 传入Map、Model和ModelMap参数,用于跳转
SpringMVC在handler方法也可以传入Map、Model和ModelMap参数,并向这些参数中保存数据(放入到请求域),都可以在页面获取到。
eg:
@RequestMapping("/handle11")
public String handle11(ModelMap modelMap) {
}
它们之间是什么关系?
- 运行时的具体类型都是BindingAwareModelMap,相当于给BindingAwareModelMap中保存的数据都会放在请求域中。