1.關于跨域的說明
1.1 跨域訪問測驗
測驗1: 同服務器測驗
說明:
1.瀏覽器的網址資訊: http://manage.jt.com/test.html
2.ajax請求的地址資訊: http://manage.jt.com/test.json
發現: 請求協議名稱://域名:埠號都相同時,請求可以正常進行.
測驗2: 不同的服務器測驗
說明:;
1.瀏覽器的網址資訊: http://www.jt.com/test.html
2.ajax請求的地址資訊: http://manage.jt.com/test.json
結論: 域名地址不相同時請求不能正常獲取回應的結果.
1.2 同源策略介紹
說明:
瀏覽器在決議ajax時,如果發現請求的協議名稱://請求的域名:請求的埠號與網址的地址都相同的時滿足同源策略的規定,瀏覽器可以正確的決議回傳值.該訪問稱之為同域訪問.該策略叫做同源策略.
但是如果違反了同源策略中的任意一條,則叫做跨域訪問.瀏覽器出于安全性的考慮.不予決議回傳值(請求正常的被處理,但是接收不到回傳值).
概括: 瀏覽器決議ajax時,由于請求違反了同源策略則稱之為跨域請求.


例子: http://localhost:8091/xxx.html
http://manage.jt.com/xx.html 不可以通訊
1.3 JSONP實作跨域
1.3.1 JSONP實作跨域的原理(有難度)
1.javaScript中的src屬性不受同源策略的約束.可以獲取遠程服務器資料.
<!--該json一直保存到瀏覽器中等待呼叫,但是沒有函式名稱無法呼叫 -->
<script type="text/javascript" src="http://manage.jt.com/test.json"></script>
2.自定義回呼函式 名稱任意
/*定義回呼函式 */
function hello(data){
alert(data.name);
}
3.將回傳值結果進行特殊的格式封裝 callback(JSON);
hello({"id":"1","name":"tomcat貓"})
1.3.2 JSONP優化策略
1.利用script中的src屬性發起請求不方便.不便于程式使用. 能否封裝為ajax呼叫方式
2.在請求路徑中拼接一個引數一般的key都是約定俗稱的 http:xxx/xx?callback=“自定義函式名稱”
3.動態的獲取callback的引數名稱之后進行特殊的格式封裝 callback(JSON);
1.3.3 JSONP概念
JSONP(JSON with Padding)是JSON的一種“使用模式”,可用于解決主流瀏覽器的跨域資料訪問的問題,由于同源策略,一般來說位于 server1.example.com 的網頁無法與不是 server1.example.com的服務器溝通,而 HTML 的
1.3.3 JSONP的Ajax呼叫
<script type="text/javascript">
$(function(){
alert("測驗訪問開始!!!!!")
$.ajax({
url:"http://manage.jt.com/web/testJSONP",
type:"get", //jsonp只能支持get請求 src只能是get請求
dataType:"jsonp", //dataType表示回傳值型別
//jsonp: "callback", //指定引數名稱
//jsonpCallback: "hello", //指定回呼函式名稱
success:function (data){ //data經過jQuery封裝回傳就是json串
alert(data.itemId);
alert(data.itemDesc);
}
});
})
</script>
1.3.4 編輯后臺Controller回傳資料
package com.jt.web.controller;
import com.jt.pojo.ItemDesc;
import com.jt.util.ObjectMapperUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JSONPController {
/**
* 測驗跨域訪問是否成功
* url地址: http://manage.jt.com/web/testJSONP?callback=jQuery111106536880527642785_1600138715329&_=1600138715330
* 回傳值的應該是經過特殊格式封裝的資料. callback(JSON)
*/
@RequestMapping("/web/testJSONP")
public String jsonp(String callback){
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("跨域測驗成功!!!!");
String json = ObjectMapperUtil.toJSON(itemDesc);
return callback+"("+json+")";
}
}
1.3.5 編輯JSONPObject物件
/**
* 測驗跨域訪問是否成功
* url地址: http://manage.jt.com/web/testJSONP?callback=jQuery111106536880527642785_1600138715329&_=1600138715330
* 回傳值的應該是經過特殊格式封裝的資料. callback(JSON)
* JSONPObject引數說明:
* 1.function 回呼函式名稱
* 2.回傳的物件之后可以被轉化為JSON
*/
@RequestMapping("/web/testJSONP")
public JSONPObject jsonp(String callback){
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("API測驗!!!");
return new JSONPObject(callback, itemDesc);
}
1.3.6 關于ajax請求時間毫秒數的說明
說明:由于瀏覽器內部有快取機制,所以如果遇到了一個相同的請求地址,瀏覽器可能會使用之間的結果.(使用快取),但是有些資料必須要求瀏覽器重資料庫中動態獲取資料,為了避免瀏覽器快取一般在url最后添加亂數或者時間毫秒數區分url請求.實作該功能.

1.4 CORS跨域方式
1.4.1 跨域訪問測驗
<script type="text/javascript">
/*$(){}結構必然是jQuery函式類別庫匯入后才能正確執行*/
$(function(){
alert("我執行了AJAX");
//利用jQuery發起AJAX請求
$.get("http://manage.jt.com/test.json",function(data){
alert(data.name);
})
})
</script>

1.4.2 CORS跨域說明
說明:當下的主流的瀏覽器默認支持cors跨域的形式,但是需要服務器添加回應的資訊.否則瀏覽器不支持資料的獲取.

1.4.3 編輯CORS配置類
說明:在jt-common中添加CORS的配置類
package com.jt.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CORSConfig implements WebMvcConfigurer {
/**
* 實作跨域的方式
* 需要配置服務端程式
* 方法說明:
* 1.addMapping(/**) 允許什么樣的請求可以跨域 所有的請求
* 2.allowedOrigins("*")可以允許任意的域名
* 3.allowCredentials(true) 跨域時是否允許攜帶cookie等引數
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true);
}
}
1.4.4 跨域測驗


2. 京淘單點登錄系統
2.1 通用頁面跳轉
2.1.1 業務分析
1.注冊的url地址
http://www.jt.com/user/register.html
2.登錄的url地址
http://www.jt.com/user/login.html
2.1.2 編輯UserController
package com.jt.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller //由于設計到頁面跳轉功能.
@RequestMapping("/user")
public class UserController {
/**
* 通用頁面跳轉實作
* 1.http://www.jt.com/user/login.html login.jsp頁面
* 2.http://www.jt.com/user/register.html register.jsp頁面
*/
@RequestMapping("/{moduleName}")
public String module(@PathVariable String moduleName){
return moduleName;
}
}
2.1.3 頁面效果展現

2.2 創建JT-SSO專案
2.2.1 JT-SSO專案說明
作用:主要為jt-web的服務器提供用戶的資料的支持,但凡涉及到user的CRUD操作都應該由該系統完成.
打包方式: jar包程式
注意事項: 繼承jt/ 依賴jt-common 添加插件.
埠號: 8093

2.2.2 創建專案

2.2.3 編輯pom.xml組態檔
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>jt-sso</artifactId>
<parent>
<artifactId>jt</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<!--添加依賴項-->
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>jt-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!--添加插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2.4 編輯User的POJO物件
@TableName("tb_user")
@Data
@Accessors(chain = true)
public class User extends BasePojo{
@TableId(type = IdType.AUTO) //主鍵自增
private Long id;
private String username; //用戶名
private String password; //密碼
private String phone; //電話
private String email; //郵箱 由于email暫時沒有使用電話代替
}
2.2.4 實作JT-SSO代碼結構

2.2.5 編輯Nginx實作反向代理
注意hosts檔案的配置. 修改nginx之后重啟服務器.
#搭建jt-sso服務器
server {
listen 80;
server_name sso.jt.com;
location / {
proxy_pass http://localhost:8093;
}
}
2.3 用戶資料校驗的分析
2.3.1 頁面url分析

2.3.2 檢索頁面JS

2.3.3 頁面JS分析
$.ajax({
url : "http://sso.jt.com/user/check/"+escape(pin)+"/1?r=" + Math.random(),
dataType : "jsonp",
success : function(data) { //狀態資訊:200 成功 狀態資訊:201 失敗
checkpin = data.data?"1":"0";
if(data.status == 200){
if (!data.data) {
validateSettings.succeed.run(option);
namestate = true;
}else {
validateSettings.error.run(option, "該用戶名已占用!");
namestate = false;
}
}else{
//標識后臺服務器運行例外
validateSettings.error.run(option, "服務器正忙,請稍后!!!(我后臺報錯了我也不知道啥錯!!!)");
namestate = false;
}
}
});
2.2.6 單點登錄業務介面

2.2.7 編輯jt-sso的UserController
package com.jt.controller;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.User;
import com.jt.service.UserService;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findAll")
public List<User> findAll(){
return userService.findAll();
}
/**
* JSONP的跨域請求 特殊的格式封裝.....
* 需求分析:校驗用戶的資料是否可用.
* url: http://sso.jt.com/user/check/{param}/{type}
* 引數: param/type
* 回傳值結果: SysResult物件
*/
@RequestMapping("/check/{param}/{type}")
public JSONPObject chcekUser(@PathVariable String param,
@PathVariable Integer type,
String callback){
//根據資訊查詢資料庫獲取回應記錄
Boolean flag = userService.checkUser(param,type);
return new JSONPObject(callback, SysResult.success(flag));
}
}
2.2.8 編輯jt-sso的UserService
package com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService{
private static Map<Integer,String> paramMap = new HashMap<>();
static {
paramMap.put(1, "username");
paramMap.put(2, "phone");
paramMap.put(3, "email");
}
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.selectList(null);
}
/**
* 校驗資料是否存在即可. 查詢總記錄數即可.
* @param param 需要校驗的資料
* @param type 校驗的型別 1username 2phone 3 email 6789910
* @return
*/
@Override
public Boolean checkUser(String param, Integer type) {
String column = paramMap.get(type);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(column, param);
//boolean flag = userMapper.selectCount(queryWrapper)>0?true:false;
return userMapper.selectCount(queryWrapper)>0;
}
}
2.2.9 頁面效果展現

2.2.10 修改全域例外處理機制
package com.jt.aop;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.vo.SysResult;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
@RestControllerAdvice //作用: 標識我是一個通知方法,并且只攔截Controll層的例外.并且回傳JSON.
public class SysResultException {
//需要定義一個全域的方法 回傳指定的報錯資訊.
//ExceptionHandler 配置例外的型別,當遇到了某種例外時在執行該方法.
//JSONP的例外處理應該是 callback({status:201,msg:"",data:""})
//利用Request物件動態獲取callback引數.之后動態封裝回傳值
@ExceptionHandler(RuntimeException.class)
public Object exception(Exception e, HttpServletRequest request){
e.printStackTrace();
String callback = request.getParameter("callback");
if(!StringUtils.isEmpty(callback)){ //jsonp請求
return new JSONPObject(callback, SysResult.fail());
}
//日志記錄/控制臺輸出. 讓程式員知道哪里報錯!!!
return SysResult.fail();
}
}
3.微服務框架介紹
3.1遠程呼叫的說明
瀏覽器決議ajax發起跨域請求.程式雖然可以正確的呼叫,但是瀏覽器可以監控用戶的所有的引數及回傳值.在一些特定的條件下該操作不安全.
一般使用跨域的請求都是用來獲取其他服務器的資料(查詢操作),如果遇到了POST需要提交的引數應該使用更加安全的請求方式實作.
3.2 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)

3.3 HttpClient入門案例
3.3.1 匯入jar包
<!--添加httpClient jar包 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
3.3.2 入門案例
package com.jt.test;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;
import java.io.IOException;
public class TestHttpClient {
/**
* 步驟:
* 1.實體化httpClient工具API
* 2.定義請求url地址 任意網路地址....
* 3.定義請求的型別 get/post/put/delete
* 4.發起請求,獲取回應的結果
* 5.判斷回應的狀態碼資訊. 200 404 500 406 400....
* 6.動態決議回傳值執行后續操作.
*/
@Test
public void test01(){
HttpClient httpClient = HttpClients.createDefault();
String url = "https://www.baidu.com/";
HttpGet get = new HttpGet(url);
try {
HttpResponse httpResponse = httpClient.execute(get);
//判斷狀態碼是否正確
int statusCode = httpResponse.getStatusLine().getStatusCode();
if(statusCode == 200){
//表示請求正確
HttpEntity httpEntity = httpResponse.getEntity(); //獲取服務器的全部回應資訊(json/html/xml/xxxx)
String result = EntityUtils.toString(httpEntity,"UTF-8");
//獲取之后可以執行業務處理......
System.out.println(result);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/64550.html
標籤:其他
上一篇:漢諾塔問題(遞回寫法)
