SpringMVC是Spring框架后续开发的web模块.主要负责前后端数据交换.其基于Servlet进行开发的框架,目的简化前后端的调用.
请求类型一共8种,但是常用的有4种(get/post/put/delete)
@RequestBody 接收前端自定义对象的参数
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式
可参考Json官网:http://www.json.org.cn/
JSON数据格式:
①JSON格式-对象格式: {"id": "100","name": "tomcat", "age": "18"}
②JSON格式-数组格式: [100,"张三",true]
JSON可以嵌套,值(value) 可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。这些结构可以嵌套。
Axios封装了Ajax,
功能和作用: Ajax主要实现前后端交互.提高用户页面与服务器之间交互效率.promise是Axios封装服务器返回值的对象
特点: 局部刷新,异步访问
缺点:不同的服务器之间发送ajax请求时会有"跨域"问题,通过注解搞定. @CrossOrigin
注意: axios为了接收后端服务器数据,利用promise对象封装后端服务器数据参数
Ajax异步的原理:
1. 由Ajax引擎直接访问后端服务器。
2. 在回调函数没有执行之前,用户可以执行自己的任务。 异步回调地狱优化-async-await
同源策略:
浏览器URL中的地址/Ajax请求的URL地址必须满足 协议/域名/端口号都相同时.表示满足同源策略.如果满足同源策略,则称之为 “同域访问” 反之称之为 “跨域访问” 跨域访问浏览器一般都会报错(浏览器默认端口号是http80,https443,localhost!=127.0.0.1)跨域解决方案:
1.jsonp 方式跨域 淘汰了.
2.CORS 跨域资源共享:CORS要求在服务器端标识哪个网址可以跨域
@CrossOrigin(value="http://www.baidu.com")表示只准许该网址http://www.baidu.com访问
SpringMVC调用流程:
1. 用户发起请求之后,第一步访问就是前端控制器.
2. 前端控制器只负责请求的转发/响应. 没有办法直接处理业务.
3.当SpringMVC容器启动时,处理器映射器首先会加载所有的@RequestMapping注解.将请求路径与方法进行绑定.保存到Map中. Map, 当前端控制器发送请求被处理器映射器接收.①如果URL地址匹配,则告知应该执行哪个方法.②如果url地址不匹配.,则提示用户4044.前端控制器得知将要执行的方法是谁,但是前端控制只能转发,没有办法执行业务.
所以请求处理器适配器执行业务逻辑.5.处理器适配器针对配置文件(xml方式/注解方式/其它方式)的格式,挑选合适的处理器去执行业务逻辑. 业务执行成功之后返回ModelAndView对象 Model:业务数据 View:页面
历史版本: 需要返回页面名称,及将数据填充到页面中
6. 前端控制器接收到返回的ModelAndView之后,交给视图解析器去解析数据. 视图解析器通过自身的配置获取页面的名称 (/web/user.html).
7. 最终通过经过视图渲染,将数据填充到页面中.最终用户看到的页面就包含了业务数据.前后端分离方式:
关键用法: @ResponseBody 要求返回业务数据并且转化为JSON串. 程序直接跳过6-7直接将数据返回给用户.
url格式如: http://localhost:8080/findUser?name=tomcat&age=18&sex=男
http://localhost:8080/user/saveHobby?hobby=篮球,排球,乒乓球
Axios测试
Axios测试案例-1
@RestController
@CrossOrigin //主要解决跨域问题
@RequestMapping("/axios")
public class AxiosController {
//@RequestParam("id")该注解主要考虑向前兼容,JDK1.5倩是需要加的
@RequestMapping("/getUserById")
public User getUserById(@RequestParam("id") Integer id){
//根据ID查询数据库
User user = new User();
user.setId(id);
user.setName("好好学习");
user.setAge(1000);
user.setSex("男");
return user;
}
@RequestMapping("/findJSON")
public User findJSON(User user){
//在业务层扩展数据
user.setId(101);
user.setSex("男");
return user;
}
@RequestMapping("/getUserByNA")
public List getUserByNA(User user){
List list = new ArrayList<>();
list.add(user);//简化赋值操作 直接返回
list.add(user);
return list;
}
服务端:
当方法return的类型为自定义对象或集合时,
springMVC框架会自动将集合或对象转成son格式的字符串然后将字符串再转成二进制数据通过网络传输给客户端
客户端:
服务器返回的是二进制数据,会先将二进制数据转成son格式的字符串
然后axios框架会将JSON格式的字符串再转成数组里面装对象
Axios测试
Axios测试案例-2
@RestController
@CrossOrigin //主要解决跨域问题
@RequestMapping("/axios")
public class AxiosController {
@RequestMapping("/getUserById")
public User getUserById(Integer id){
int a = 100;
//根据ID查询数据库
User user = new User();
user.setId(id);
user.setName("好好学习");
user.setAge(1000);
user.setSex("男");
return user;
}
@RequestMapping("/getUserByNA")
public List getUserByNA(User user){
List list = new ArrayList<>();
list.add(user);//简化赋值操作 直接返回
list.add(user);
return list;
}
@RequestMapping("/findUserByNS/{name}/{sex}") //调用set方法为属性赋值
public List findUserByNS(User user){
List list = new ArrayList<>();
list.add(user);
list.add(user);
return list;
}
//@RequestMapping(value="/saveUser",method = RequestMethod.POST)
@PostMapping("/saveUser")
public String saveUser(@RequestBody User user){
System.out.println(user);
return "新增用户成功!!!";
}
}
restFul风格方式提交数据一般用于更新操作
url格式如: http://localhost:8080/findUser/tomcat/18/男
要求: restFul的风格数据的位置一旦确定,不能修改.
注意: restFul风格请求支持常用的4种请求类型(get/post/put/delete),
但是为了数据安全问题一般不使用post请求
Axios测试
Axios测试案例-1
@RequestMapping("/findUser/{name}/{age}/{sex}")
public String findUser(@PathVariable String name,
@PathVariable int age,
@PathVariable String sex){
return name+":"+age+":"+sex;
}
/**注意:如果{ }的属性与对象的属性名称一致则可以使用对象接收 */
@RequestMapping("/findUserByNS/{name}/{sex}") //调用set方法为属性赋值
public List findUserByNS(User user){
List list = new ArrayList<>();
list.add(user);
list.add(user);
return list;
}
@Controller
将类交给SpringMVC管理,SpringMVC交给Spring容器管理JSON串与对象之间的相互转化
1.@ResponseBody
①如果返回的是对象,将返回对象转化为JSON串到前端
②如果返回String类型,则@ResponseBody将字符串本身返回给前端.
2.@RequestBody JSON串转化为User
要求: JSON串转化 要求json串中的属性与对象中的属性一致,并且赋值时调用对象的set方法@RestController public class WeiboController { @Autowired(required = false) WeiboMapper mapper; @RequestMapping("/insert") public void insert(@RequestBody Weibo weibo){ //由于客户端提交的参数不是FormData对象了 是一个自定义的对象 // 需要通过@RequestBody注解修饰接收数据的参数 System.out.println("weibo = " + weibo); mapper.insert(weibo); } }
@RestController
等同于@Controller + @ResponseBody
@RequestMapping
负责用户的请求路径与后台服务器之间的映射关系
可以支持任意类型的请求. 但是这样的写法不安全
对应请求使用如下注解:新增: post请求类型 @PostMapping("")
删除: delete请求类型 @DeleteMapping("")
修改: put请求类型 @PutMapping("")
查询: get请求类型 @GetMapping("")@PathVariable
接收RestFul风格数据时,利用@PathVariable注解,动态获取路径中的数据,要求名称必须匹配
- 405 异常 ajax的请求类型与后端接收的请求类型不匹配.
- 400异常 参数类型不匹配
- 404异常 请求路径找不到
- 403异常 后端未对请求进行处理
客户端和服务器之间进行数据交互,遵循的是HTTP协议,此协议属于无状协议(一次请求对应一次响应)响应完连接断开,服务器无法跟踪客户端的请求,通过会话管理中的Cookie技术,可以在客户端向服务器发出请求时服务器给客户端添加一个标识(把数据保存到这个标识里面) , 之后客户端每次发出请求时都会带上这个标识,这样服务器通过此标识就能识别出该客户端的信息, 但是这种把数据保存在客户端的方式存在数据被篡改的风险,Session的作用就是能够解决这种问题, 因为Session的数据是保存在服务器端,不存在被篡改的问题.
Cookie: 数据保存在客户端,类似打孔式的会员卡
- 只能保存字符串类型的数据
- 保存时长: 默认保存在浏览器内存中, 浏览器关闭时清除, 也可以设置任意的保存时长,设置后数据会保存到客户端磁盘中,时间到了后清除.
- 应用场景: 长时间保存的数据使用Cookie,比如记住用户名和密码
Session: 数据保存在服务器端, 类似银行卡
- 可以保存任意对象类型的数据
- 保存时长: 只能保存半小时左右
- 应用场景: 对数据安全性要求比较高并且是短时间保存的,比如登录状态
@RestController
public class UserController {
@Autowired(required = false)
UserMapper mapper;
@RequestMapping("/login")
public int login(@RequestBody User user, HttpSession session, HttpServletResponse response){
System.out.println("user = " + user);
User u = mapper.selectByUsername(user.getUsername());
if (u!=null){
if (u.getPassword().equals(user.getPassword())){
//登录成功后把从数据库里面查询到的用户对象保存到Session会话对象中
session.setAttribute("user",u);
//判断是否需要记住用户名和密码
if (user.isRem()){
//创建Cookie记住用户名和密码
Cookie c1 = new Cookie("username",user.getUsername());
Cookie c2 = new Cookie("password",user.getPassword());
//设置Cookie保存数据的时长
c1.setMaxAge(60*60*24*30);
//把cookie下发给客户端
response.addCookie(c1);
response.addCookie(c2);
}
return 1;
}
return 3;
}
return 2;
}
@RequestMapping("/currentUser")
public User currentUser(HttpSession session){
//获取登录成功时保存的用户对象
return (User) session.getAttribute("user");
}
@RequestMapping("/logout")
public void logout(HttpSession session){
//删除登录成功时保存的用户对象
session.removeAttribute("user");
}
}
Title
登录页面
@RestController
public class UploadController {
@RequestMapping("/upload")
public String upload(MultipartFile picFile) throws IOException {
//得到原始文件名
String fileName = picFile.getOriginalFilename();
//得到后缀 .jpg
String suffix = fileName.substring(fileName.lastIndexOf("."));
//得到唯一文件名 UUID.randomUUID()获取唯一标识符
fileName = UUID.randomUUID()+suffix;
System.out.println("文件名:"+fileName);
//保存图片的文件夹
String dirPath = "D:/file";
File dirFile = new File(dirPath);
//判断如果文件夹不存在 则创建文件夹
if (!dirFile.exists()){
dirFile.mkdirs();//创建文件夹
}
//准备一个完整的文件路径
String filePath = dirPath+"/"+fileName;
//把上传的文件保存到上面指定的路径 异常抛出
picFile.transferTo(new File(filePath));
//把图片在服务器中的路径返回给客户端
return "/"+fileName;
}
@RequestMapping("/remove")
public void remove(String name){
//文件夹路径
String dirPath = "D:/file";
//得到文件的完整路径
String file = dirPath+name;
System.out.println("删除的文件路径:"+file);
//删除服务器中的文件
new File(file).delete();
}
}
#配置静态资源文件夹 默认的是static文件夹
spring.web.resources.static-locations=file:D:/file,classpath:static
#设置单个上传文件的大小
spring.servlet.multipart.max-file-size=10MB
#设置批量上传文件的总大小
spring.servlet.multipart.max-request-size=100MB