CGB2004-京淘项目Day16

1 关于JSONP知识说明

1.1 JSONP工具API说明

1.1.1 JSONP页面说明

$.ajax({
			url:"http://manager.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);
			}
		});	

1.1.2 Ajax请求方式

在这里插入图片描述

1.1.3 服务器处理跨域请求

package com.jt.web.controller;

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.ItemDesc;
import com.jt.unit.ObjectMapperUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController     //json字符串
public class JSONPController {

    /**
     * 完成JSONP的调用
     * url:http://manager.jt.com/web/testJSONP?callback=jQuery111101021758391465013_1597656788213&_=1597656788214
     * 规定:返回值结果,必须经过特殊的格式封装.callback(json)
     */
    @RequestMapping("/web/testJSONP")
    public JSONPObject jsonp(String callback){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(101L).setItemDesc("我是商品详情信息");
        return new JSONPObject(callback, itemDesc);
    }

   /* public String  jsonp(String callback){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(101L).setItemDesc("我是商品详情信息");
        String json = ObjectMapperUtil.toJSON(itemDesc);
        //return callback+"({'id':'100','name':'tomcat猫'})";
        return callback +"("+json+")";
    }*/

}

2. CORS跨域访问说明

2.1CORS说明

CORS,全称Cross-Origin Resource Sharing [1] ,是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制,通常由于同域安全策略(the same-origin security policy)浏览器会禁止这种跨域请求。
知识回顾:
JSONP: 用户利用jsonp向服务器端动态获取数据的过程. 主体用户.
CORS: 服务器是否允许客户端访问的技术. 主体服务器.

2.2 CORS原理说明

用户可以向普通的ajax请求一样发起跨域请求. get/post/put/delete,由于当下的跨域的业务比较常见,所有的主流的浏览器默认支持跨域. CORS核心需要配置服务器端是否允许跨域

2.2.1 常规ajax跨域请求

1).页面标识

<script type="text/javascript">
	/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
	$(function(){
		alert("我执行了AJAX");
		$.get("http://manager.jt.com/test.json",function(data){
			alert(data.name);
		})
	})
</script>

2).页面报错信息. 表示服务器端暂时不允许跨域.
在这里插入图片描述

2.3 服务器实现CORS跨域

说明: 服务器端如果需要实现CORS跨域请求,则需要在服务器端标识允许跨域的网址即可.

2.3.1 编辑页面实现跨域请求

编辑jt-web 中的test.html页面信息.

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

2).编辑json数据
在这里插入图片描述

2.3.2 编辑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 {

    //扩展跨域请求的方法
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //1.允许什么样的请求进行跨域
        // /* 只允许一级目录请求    /** 表示多级目录请求.
        registry.addMapping("/**")
        //2.允许哪些服务进行跨域
                .allowedOrigins("*")
                //3.是否允许携带cookie信息
                .allowCredentials(true)
                //4.定义探针检测时间 在规定的时间内不再询问是否允许跨域
                .maxAge(1800);
    }
}

2.3.3 编辑CORS流程图

在这里插入图片描述

2.3.4 CORS跨域响应信息.

在这里插入图片描述

3. 构建JT-SSO后台服务器

3.1 项目说明

说明: JT-SSO主要负责用户的单点登录操作.及用户数据认证的业务.由于不需要页面的支持,所以JT-SSO 打 jar包即可.

3.2 创建项目

3.2.1 创建jt-sso

在这里插入图片描述

3.2.2 添加继承/依赖/插件

<?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>com.jt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!--添加依赖-->
    <dependencies>
        <dependency>
            <groupId>com.jt</groupId>
            <artifactId>jt-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <!-- maven项目指定的插件配置 该插件主要负责 maven项目相关操作 打包/test/clean/update等相关maven操作 注意事项:但凡是maven项目则必须添加
		插件.否则将来项目部署必然出错 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.2.3 编辑User的POJO对象

说明:构建POJO对象

package com.jt.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;

@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;
}

3.2.4 构建代码层级结构

在这里插入图片描述

3.2.5 编辑UserController 编辑测试方法

package com.jt.controller;

import com.jt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

//服务器端程序要求返回的都是JSON 所以使用
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    /*demo测试*/
    @RequestMapping("/getMsg")
    public String  getMsg(){

        return "sso单点登录系统正常";
    }
}

3.2.6编辑Hosts文件

在这里插入图片描述

3.2.7 编辑nginx配置文件

修改nginx之后重启服务器.

# 配置前台服务器
	server {
		listen 80;
		server_name  sso.jt.com;

		location / {
			proxy_pass http://localhost:8093;
		}
	}

3.2.8.访问测试效果

在这里插入图片描述

3.3 完成用户信息校验

3.3.1 检查URL请求路径

在这里插入图片描述

3.3.2 检查JS

1).检索项目中的代码.
在这里插入图片描述
2).检查用户JSONP跨域请求
在这里插入图片描述

3.3.3 接口文档说明

在这里插入图片描述

3.3.4 编辑jt-sso UserController

package com.jt.controller;

import com.fasterxml.jackson.databind.util.JSONPObject;
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;

//服务器端程序要求返回的都是JSON 所以使用
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    /*demo测试*/
    @RequestMapping("/getMsg")
    public String  getMsg(){

        return "sso单点登录系统正常";
    }

    /**
     * 1.url请求地址: http://sso.jt.com/user/check/{param}/{type}
     * 2.请求参数:    {需要校验的数据}/{校验的类型是谁}
     * 3.返回值结果:  SysResult返回  需要包含true/false
     * 4.JSONP请求方式:  返回值必须经过特殊的格式封装 callback(json)
     */
    @RequestMapping("/check/{param}/{type}")
    public JSONPObject checkUser(@PathVariable String param,
                                 @PathVariable Integer type,
                                 String callback){

        //1.校验数据库中是否存在该数据
        boolean flag = userService.checkUser(param,type);  //存在true  不存在false
        return new JSONPObject(callback, SysResult.success(flag));
    }

}

3.3.5 编辑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 jdk.nashorn.internal.codegen.TypeMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpl implements  UserService{

    //采用工具API形式动态获取
    private static Map<Integer,String> typeMap = new HashMap<>();
    static {  //类加载时就要执行  只执行一次
        typeMap.put(1,"username");
        typeMap.put(2,"phone");
        typeMap.put(3,"email");
    }


    @Autowired
    private UserMapper userMapper;

    /**
     * 查询数据库,检查是否有数据.
     * @param param
     * @param type
     * @return  true 表示数据已存在   false 数据可以使用
     */
    @Override
    public boolean checkUser(String param, Integer type){
        //1.根据参数类型获取校验的类型 column
        String column = typeMap.get(type);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(column, param);
        int count = userMapper.selectCount(queryWrapper);
        return count==0?false:true;
    }


}

3.3.6 页面效果展现

在这里插入图片描述

3.3.7 全局异常处理机制

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   //定义异常处理的通知.  只拦截Controller层抛出的异常. 并且返回值JSON串
public class SystemExceptionAOP {

    /**
     * 如果跨域访问发生了异常 ,则返回值结果必须经过特殊的格式封装才行.
     * 如果是跨域访问形式,全局异常处理 可以正确的返回结果.
     * 思路: 1.判断用户提交参数中是否有callback参数
     * callback(json)
     * * @param e
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    public Object fail(Exception e, HttpServletRequest request){

        //1.获取用户的请求参数
        String callback = request.getParameter("callback");

        //2.判断参数是否有值
        if(StringUtils.isEmpty(callback)){
            //用户请求不是jsonp跨域访问形式
            //打印异常信息
            e.printStackTrace();
            return SysResult.fail();
        }else{
            //jsonp的报错信息.
            e.printStackTrace();
            return new JSONPObject(callback, SysResult.fail());
        }
    }
}

3.3.8 重构页面JS

$.ajax({
            	url : "http://sso.jt.com/user/check/"+escape(pin)+"/1?r=" + Math.random(),
            	dataType : "jsonp",
            	success : function(data) {  //sysResultJSON
                    checkpin = data.data?"1":"0";
                    //判断jsonp校验是否正常
                    if(data.status == 200){
                     if (!data.data) { //false
                        validateSettings.succeed.run(option);
                        namestate = true;
                         }else {
                            validateSettings.error.run(option, "该用户名已占用!");
                            namestate = false;
                         }
                    }else{
                        validateSettings.error.run(option, "服务器异常,请稍后重试!!!!");
                        namestate = false;
                    }

                }
            });

4. HttpClient

4.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)
SpringCloud跨域中实现远程数据访问底层实现就是httpClient.
httpClient作用: 在java代码内部发起http请求.

4.2 HttpClient入门案例

4.2.1 引入httpClient工具包

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

4.2.2 HttpClient入门案例

package com.jt;

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 {

    /**
     * 业务需求:在java代码中访问百度的页面
     * url: http://www.baidu.com    html代码片段
     * 实现步骤:
     *      1. 获取httpClient对象
     *      2. 自定义url地址
     *      3. 定义请求类型
     *      4. 发起请求 获取响应结果.
     *      5. 校验返回值状态,是否正确
     *      6. 获取返回值信息,之后完成后续业务处理.
     *      SDK......
     * */
    @Test
    public void test01(){
        HttpClient httpClient = HttpClients.createDefault();
        String url = "https://www.cctv.com";
        HttpGet get = new HttpGet(url);
        try {
            HttpResponse httpResponse = httpClient.execute(get);
            //获取返回值状态信息
            int status = httpResponse.getStatusLine().getStatusCode();
            if(status == 200){
                //请求正确的.  获取响应结果
                HttpEntity entity = httpResponse.getEntity(); //获取响应对象的实体信息.
                //将实体对象转化为用户能够识别的字符串
                String result = EntityUtils.toString(entity,"UTF-8");
                System.out.println(result);
            }else{
                System.out.println("httpClient调用异常.");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}

4.3 HttpClient高级案例

4.3.1 业务说明

用户通过 http://www.jt.com/user/httpClient/saveUser/{username}/{password} 访问服务器.要求利用httpClient技术将用户信息保存到jt-sso中.
发送url请求路径: http://sso.jt.com/user/httpClient/saveUser?username=xxxx&password=xxxx
实现数据传递.
在jt-sso中完成数据入库操作.

4.3.2 编辑jt-web Controller

package com.jt.controller;

import com.jt.pojo.User;
import com.jt.service.HttpClientService;
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;

@RestController     //学习httpCLient调用规范
public class HttpClientController {

    @Autowired
    private HttpClientService httpClientService;

    /**
     * 用户测试路径:
     * http://www.jt.com/user/httpClient/saveUser/admin123456/123456789
     * 将数据传递给sso.jt.com
     * return "用户请求成功"
     */
    @RequestMapping("/user/httpClient/saveUser/{username}/{password}")
    public String saveUser(User user){ //参数接收与对象的属性必须保持一致.可以自动赋值springmvc

        httpClientService.saveUser(user);
        return "httpClient测试成功!!!";
    }


}

4.3.2 编辑jt-web Service

package com.jt.service;

import com.jt.pojo.User;
import com.jt.unit.ObjectMapperUtil;
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.springframework.stereotype.Service;

import java.io.IOException;

@Service
public class HttpClientServiceImpl implements HttpClientService{

    //位置jt-web 不能直接链接数据库 需要将数据传递给sso.jt.com
   @Override
    public void saveUser(User user) {
       //1.将user对象转化为json   http://xxxxx?id=1&name=xxx
       String userJSON = ObjectMapperUtil.toJSON(user);
       String url = "http://sso.jt.com/user/httpClient/saveUser?username="
                        +user.getUsername()+"&password="+user.getPassword();
       //get请求

       HttpClient httpClient = HttpClients.createDefault();
       HttpGet get = new HttpGet(url);
       try {
          HttpResponse httpResponse =  httpClient.execute(get);
          if(httpResponse.getStatusLine().getStatusCode() != 200){
                throw new RuntimeException("请求错误");   
          }
       } catch (IOException e) {
           e.printStackTrace();
           throw new RuntimeException("请求错误");
       }

   }
}

4.3.3 编辑jt-sso Controller

 /**
     * 完成httpClient测试
     * url:http://sso.jt.com/user/httpClient/saveUser?username=111&password="2222"
     */
    @RequestMapping("/httpClient/saveUser")
    public SysResult saveUser(User user){

        userService.saveHttpCleint(user);
        return SysResult.success();
    }

4.3.4 编辑jt-sso Service

 @Override
    public void saveHttpCleint(User userPOJO) {
        userPOJO.setEmail("[email protected]") //数据库中要求email和phone是非空的 暂时写死
                .setPhone("1311112222");
        userMapper.insert(userPOJO);
    }

4.3.5 页面效果展现

测试URL地址: http://www.jt.com/user/httpClient/saveUser/admin123456/12345678
在这里插入图片描述

作业

1.跨域和httpClient调用区别!!! 相同点 不同点
2.RPC

猜你喜欢

转载自blog.csdn.net/qq_16804847/article/details/108071300