第三阶段---day06-day07 SpringMVC

SpringMVC

1. Spring总结

1.1 IOC-DI

1.IOC: 控制反转,对象的生命周期由spring容器管理
2.xml配置文件的写法:bean标签 id/class xml容器的实现类
3.注解写法: @Bean 写在配置类
4.单例多例问题 默认单例 @Scope 单例:singleton 多例:prototype
5.懒加载: @lazy 用户使用时创建
6.声明周期方法: 对象创建(无参构造)/对象初始化@PostConstruct/业务调用/对象销毁@PreDestroy
7.DI:依赖注入 为对象的属性赋值
8.简单属性赋值: @value 注解 需要些一个配置文件在resource文件夹里
9.引用赋值: @Autowired 1.默认按照类型匹配 2.按照名称匹配
10. 注入的方式: set注入 构造方法注入 工厂模式注入

1.2 AOP

1.什么是AOP? 面向切面编程,在不修改源码的情况下,对方法进行扩展,解决了业务的耦合性
2.底层核心机制: 动态代理机制 JDK/CDLIB 动态代理
3.关键词:
3.1:切入点表达式:如果用户调用满足切入点表达式,则创建代理对象,执行AOP操作
3.2:通知:对业务的扩展 5个通知 环绕通知最为强大
3.3连接点: 用户调用的方法满足切入点表达式, 则该方法称为连接点

1.3 Spring框架优势

1.spring框架的设计让程序从层级到业务实现了松耦合
2.Spring基于这样的设计思想,可以整合其他第三方框架,使得程序可以以一种统一的方式进行调用

2. SpringMVC

2.1 介绍

1.SpringMVC 是spring框架后续开发的web模块,主要负责与前端用户进行交互
2.SpringMVC基于Servlet进行开发的框架,目的是简化前后端的调用

2.2 Servlet 回顾

java编写的服务器端程序.主要功能在于交互式的浏览和修改数据,生成动态的web内容
狭义的servlet是java语言实现的一个接口
广义的servlet是任何实现了Servlet这个接口的类-----一般理解为这个
总结: Servlet是java针对前后端交互,开发的一种调用机制
弊端:
1.一个业务需求就需要一个Servlet 数量繁多
2.需要编辑大量的配置文件 web.xml 开发繁琐
3.从servlet中获取的参数都是String数据类型,需要手动转化类型
4.Servlet只提供了get/post请求,不满足当下需求

2.3 SpringMVC入门案例

2.3.1 创建项目

1.创建项目
在这里插入图片描述
2.勾选jar包
在这里插入图片描述
3.测试tomcat服务器是否正常使用
在这里插入图片描述

2.3.2 SpringMVC开发注意事项

1.开发时注意包路径 在主启动类的同包及子包中编辑
在这里插入图片描述
2.现在开发一般都是用前后端分离的方式,所以服务器一般返回的都是json串
3.每次编辑完成代码,需要重启tomcat服务器

2.3.3 编辑HelloController
package com.jt.controller;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller  //springmvc专门扫描的注解
public class HelloController{
	@RequestMapping("/hello")
	@ResponseBody
	public String hello(){
		return "您好mvc";
}
}
2.3.4 页面展示效果

URL1: http://localhost:8080/hello
URL2: http://127.0.0.1:8080/hello
在这里插入图片描述

2.4 SpringMVC注解说明

1.@RequestMapping("/hello")
负责用户的请求路径与后台服务器之间的映射关系
如果请求路径不匹配,则用户报错404
在这里插入图片描述
2.@ResponseBody
作用: 将服务器的返回值转化为JSON. 如果服务器返回的是String类型,则按照自身返回.

2.5 SpringDemo 测试2

2.5.1 编辑pojo
package com.jt.pojo;

import java.io.Serializable;

public class User implements Serializable {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
2.5.2 编辑Controller方法
 	@RequestMapping("/getUser")
    @ResponseBody //{id:101,name:"SpringMVC!!"}
    public User getUser(){
        User user = new User();
        user.setId(101);
        user.setName("SpringMVC!!");
        return user;
    }
2.5.3 页面效果展现

说明:返回的数据就是JSON串
在这里插入图片描述

2.6 SpringMVC底层实现原理

在这里插入图片描述
重要组件:

  1. 前端控制器 DispatcherServlet
  2. 处理器映射器 handlerMapping
  3. 处理器适配器 handlerAdapter
  4. 视图解析器 ViewResolver

SpringMVC调用流程:
1.用户发起请求之后,第一步访问就是前端控制器.
2.前端控制器只负责请求的转发/响应. 没有办法直接处理业务.
3.当SpringMVC容器启动时,处理器映射器首先会加载所有的@RequestMapping注解.将请求路径与方法进行绑定.保存到Map中. Map</url,method方法>, 当前端控制器发送请求被处理器映射器接收.如果URL地址匹配,则告知应该执行哪个方法.如果url地址不匹配.,则提示用户404
4.前端控制器得知将要执行的方法是谁,但是前端控制只能转发,没有办法执行业务.所以请求处理器适配器执行业务逻辑
5.处理器适配器针对配置文件(xml方式/注解方式/其它方式)的格式,挑选合适的处理器去执行业务逻辑. 业务执行成功之后返回ModelAndView对象 Model:业务数据 View:页面

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

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

2.7 SpringMVC参数接收用法

代码简化:
在这里插入图片描述

2.7.1 简单参数传参----历史版本
package com.jt.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class UserController {

    /**
     * URL:http://localhost:8080/user/findUser?id=100&name=tomcat
     * 类型: get请求
     * 返回值: String id:name
     * 补课:
     *  1.Servlet-request对象/response对象
     *  2.Servlet中如何取值??
     */
    @RequestMapping("/user/findUser")
    @ResponseBody   //响应数据  JSON
    public String findUser(HttpServletRequest request,
                           HttpServletResponse response){
        String id = request.getParameter("id");
        int intId = Integer.parseInt(id);
        String name = request.getParameter("name");
        return intId +":"+name;
    }
}

2.7.2 简单参数传参—MVC方式
/**
     * URL:http://localhost:8080/user/findUser2?id=100&name=tomcat
     * 规则: SpringMVC中的参数名称,必须与传递参数名称一致
     * 原理: SpringMVC在内部将Servlet的取值的方式包装.用户只需填写参数
     *      即可以获取数据.
     * @return
     */
    @RequestMapping("/user/findUser2")
    @ResponseBody
    public String findUser2(Integer id,String name){

        return id +":"+name;
    }
2.7.3 使用对象接收参数
 /**
     * url:http://localhost:8080/user/getUser?id=1&name=李四&age=18
     * 返回值: User对象
     * 知识点:
     *   当遇到多个参数时,可以使用对象封装.
     *   要求对象的属性必须与参数名称一致,同时必须有Set/Get方法.
     *   SpringMVC会自动的将参数赋值给对象的属性.
     */
    @RequestMapping("/getUser")
    public User getUser(User user){
        return user;
    }

在这里插入图片描述

2.8 RestFul结构

2.8.1 请求说明

1.GET请求: http://localhost:8080/user/restFul?id=1&name=张三
2.RestFul请求: http://localhost:8080/user/restFul/1/张三

2.8.2 RestFul语法

1.URL中请求的参数使用/分割开
RestFul请求: http://localhost:8080/user/restFul/1/张三
2.服务器端参数接收时,变量使用{xx}进行包裹,并且位置固定
3.利用@PathVariable注解 动态获取路径中的数据,要求名称必须匹配

 /**
     * RestFul结构 动态接收参数
     * url: http://localhost:8080/user/restFul/1/张三
     * 返回值: 返回User对象
     * 难点: 需要从URL的路径中获取参数!!!
     * 语法:
     *  1.服务器端参数接收时,变量使用{xx}进行包裹,并且位置固定.
     *  2.利用@PathVariable注解,动态获取路径中的数据,要求名称必须匹配
     */
    @RequestMapping("/restFul/{id}/{name}")
    public User restFul(@PathVariable Integer id,
                        @PathVariable String name){
        User user = new User();
        user.setId(id);
        user.setName(name);
        return user;
    }

在这里插入图片描述

2.8.3 RestFul结构对象传参
  /**
     * URL: http://localhost:8080/user/restFul2/1/王五/18
     * RestFul对象接收:
     *   如果对象的属性与{key}相同,则可以使用对象接收.
     * 用途: restFul结构 一般用于更新操作
     * @param user
     * @return
     */
    @RequestMapping("/restFul2/{id}/{name}/{age}")
    public User restFul2(User user){

        return user;
    }

2.9 请求类型与业务的关系

1.请求类型
在这里插入图片描述
2. 规则: 随着业务深入,请求类型与业务渐渐的绑定.
新增: post请求类型 @PostMapping("")
删除: delete请求类型 @DeleteMapping("")
修改: put请求类型 @PutMapping("")
查询: get请求类型 @GetMapping("")

3.springmvc参数传递

3.1 同名参数提交

3.1.1 页面说明

复选框: name=“hobby” 口篮球 口足球 口乒乓球
问题: 参数如何提交? hobby=篮球,足球,乒乓球
前端URL模式: http://localhost:8080/user/saveHobby?hobby=篮球,足球,乒乓球

3.1.2 编辑UserController
 /**
     * URL地址: http://localhost:8080/user/saveHobby?hobby=篮球,排球,乒乓球
     * 返回值: 参数获取之后返回
     * SpringMVC功能:
     *      如果url中的参数使用,号的方式连接,则可以自动的转化为数组结构
     */
    @GetMapping("/saveHobby")
    public String[] saveHobby(String[] hobby){
        //String[] arrays = hobby.split(",");
        //将字符串转化为数组,可以方便后续业务的调用
        //return arrays;
        return hobby;
    }

4. 前后端调用

4.1 Ajax

4.1.1 Ajax介绍

使用Ajax技术,网页应用能够快速的将增量更新呈现在用户界面上,而不需要重新加载整个页面,这样可以让程序更快的回应用户的操作

4.1.2 Ajax特点

Ajax特点: 局部刷新,异步访问
1.同步请求:浏览器发起请求到服务器时,如果服务器没有响应,用户则无法获取页面数据,处于等待状态.不可以做其它的操作.
2.异步请求:异步请求时,浏览器可以进行其它的操作.当ajax数据获取之后,信息在页面的局部刷新. (可以理解为多线程操作方式)

4.1.3 Ajax异步原理

Ajax为什么可以异步? 以为有Ajax引擎
回调函数: 服务器返回数据,通过回调函数通知用户.
在这里插入图片描述

4.2 跨域问题

注解: @CrossOrigin
在这里插入图片描述

4.3 前后端调用入门案例

4.3.1 前端js
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>ajax入门案例</h1>
		<script src="../js/axios.js"></script>
		<script>
			//promise是Axios封装服务器返回值的对象
			let url1="http://localhost:8080/axios/findStr"
			axios.get(url1)
				 .then(function(promise){
					 console.log(promise)
					 console.log(promise.data)
				 })
		</script>
	</body>
</html>

在这里插入图片描述

4.3.2 编辑AxiosController
package com.jt.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/axios")
@CrossOrigin    //专门解决跨域问题   前后端端口不一样 需要进行跨域
public class AxiosController {

    /**
     * http://localhost:8080/axios/findStr
     */
    @GetMapping("/findStr")
    public String findStr(){

        return "再坚持半天!!!";
    }

}

4.3 前后端调用----带简单参数

4.3.1 编辑页面js
//2.带参数的业务调用  返回字符串+id!!!
			let url2 = "http://localhost:8080/axios/getUserById?id=100";
			axios.get(url2)
				 .then(function(promise){
					 console.log(promise.data)
				 })

4.3.2 编辑AxiosController
@GetMapping("/findUserById")
public String findUserById(Integer id){
	return "获取数据:"+id;
}
4.3.3 前后端调用----简化操作
axios.defaults.baseURL = "http://localhost:8080"

在这里插入图片描述

4.4 前后端调用 ---- 对象传参

4.4.1 页面URL分析
			//3.对象参数传递写法   利用API自动拼接参数
			let user = {id: 100,name: "tomcat"}
			axios.get("/axios/findUser",{params: user})
				 .then(function(promise){
					 console.log(promise.data)
				 })
4.4.2 编辑AxiosController
 /**
     * 接收对象参数
     * URL: http://localhost:8080/axios/findUser?id=100&name=tomcat
     */
    @GetMapping("/findUser")
    public User findUser(User user){

        return user;
    }

4.5 前后端调用-ResultFul结构

4.5.1 前端js调用

重点:RestFul的结构不区分请求类型,任意请求都可以通过RestFul的结构发送数据

//4.RestFul结构实现数据传递  第一种:简单操作
			let rest1 = {id: 100,name: "tomcat",age: 19}
			axios.get("/axios/result/"+rest1.id+"/"+rest1.name+"/"+rest1.age)
				 .then(function(promise){
					 console.log(promise.data)
				 })
			
			/**
			 * 5.RestFul结构实现数据传递  ]
			 *  第二种:模板字符串写法
			 * 语法: 	反引号  ` `
			 * 字符取值: ${rest2.id}
			 * 作用: 1.常见字符串拼接
			 * 		 2.可以保证代码的数据结构
			 */
			let rest2 = {id: 100,name: "tomcat",age: 19}
			axios.get(`/axios/result/${rest2.id}/${rest2.name}/${rest2.age}`)
			
			
			//模板字符串 保证代码格式
			let div = `<div>
							<p>天青色等烟雨</p>
							<p>而我在等你</p>
							<p>炊烟袅袅升起</p>
							<p>隔江千万里</p>
					   </div>`
4.5.2 编辑后端Controller
 /**
     * 4.接收restFul的数据
     * URL: http://localhost:8080/axios/result/100/tomcat/19
     * 返回值: User对象
     */
    @GetMapping("/result/{id}/{name}/{age}")
    public User result(User user){

        return user;
    }

4.6 前端Post提交方式

4.6.1 前端页面js
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<h1>ajax-POST请求</h1>
		<script src="../js/axios.js"></script>
		<script>
			//1.Axios优化
			axios.defaults.baseURL = "http://localhost:8080"
		
			/**
			 * 2.axios的post请求说明
			 * 2.1 什么时候使用post请求 新增操作
			 * 知识点:
			 * 		let user js对象  json串  java对象
			 *  说明: 
			 * 		前端代码传递的JS对象,而后端使用的是java对象,
			 * 		2种对象没有办法直接转化,需要转化JSON进行传递.
			 * 	axios使用post请求时,自动将JS对象解析为JSON串
			 */
			let user = {id:100, name:"tomcat猫", age: 20}
			axios.post("/axios/saveUser",user)
				 .then(function(promise){
					 console.log(promise.data)
				 })
			
			
			
		</script>
	</body>
</html>

在这里插入图片描述

4.6.2 编辑后端Controller
/**
     * 编辑后端Controller
     * URL: /axios/saveUser
     * 参数: json串
     *      {"id":100,"name":"tomcat猫","age":20}
     * 返回值: User
     * 难点:
     *      1.将JSON串转化为Java对象  @RequestBody
     *      2.将Java对象转化为JSON串! @ResponseBody
     */
    @PostMapping("/saveUser")
    public User saveUser(@RequestBody User user){

        return user;
    }

4.7 参数类型规范

1.Get/ Delete 参数提交方式一样
2.Post / Put 参数提交方式一样
3.RestFul 结构适用于所有的请求类型

4.8 跨域问题

4.8.1 同源策略

浏览器的网址 与 Ajax请求 的网址 必须满足 如下要求: 协议://域名:端口号 必须相同
如果满足要求则是同域访问,如果不满足要求,则是跨域访问

4.8.2 同源策略练习题

练习1:

  1. http://localhost:8080/xxx/xxx 浏览器地址
  2. http://localhost:8080/yyy/yyy ajax请求地址 同域请求

练习2:

  1. http://127.0.0.1:8080/xxx/xxx 浏览器地址
  2. http://localhost:8080/yyy/yyy ajax请求地址 跨域请求 域名不同

练习3: 域名与IP映射

  1. http://www.jt.com:8080/xxx/xxx 浏览器地址
  2. http://10.8.8.9:8080/yyy/yyy ajax请求地址 跨域请求! 域名不同

练习4:

  1. http://www.jt.com:80/xxx/xxx 浏览器地址
  2. http://www.jt.com/yyy/yyy ajax请求地址 同域请求!!! http协议默认80端口

练习5:

  1. https://www.jt.com/xxx/xxx 浏览器地址
  2. https://www.jt.com:443/yyy/yyy ajax请求地址 同域请求!!!
    https协议默认端口443

练习6:

  1. http://www.jt.com/xxx/xxx 浏览器地址
  2. https://www.jt.com:443/yyy/yyy ajax请求地址 跨域请求
4.8.3 CORS介绍

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

跨域的错误报告:
在这里插入图片描述
跨域解决方案:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringMVC 中,我们可以通过 ResponseBody 注解返回音频流,具体步骤如下: 1. 在 Controller 中定义一个返回类型为 ResponseEntity<byte[]> 的方法,该方法需要使用 @ResponseBody 注解标注。 2. 在方法中获取音频文件的字节数组,并将其放入 ResponseEntity 对象中返回。 3. 在 ResponseEntity 对象中设置 Content-Type、Content-Disposition 等响应头,以便浏览器正确解析音频流并进行播放。 示例代码如下: ```java @RequestMapping("/audio") @ResponseBody public ResponseEntity<byte[]> getAudio() throws IOException { // 读取音频文件字节数组 InputStream in = getClass().getResourceAsStream("/static/audio/sample.mp3"); byte[] audioBytes = IOUtils.toByteArray(in); // 设置响应头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType("audio/mpeg")); headers.setContentDispositionFormData("attachment", "sample.mp3"); // 返回音频流 return new ResponseEntity<>(audioBytes, headers, HttpStatus.OK); } ``` 上述代码中,我们将音频文件 sample.mp3 放在了项目的 /static/audio 目录下。在方法中,我们使用 IOUtils.toByteArray() 方法将音频文件转换为字节数组,并将其放入 ResponseEntity 对象中返回。在设置响应头时,我们使用 MediaType.parseMediaType() 方法设置 Content-Type,使用 setContentDispositionFormData() 方法设置 Content-Disposition。最后,我们通过 new ResponseEntity<>(audioBytes, headers, HttpStatus.OK) 创建 ResponseEntity 对象并返回。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值