京淘项目实战开发-14 【集群工作原理、前台搭建、跨域问题】

1.集群工作原理

1.1 集群宕机条件

宕机条件: 如果节点主机数量缺失,则集群崩溃.

  • 案例1: 1主1从
    现在→ 3台主机 / 3台从机 共6台redis

问至少宕机几台 集群崩溃? 2台
在这里插入图片描述

  • 案例2: 1主2从
    现在→ 3台主机 / 6台从机 共9台redis

问至少宕机几台 集群崩溃? 5台
在这里插入图片描述

  • 案例3:1主3从
  • 现在→ 3台主机 / 9台从机 共12台redis

问至少宕机几台 集群崩溃? 8台


1.2 Redis集群入门案例

 /**
     * Redis集群测试
     * set操作主机! slave只负责数据的同步
     */
    @Test
    public void testRedisCluster(){
        Set<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.126.129", 7000));
        nodes.add(new HostAndPort("192.168.126.129", 7001));
        nodes.add(new HostAndPort("192.168.126.129", 7002));
        nodes.add(new HostAndPort("192.168.126.129", 7003));
        nodes.add(new HostAndPort("192.168.126.129", 7004));
        nodes.add(new HostAndPort("192.168.126.129", 7005));
        JedisCluster jedisCluster = new JedisCluster(nodes);
        jedisCluster.set("aa", "redis集群测试"); //如何存储? 存入的那台主机?
        System.out.println("获取数据:"+jedisCluster.get("aa"));
    }

在这里插入图片描述

1.3 hash槽算法

1.3.1 算法介绍

       说明: RedisCluster采用此分区,所有的键根据哈希函数(CRC16[key]%16384)映射到0-16383槽内,共16384个槽位(2^14次方),每个节点维护部分槽及槽所映射的键值数据.根据主节点的个数,均衡划分区间.

算法:哈希函数: Hash()=CRC16[key]%16384
在这里插入图片描述
       当向redis集群中插入数据时,首先将key进行计算.之后将计算结果匹配到具体的某一个槽的区间内,之后再将数据set到管理该槽的节点中.
如图-27所示
在这里插入图片描述

1.3.2 面试题说明

1). 如果分区对不同的key hash(key1)= 3000 hash(key2)=3000

问? 算法是否有误? 是否影响数据的存取?

A 不影响

执行过程:
存:key1/key2 都归第一个主机node进行管理. redis.set(key1,value1), redis.set(key2,value2);
取: key1 hash(key1)=3000 找到node 进行取值操作 redis.get(key1) 结果一定正确

2). redis集群中最多存储16384个数据? 错!
16384只是hash槽位的个数,与存储数量没有必然的联系。能存储多少 完全由redis内存决定。

3). redis集群中主机的数量有没有要求? A:有要求 B:无限的? A : 3-16384台

1.4 SpringBoot整合Redis集群

1.4.1 编辑配置文件

redis.nodes=192.168.126.129:7000,192.168.126.129:7001,192.168.126.129:7002,192.168.126.129:7003,192.168.126.129:7004,192.168.126.129:7005

在这里插入图片描述

1.4.2 编辑Redis集群配置类

@Configuration  //标识为一个配置类, 一般整合第三方
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {

    @Value("${redis.nodes}")
    private String nodes;       //node,node,node

    @Bean
    public JedisCluster jedisCluster(){
        //new 一个HashSet集合
        Set<HostAndPort> nodeSet = new HashSet<>();
        //使用,号拆分
        //把nodes按照 ,号,拆分成一个一个节点的数组
        String[] nodeArray = nodes.split(",");
        //进行循环遍历
        for (String node : nodeArray){
            //获取ip地址和端口
            String host = node.split(":")[0];
            int port = Integer.parseInt(node.split(":")[1]);
            //封装参数
            HostAndPort hostAndPort = new HostAndPort(host,port);
            nodeSet.add(hostAndPort);
        }
        //创建连接池,编辑redis配置文件,调整连接数量
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMinIdle(10);//最小空闲数量,最小连接数
        jedisPoolConfig.setMaxIdle(40);//最大的空闲数量
        jedisPoolConfig.setMaxTotal(1000);//最大连接数
        //调用连接池
        return new JedisCluster(nodeSet,jedisPoolConfig);
    }

1.4.3 编辑Redis AOP

    //注入对象
    @Autowired
    //private Jedis jedis; //单台redis
    //private ShardedJedis jedis; //分片redis 内存扩容
    private JedisCluster jedis; //redis集群

在这里插入图片描述

2. 京淘项目前台搭建

2.1 京淘前后端调用

在这里插入图片描述

2.2 京淘前台搭建

2.2.1 创建JT-WEB

在这里插入图片描述

2.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">
    <!--添加继承-->
    <parent>
        <artifactId>jt</artifactId>
        <groupId>com.jt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <!--打包方式 html jar|jsp war -->
    <packaging>war</packaging>
    <artifactId>JT_WEB</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <!--添加依赖-->
    <dependencies>
        <dependency>
            <groupId>com.jt</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>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.2.3 导入静态资源文件

在这里插入图片描述

2.2.4 配置京淘启动项

在这里插入图片描述

如果报错404 则需要重新配置工作目录即可.
在这里插入图片描述
启动测试
在这里插入图片描述

2.2.5 配置域名代理

要求: http://www.jt.com 的方式访问localhost:8092的服务器.

修改hosts文件:
在这里插入图片描述

修改nginx.conf
在这里插入图片描述

	# 京淘前台管理系统
	server {
		listen 80;
		server_name www.jt.com;

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

	#nginx配置必须在http协议之内完成,否则不生效

修改nginx配置文件之后,重启nginx服务器
在这里插入图片描述

2.2.6 关于https访问报错说明

个别的浏览器 可能将请求路径 自动的转化为https

解决方案:

1.去京淘问题集中 查找答案

2.自己百度 https禁用
在这里插入图片描述
在这里插入图片描述

2.3 拦截静态资源.html

2.3.1 业务分析

通常情况下,需要获取商品信息时,一般采用都是restFul风格, {itemId}.html 要求后端服务器应该拦截.html为结尾的请求即可。
在这里插入图片描述

2.3.2 以.html结尾的优势

如果网站页面 以.html为结尾的请求,则该页面更加容易被搜索引擎记录. 通过搜索引擎提高网站的曝光率.
搜索引擎工作原理:
在这里插入图片描述

2.3.3 后台服务器拦截策略

package com.jt.controller;

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

@Controller
public class IndexController {

    @RequestMapping("index")
    public String index(){
        return "index";
    }
}

1.默认条件下后台服务器只拦截前缀型请求
在这里插入图片描述
2.如果在浏览器中写入index.html 则后台服务器认为,请求的是一个具体的静态页面
在这里插入图片描述
我们来添加一个页面:
在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
	
</head>
<body>
	<h1>首页测试</h1>
</body>
</html>

在这里插入图片描述

3.如果需要后台服务器拦截静态页面,之后通过服务器进行中转,则需要额外的配置

package com.jt.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfigurer implements WebMvcConfigurer{
	
	//开启匹配后缀型配置  .html请求时 springMVC才会拦截.
	@Override
	public void configurePathMatch(PathMatchConfigurer configurer) {
		
		configurer.setUseSuffixPatternMatch(true);
	}
}

2.3.4 伪静态

       伪静态是相对真实静态来讲的,通常我们为了增强搜索引擎的友好面,都将文章内容生成静态页面,但是有的朋友为了实时的显示一些信息。或者还想运用动态脚本解决一些问题。不能用静态的方式来展示网站内容。但是这就损失了对搜索引擎的友好面。怎么样在两者之间找个中间方法呢,这就产生了伪静态技术。伪静态技术是指展示出来的是以html一类的静态页面形式,但其实是用ASP一类的动态脚本来处理的。
总结: 以.html结尾的"动态"页面技术

2.4 用户登录/注册跳转

2.4.1 业务需求说明

1). 当用户网址 http://www.jt.com/user/login.html 要求跳转到登录页面中 login.jsp

2). 注册页面 http://www.jt.com/user/register.html 要求跳转到登录页面中 register.jsp

要求用一个方法实现通用的页面跳转

2.4.2 利用RestFul实现页面跳转

说明:编辑UserController 利用restFul的方式,实现页面通用跳转

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
     */
    //modleName模块名
    @RequestMapping("/{modleName}")
    public String module(@PathVariable String modleName){

        return modleName;
    }
}

运行测试:
http://www.jt.com/user/register.html
在这里插入图片描述
http://www.jt.com/user/login.html
在这里插入图片描述

3 关于跨域问题说明

3.1 跨域测试

3.1.1 测试demo1

在这里插入图片描述
在这里插入图片描述

1).访问页面的网址 http://manage.jt.com:80/test.html

2).Ajax访问数据的地址: http://manage.jt.com:80/test.json

分析: 协议://域名:端口 完全一致.

测试是否正常: 测试正常
在这里插入图片描述

结论: 如果协议://域名:端口号 都相同时 请求可以正常的进行.


3.1.2 测试demo2

1).访问页面的网址 http://www.jt.com:80/test.html

2).Ajax访问数据的地址: http://manage.jt.com:80/test.json

分析: 协议://域名:端口 域名不同.
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

测试结果: ajax调用无法正常执行.


3.1.3 关于浏览器同源策略的说明

说明: 浏览器规定 当浏览器解析页面时,当遇到ajax请求时 如果请求与当前页面的 协议://域名:端口号都相同时,则满足同源策略 称之为同域

请求.浏览器可以正确解析返回值 请求正常.

如果三者中有一项不同,则把请求称之为叫做跨域请求. 浏览器出于安全性的考虑 则不予解析返回值.
在这里插入图片描述

远程请求的流程:
在这里插入图片描述

3.2 JSONP

3.2.1 关于JSONP介绍

JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略(src),网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解

重点:JSONP实现跨域,利用Script中的开放策略src属性实现的远程数据获取


服务端 JSONP 格式数据:

如客户想访问 : https://www.baidu.com/try/ajax/jsonp.php?jsoncallback=callbackFunction

假设客户期望返回数据:["customername1","customername2"]

真正返回到客户端的数据显示为: callbackFunction(["customername1","customername2"])


3.2.2 JSONP原理说明

1). 利用javaScript标签 动态获取远程数据

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

2).自定义回调函数

<script type="text/javascript">
		/*JS是解释执行的语言  */
		/*定义回调函数  */
		function hello(data){
			alert(data.name);
		}
	</script>

3). 将返回值结果 进行特殊格式封装

hello({"id":"1","name":"tom"})

在这里插入图片描述

问题: JSONP能否发起POST请求啊?

不能 原因: javaScript中的src属性只能发起get请求,不可以用POST。

3.2.3 jQuery中的JSONP

3.2.3.1 编辑页面JS

<!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("测试访问开始!!!!!")
		$.ajax({
			url:"http://manage.jt.com/web/testJSONP",
			type:"get",				//jsonp只能支持get请求
			dataType:"jsonp",       //dataType表示返回值类型  必须添加
			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>

3.2.3.2 京淘后台业务实现

package com.jt.web;

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

    @RequestMapping("/web/testJSONP")
    public JSONPObject testJSONP(String callback){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("详情信息2222");
        return new JSONPObject(callback, itemDesc);//函数名字,值
    }


    /**
     * JSONP请求 返回值要求:  callback(JSON)
     * 1.请求网址:  http://manage.jt.com/web/testJSONP?callback=xxxx
     * 2. 页面取值  itemDesc属性
     */
   /* @RequestMapping("/web/testJSONP")
    public String testJSONP(String callback){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("详情信息");
        String json = ObjectMapperUtil.toJSON(itemDesc);
        //jsonp步骤3 封装指定的格式
        return callback + "(" + json + ")";
    }*/
}
	$(function(){
		alert("测试访问开始!!!!!")
		$.ajax({
			url:"http://manage.jt.com/web/testJSONP",
			type:"get",				//jsonp只能支持get请求
			dataType:"jsonp",       //dataType表示返回值类型
			//jsonp: "callback",    //指定参数名称
			//jsonpCallback: "hello",  //指定回调函数名称
			success:function (data){   //data经过jQuery封装返回就是json串
				alert(data.itemDesc);

运行测试:
在这里插入图片描述在这里插入图片描述

3.2 CORS

3.2.1 CORS介绍

跨源资源共享 (CORS) (或通俗地译为跨域资源共享)是一种基于HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域,协议和端口),这样浏览器可以访问加载这些资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有HTTP方法和真实请求中会用到的头。

补充: 现阶段几乎所有的浏览器都默认支持CORS(IE除外)


3.2.2 CORS跨域测试

复制Web中的test.html,修改为cors.html

1).修改ajax请求路径

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

	$(function(){
		alert("我执行了AJAX");
		//利用jQuery发起AJAX请求
		$.get("http://manage.jt.com/cors.json",function(data){
			alert(data.name);
		})
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>

2)标识后端的JSON

复制manage中的test.json改为cors.json

{"id":"1","name":"cors的JSON"}

3).跨域的报错
在这里插入图片描述

3.2.3 CORS跨域原理

说明: CORS 在响应头中标识哪些网址可以访问服务器,CORS的配置是服务器端的配置和浏览器没关系!
在这里插入图片描述

3.2.4 编辑后台Controller

1)修改为cors.html

	$(function(){
		$.get("http://manage.jt.com/testCors",function(data){
			alert(data.itemDesc);
		})
	})

2)添加后端控制

package com.jt.web;

import com.jt.pojo.ItemDesc;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(value = "http://www.jt.com")   //标识当前Controller中的方法 允许被其他服务器访问
                                         //预检: 在规定时间内同源策略不会再次拦截 提高效率
public class CorsController {

    /**
     * http://manage.jt.com/testCors
     * @return
     */
    @RequestMapping("testCors")
    public ItemDesc cors(){

        return new ItemDesc().setItemDesc("CORS测试");
    }
}

响应头信息:
在这里插入图片描述

在这里插入图片描述


预检:在规定时间内同源策略不会再次拦截 提高效率

//标识当前Controller中的方法 允许被其他服务器访问
@CrossOrigin(value = "http://www.jt.com",maxAge = 180)   
//预检: 在规定时间内同源策略不会再次拦截 提高效率
public class CorsController {

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值