SpringMVC前后端数据交换简述

一.基本概念及知识准备:

1)基本概念

SpringMVC是Spring框架后续开发的web模块.主要负责前后端数据交换.其基于Servlet进行开发的框架,目的简化前后端的调用.
请求类型一共8种,但是常用的有4种(get/post/put/delete)

SpringMVC前后端数据交换简述_第1张图片

接收参数

@RequestBody 接收前端自定义对象的参数 

2)JSON知识回顾

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)。这些结构可以嵌套。

 3)Axios知识回顾

Axios封装了Ajax,
功能和作用: Ajax主要实现前后端交互.提高用户页面与服务器之间交互效率.

                     promise是Axios封装服务器返回值的对象
特点: 局部刷新,异步访问
缺点:
不同的服务器之间发送ajax请求时会有"跨域"问题,通过注解搞定. @CrossOrigin
注意: axios为了接收后端服务器数据,利用promise对象封装后端服务器数据参数
Ajax异步的原理:
1. 由Ajax引擎直接访问后端服务器。
2. 在回调函数没有执行之前,用户可以执行自己的任务。 异步

SpringMVC前后端数据交换简述_第2张图片

回调地狱优化-async-await


SpringMVC前后端数据交换简述_第3张图片

 

4)跨域问题

同源策略:
浏览器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访问

5)Tomcat/jetty对请求的处理

SpringMVC前后端数据交换简述_第4张图片

 二.SpringMVC底层实现原理

SpringMVC前后端数据交换简述_第5张图片

SpringMVC调用流程:


1. 用户发起请求之后,第一步访问就是前端控制器.
2. 前端控制器只负责请求的转发/响应. 没有办法直接处理业务.
3.当SpringMVC容器启动时,处理器映射器首先会加载所有的@RequestMapping注解.将请求路径与方法进行绑定.保存到Map中. Map, 当前端控制器发送请求被处理器映射器接收.①如果URL地址匹配,则告知应该执行哪个方法.②如果url地址不匹配.,则提示用户404

4.前端控制器得知将要执行的方法是谁,但是前端控制只能转发,没有办法执行业务.
所以请求处理器适配器执行业务逻辑.

5.处理器适配器针对配置文件(xml方式/注解方式/其它方式)的格式,挑选合适的处理器去执行业务逻辑. 业务执行成功之后返回ModelAndView对象 Model:业务数据 View:页面

历史版本: 需要返回页面名称,及将数据填充到页面中
6. 前端控制器接收到返回的ModelAndView之后,交给视图解析器去解析数据. 视图解析器通过自身的配置获取页面的名称 (/web/user.html).
7. 最终通过经过视图渲染,将数据填充到页面中.最终用户看到的页面就包含了业务数据.

前后端分离方式:
关键用法: @ResponseBody 要求返回业务数据并且转化为JSON串. 程序直接跳过6-7直接将数据返回给用户.

三.传统方式发送请求

1)传统get/delete方式放松请求

url格式如: http://localhost:8080/findUser?name=tomcat&age=18&sex=

                http://localhost:8080/user/saveHobby?hobby=篮球,排球,乒乓球

①前端发送 axios请求



	
		
		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格式的字符串再转成数组里面装对象

SpringMVC前后端数据交换简述_第6张图片

 2)传统post/put方式放松请求

①前端发送 axios请求



	
		
		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风格发送请求

restFul风格方式提交数据一般用于更新操作
url格式如: http://localhost:8080/findUser/tomcat/18/男
要求:  restFul的风格数据的位置一旦确定,不能修改.
注意: restFul风格请求支持常用的4种请求类型(get/post/put/delete),
          但是为了数据安全问题一般不使用post请求

1)前端发送 axios请求 



	
		
		Axios测试
		
	
	
		

Axios测试案例-1

 2)后端接收数据并返回处理好的数据

 
    @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注解,动态获取路径中的数据,要求名称必须匹配

 五.请求常见异常

  1. 405 异常 ajax的请求类型与后端接收的请求类型不匹配.
  2. 400异常 参数类型不匹配
  3. 404异常 请求路径找不到
  4. 403异常 后端未对请求进行处理

 会话管理

客户端和服务器之间进行数据交互,遵循的是HTTP协议,此协议属于无状协议(一次请求对应一次响应)响应完连接断开,服务器无法跟踪客户端的请求,通过会话管理中的Cookie技术,可以在客户端向服务器发出请求时服务器给客户端添加一个标识(把数据保存到这个标识里面) , 之后客户端每次发出请求时都会带上这个标识,这样服务器通过此标识就能识别出该客户端的信息, 但是这种把数据保存在客户端的方式存在数据被篡改的风险,Session的作用就是能够解决这种问题, 因为Session的数据是保存在服务器端,不存在被篡改的问题.

Cookie: 数据保存在客户端,类似打孔式的会员卡

  • 只能保存字符串类型的数据
  • 保存时长: 默认保存在浏览器内存中, 浏览器关闭时清除, 也可以设置任意的保存时长,设置后数据会保存到客户端磁盘中,时间到了后清除.
  • 应用场景: 长时间保存的数据使用Cookie,比如记住用户名和密码

 Session: 数据保存在服务器端, 类似银行卡

  • 可以保存任意对象类型的数据
  • 保存时长: 只能保存半小时左右
  • 应用场景: 对数据安全性要求比较高并且是短时间保存的,比如登录状态

通过Cookie实现记住用户名和密码功能 

@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

cookie实现记住用户名和密码及session保存登录状态

SpringMVC前后端数据交换简述_第7张图片

 SpringMVC前后端数据交换简述_第8张图片

 SpringMVC前后端数据交换简述_第9张图片

 SpringMVC前后端数据交换简述_第10张图片SpringMVC前后端数据交换简述_第11张图片

你可能感兴趣的:(java,后端)