跨域

1跨域

1.1 什么是跨域?

定义: 当浏览器解析ajax时,ajax发起请求的地址如果与当前页面所在的地址违反同源策略时,则称之为跨域(请求)

1.2 跨域访问测试

案例1:
页面网址:http://manage.jt.com:80/test.html
ajax请求: http://manage.jt.com:80/test.json
结论: 当请求协议://域名:port端口号都相同时 访问正常的.

案例2:
页面网址: http://www.jt.com:80/test.html
ajax请求: http://manage.jt.com:80/test.json
结论: 当浏览器的地址与ajax地址不同时,请求不能正常执行.

1.3 同源策略说明

说明:浏览器在发起AJAX请求时,必须遵守同源策略的规定.否则数据无法正常解析.
策略说明: 发起请求时,必须满足 协议://域名:端口都相同(和当前页面对比)时.满足同源策略要求.浏览器可以正确的发起请求,并且解析结果.,
但是如果上述的三项中有一项不同,则表示跨域访问.浏览器不予解析返回值结果.
在这里插入图片描述
例题: 问http://manage.jt.com/test.html 和http://localhost:8091/test.json 能否通信?
答案: 不能通信 1)域名不一致 2)端口不同

2 JSONP跨域

2.1JSONP跨域实现原理

1).利用javascript中的src属性实现跨域

<script type="text/javascript" src="http://manage.jt.com/test.json"></script>

2).自定义回调函数 function callback(){}

	function hello(data){
			alert(data.name);
		}

3).将返回值结果 进行特殊的格式封装 callback(JSON数据)

hello({"id":"1","name":"tomcat猫"})

2.2 jQuery实现JSONP跨域访问

2.2.1 编辑html页面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSONP测试</title>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	$(function(){
		alert("测试访问开始!!!!!")
		//网页位置: www.jt.com/JSONP.html
		$.ajax({
			url:"http://manage.jt.com/web/testJSONP",
			type:"get",				//jsonp只能支持get请求  不支持post,因为src支持get
			dataType:"jsonp",       //dataType表示返回值类型  如果是跨域访问,则必须添加jsonp
			//jsonp: "callback",    //指定参数名称
			//jsonpCallback: "hello",  //指定回调函数名称
			success:function (data){   //data经过jQuery封装返回就是json串
				alert(data.id);
				alert(data.name);
				//转化为字符串使用
				//var obj = eval("("+data+")");
				//alert(obj.name);
			}	
		});	
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>

2.2.2 页面url分析

在这里插入图片描述

2.2.3 编辑JSONPController

说明: 在jt-manage中添加JSONPController.实现跨域访问

@RestController
public class JSONPController {
	
	/**
	 * url:http://manage.jt.com/web/testJSONP?callback=jQuery111107990405330439474_1595323762313&_=1595323762314
	 * @return JSONPObject 专门负责封装JSONP的返回值结果的.
	 * 注意事项:  返回值结果必须通过特殊的格式封装    callback(JSON数据)
	 */
	@RequestMapping("/web/testJSONP")
	public JSONPObject jsonp(String callback) {
		
		//准备返回数据
		User user = new User();
		user.setId(100L).setPassword("我是密码");
		return new JSONPObject(callback, user);
	}
	
	
}

2.2.4 JSONP服务器返回值

在这里插入图片描述

3 CORS跨域

3.1 CORS跨域实现原理

说明:当下的主流的浏览器天生都支持跨域,通过添加请求头信息,将源地址进行标识,之后发往后端服务器.
在这里插入图片描述
关键点: 跨域请求由浏览器和服务器共同完成,.要求双方都必须同意跨域才行. 但是默认的条件下服务器端是不允许跨域的.所以必须经过配置才行
在这里插入图片描述

3.2 CORS实现跨域

说明:在jt-common中添加跨域配置
//类似于web项目中使用的web.xml配置文件
@Configuration
public class CorsConfig implements WebMvcConfigurer{

/**
 * 配置后端服务器可以跨域的清单
 * 参数说明:  addMapping:什么样的请求可以进行跨域   /web/**    /aaa/b/c/e/d/d/d
 *          /*   匹配一级目录
 *          /**  匹配多级目录   使用最多
 */
@Override
public void addCorsMappings(CorsRegistry registry) {
	
	registry.addMapping("/**")
			.allowedOrigins("*")   //配置源 通配
			.allowedMethods("GET","POST","PUT","DELETE","HEAD") //允许的请求方式
			.allowCredentials(true)		//是否允许携带cookie
			.maxAge(1800);				//允许跨域的持续时间
}

}

3.3 编辑ajax请求页面

	<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
	$(function(){			   //正常
		alert("我要进行cors的跨域了!!!!");   //正常
		//利用jQuery发起AJAX请求
		$.get("http://manage.jt.com/web/testCors",function(data){
			alert(data.id);
			alert(data.password);
		})
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>

3.4 编辑CorsController

@RestController
public class CorsController {
	
	
	@RequestMapping("/web/testCors")
	public User testUser() {
		System.out.println("我执行了业务操作!!!");
		return new User().setId(100L).setPassword("我是cors的返回值!!!!");
	}
	
}

3.5 查看响应信息

在这里插入图片描述

4 用户信息校验

4.1 业务需求

在这里插入图片描述
说明:当用户添加注册信息时,需要向JT-SSO单点登录系统进行数据的校验.如果数据库中存在/不存在都应该返回相关信息,之后页面提示信息给用户.

4.2 页面JS分析

在这里插入图片描述
注意事项: 明确url中的哪些部分一定写死在js中.之后根据检索的功能快速定位JS位置.
在这里插入图片描述
说明:配置ajax实现JSONP的请求.
在这里插入图片描述

4.3 业务接口文档

在这里插入图片描述

4.4 编辑UserController

/**
	 * 1.url:http://sso.jt.com/user/check/{param}/{type}
	 * 2.参数:param  需要校验的数据   
	 *       type   校验的类型
	 * 3.返回值结果:   SysResult对象     data:true/false
	 * 4.jsonp跨域访问
	 * 终极目标:  1.快  省  安全
	 */
	@RequestMapping("/check/{param}/{type}")
	public JSONPObject checkUser(@PathVariable String param,@PathVariable Integer type,
			String callback) {
		
		boolean flag = userService.checkUser(param,type);//要求返回true/false
		SysResult sysResult = SysResult.success(flag);
		return new JSONPObject(callback, sysResult);
	}

4.5 编辑UserService

@Service
public class UserServiceImpl implements UserService {
	
	@Autowired
	private UserMapper userMapper;
	private static Map<Integer,String> paramMap; //如果项目中固定写死的可以通过static方式维护
	
	static {
		//1.将type类型转化为具体的字段信息.
		Map<Integer,String> map = new HashMap<>();
		map.put(1, "username");
		map.put(2, "phone");
		map.put(3, "email");
		paramMap = map;
	}

	//校验数据库中是否有数据!!!  有true   没有false
	//type 1 username,  2 phone ,3 eamil 
	@Override
	public boolean checkUser(String param, Integer type) {
		//String column = type==1?"username":((type==2)?"phone":"email");
		String column = paramMap.get(type);
		//1.通过获取数据库中的记录总数,判断是否存在数据.
		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq(column, param);
		int count = userMapper.selectCount(queryWrapper);
		return count>0?true:false;
	}
}

4.6 页面效果

在这里插入图片描述

4.7 优化页面结构

添加状态码的判断编辑jdValidate.js:

 $.ajax({
            	url : "http://sso.jt.com/user/check/"+escape(pin)+"/1?r=" + Math.random(),
            	dataType : "jsonp",
            	success : function(data) {
                    checkpin = data.data?"1":"0";
                    //校验服务器数据是否正确
                    if(data.status == 200){
                    	 //返回值data.data=true 已存在/false 不存在
                        if (!data.data) {
                            validateSettings.succeed.run(option);
                            namestate = true;
                        }else {
                            validateSettings.error.run(option, "该用户名已占用!");
                            namestate = false;
                        }
                    }else{
                    	 validateSettings.error.run(option, "服务器正忙,请重试!!!");
                         namestate = false;
                    }
                   
                }
            });

4.8 全局异常处理机制优化

package com.jt.aop;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.vo.SysResult;

import lombok.extern.slf4j.Slf4j;

//标识改类是全局异常处理机制的配置类
@RestControllerAdvice //advice通知   返回的数据都是json串
@Slf4j	//添加日志
public class SystemExceptionAOP {
	
	/*
	 * 添加通用异常返回的方法.
	 * 底层原理:AOP的异常通知.
	 * 
	 * 常规手段:  SysResult.fail();
	 * 跨域访问:  JSONP   必须满足JSONP跨域访问要求  callback(SysResult.fail())
	 * 问题: 如何断定用户使用的是跨域方式还是普通业务调用??? 
	 * 分析: jsonp请求   get请求的方式携带?callback   
	 * 判断依据:  用户参数是否携带callback  特定参数,一般条件下不会使用
	 * */
	@ExceptionHandler({RuntimeException.class}) //拦截运行时异常
	public Object systemResultException(HttpServletRequest request,Exception exception) {
		
		String callback = request.getParameter("callback");
		if(StringUtils.isEmpty(callback)) {	//不是跨域访问
			log.error("{~~~~~~"+exception.getMessage()+"}", exception); //输出日志
			return SysResult.fail();	 //返回统一的失败数据
		}
		
		//说明:有可能跨域  jsonp只能提交GET请求
		String method = request.getMethod();
		if(!method.equalsIgnoreCase("GET")) {
			//如果不是get请求,不是jsonp请求方式
			log.error("{~~~~~~"+exception.getMessage()+"}", exception); //输出日志
			return SysResult.fail();	 //返回统一的失败数据
		}
		
		//3.如果程序执行到这里,标识进行了JSONP的请求. 按照JSONP的方式返回数据
		log.error("{~~~~~~"+exception.getMessage()+"}", exception); //输出日志
		return new JSONPObject(callback, SysResult.fail());
		
	}
}

5 HttpClient

5.1 HttpClient介绍

HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在HttpClient最新版本为 HttpClient 4.5 .6(2015-09-11)

5.2 场景介绍

说明:跨域的形式只能发生在有页面的web端,由浏览器解析页面JS.发起ajax请求.实现跨域.但是由于分布式的思想,后端服务器的数量众多.有时可能由A业务服务器向B业务服务器获取业务数据,但是没有页面的支持,所以不能通过跨域的形式实现.只能通过远程过程调用的方式实现数据的通信.
在这里插入图片描述

5.3 HttpClient入门案例

5.3.1 导入jar包

<!--添加httpClient jar包 -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
		</dependency>

5.3.2 测试案例

package com.jt.test;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;

public class TestHttpClient {
	
	/**
	 * 案例说明:                           万能用法
	 * 	1.利用httpClient机制 访问百度服务器.   http://www.baidu.com
	 * 	2.实现步骤: (了解即可)
	 * 		1.定义请求网址
	 * 		2.定义httpClient工具API对象
	 * 		3.定义请求的类型
	 * 		4.发起请求,获取返回值结果
	 * 		5.校验返回值
	 * 		6.获取返回值结果数据.
	 * @throws IOException 
	 * @throws ClientProtocolException 
	 */
	@Test
	public void testGet() throws ClientProtocolException, IOException {
		String url = "http://www.baidu.com";//任意网络资源  包裹业务服务器.
		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpGet httpGet = new HttpGet(url);
		CloseableHttpResponse response = httpClient.execute(httpGet);//不能保证网络请求一定正确.
		//发起请求之后 需要判断返回值结果是否正确  一般条件下判断响应状态码信息是否为200.
		//404 400 提交参数异常  406 接收参数异常 500 服务器异常  504  超时   200正常 
		int status = response.getStatusLine().getStatusCode();
		if(status == 200) {
			//说明请求正确  获取返回值的实体对象
			HttpEntity httpEntity = response.getEntity();
			//将远程服务器返回的信息,转化为字符串. 方便调用   1.json   2.html代码片段
			String result = EntityUtils.toString(httpEntity,"utf-8");
			System.out.println(result);
		}
	}
	
}

5.3.3 HttpClient与跨域的区别

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值