原理说明:
Redis的所有节点都会保存当前redis集群中的全部主从状态信息.并且每个节点都能够相互通信.当一个节点发生宕机现象.则集群中的其他节点通过PING-PONG检测机制检查Redis节点是否宕机.当有半数以上的节点认为宕机.则认为主节点宕机.同时由Redis剩余的主节点进入选举机制.投票选举链接宕机的主节点的从机.实现故障迁移.
说明:当redis主节点宕机之后.没有从节点进行替补,则整个redis集群崩溃!!!
特点:集群中如果主机宕机,那么从机可以继续提供服务,
当主机中没有从机时,则向其它主机借用多余的从机.继续提供服务.如果主机宕机时没有从机可用,则集群崩溃.
答案:9个redis节点,节点宕机5-7次时集群才崩溃.
知识准备:
1.当用户操作redis主机时,从机会自动的实现数据的同步!!! (主从复制)
2.Redis集群搭建的主要的目的2个 1.实现内存扩容 2.可以实现Redis的高可用.
3.redis中的主机所保存的数据都是不相同的!!!.
4.redis集群中的数据存储,不是随机存储,内部有算法的支持. hash槽算法(分区算法)
Redis集群搭建的划分:
存储的原理:
说明: RedisCluster采用此分区,所有的键根据哈希函数(CRC16[key]%16384)映射到0-16383槽内,共16384个槽位,每个节点维护部分槽及槽所映射的键值数据.根据主节点的个数,均衡划分区间.
算法:哈希函数: Hash()=CRC16[key]%16384
当向redis集群中插入数据时,首先将key进行计算.之后将计算结果匹配到具体的某一个槽的区间内,之后再将数据set到管理该槽的节点中.
如图-27所示
说明:根据分布式的规则.jt-web服务器只负责数据的展现.如果需要后端数据的支持,则需要通过远程访问的形式动态的获取数据.之后将数据通过js填充到页面中即可,实现了前后端分离.
目的: 实现了系统的解耦!!!
注意事项: web项目打包类型: war
<parent>
<groupId>com.jt.huanan</groupId>
<artifactId>jt</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<!--2.添加依赖 jt-common -->
<dependencies>
<dependency>
<groupId>com.jt.huanan</groupId>
<artifactId>jt-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<!--3.添加插件 -->
<!--build是负责项目打包部署 一般将项目开发完成之后,需要进行服务器部署(Linux) -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
复制文件的路径:
将上述的src文件导入到jt-web项目中即可.
//在jt-web服务器启动时,不会加载数据源的配置.
@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)
public class SpringBootRun {
public static void main(String[] args) {
SpringApplication.run(SpringBootRun.class,args);
}
}
说明:通过localhost:8092服务器访问jt-web服务器.
说明: 用户通过www.jt.com:80的方式 访问localhost:8092服务器.
1).配置hosts文件
#配置Linux环境下的服务
#192.168.126.129 image.jt.com
#192.168.126.129 manage.jt.com
# 京淘电商环境
127.0.0.1 image.jt.com
127.0.0.1 manage.jt.com
127.0.0.1 www.jt.com
127.0.0.1 sso.jt.com
2).配置nginx配置文件
#配置jt-web服务器
server {
listen 80;
server_name www.jt.com;
location / {
proxy_pass http://localhost:8092;
}
}
配置文件之后,重启nginx服务器即可
说明:个别谷歌浏览器会将http请求默认转化为https请求方式,如果采用https的请求方式,则必然会出现如下的问题.
解决方案:应该告知谷歌浏览器,禁止将http请求的方式自动转化为https即可.
解决方法:
1).在浏览器地址栏中输入 “chrome://net-internals/#hsts:“
2).编辑谷歌浏览器配置
3).之后将浏览器缓存清空,之后重启浏览器即可.
说明:当用户点击登陆/注册页面时,应该跳转到指定的页面.
url1:http://www.jt.com/user/register.html
http://www.jt.com/user/login.html
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 实现页面跳转
* 1.http://www.jt.com/user/login.html
* 2.要求跳转的页面是 login.jsp
*
* 业务说明:一般利用springMVC进行请求拦截时,不会拦截后缀.
* 要求: 用户通过www.jt.com/user/login的方式同样可以实现页面跳转.
*核心: 告知springMVC框架,要求拦截后缀.
*/
@RequestMapping("/login")
public String login() {
return "login";
}
}
2).开启后缀类型匹配
@Configuration //web.xml配置文件
public class MvcConfigurer implements WebMvcConfigurer{
//开启匹配后缀型配置
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(true);
}
}
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 实现页面跳转
* 1.http://www.jt.com/user/login.html
* 要求跳转的页面是 login.jsp
* 3.http://www.jt.com/user/register.html
* 要求跳转的页面是 register.jsp
*
*
* 业务说明:一般利用springMVC进行请求拦截时,不会拦截后缀.
* 要求: 用户通过www.jt.com/user/login的方式同样可以实现页面跳转.
*核心: 告知springMVC框架,要求拦截后缀.
*/
@RequestMapping("/{moduleName}")
public String login(@PathVariable String moduleName) {
return moduleName;
}
}
说明:jt-sso主要负责的是用户的相关操作 注册/登陆/登出等操作.
打包方式: jar包项目.
<parent>
<groupId>com.jt.huanan</groupId>
<artifactId>jt</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<!--2.添加依赖 jt-common -->
<dependencies>
<dependency>
<groupId>com.jt.huanan</groupId>
<artifactId>jt-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<!--3.添加插件 -->
<!--build是负责项目打包部署 一般将项目开发完成之后,需要进行服务器部署(Linux) -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
create table tb_user
(
id bigint not null auto_increment,
username varchar(50),
password varchar(32) comment 'MD5加密',
phone varchar(20),
email varchar(50),
created datetime,
updated datetime,
primary key (id)
);
@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; //暂时用电话代替邮箱
}
//@Mapper
public interface UserMapper extends BaseMapper<User>{
//java规定: interface不允许直接new对象
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.selectList(null);
}
}
//是否需要跳转页面 true:@Controller false:@RestController
@RestController
public class UserController {
@Autowired
private UserService userService;
//测试方法 ,查询所有的用户信息
@RequestMapping("/findAll")
public List<User> findAll(){
return userService.findAll();
}
}
//标识该启动类是SpringBoot的方式
@SpringBootApplication
@MapperScan("com.jt.mapper") //mapper的包路径 之后根据指定的接口包路径创建代理对象
public class SpringBootRun {
public static void main(String[] args) {
SpringApplication.run(SpringBootRun.class, args);
}
}
server:
port: 8093
servlet:
context-path: /
spring:
datasource:
#引入druid数据源
#type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.jt.mapper: debug
说明:当用户进行信息注册时,当用户输入完成用户名/手机号之后,需要将用户信息获取之后发送到后端服务器JT-SSO中实现数据的校验, 如果数据库中已经存在该数据,则通知用户,用户名或电话已存在.
1.服务器A: www.jt.com
2.服务器B: sso.jt.com
服务器A与服务器B如何通信???
常见方式:
1.httpClient
2.ajax 的跨域访问
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)
总结: httpClient是支持http协议的客户端编程工具包.
<!--添加httpClient jar包 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
案例说明: 要求在jt-web的服务器中,获取jt-sso服务器中的user数据. url请求地址如下:http://localhost:8093/findAll
public class TestHttpClient {
/**
* 目的: jt-web 访问jt-sso获取服务器数据
*url:http://localhost:8093/findAll
*实现步骤:
* 1.新建httpClient工具API对象
* 2.确定请求的网址
* 3.封装请求方式 get/post/put/delete
* 4.发起请求
* 5.判断用户的请求是否正确.
* 6.如果请求正确,则获取返回值结果
*
* 总结: httpClient相当于在java程序内部内置了一个浏览器.通过http请求协议
* 动态获取远程服务器资源. 该用法是一种万能的用法.
*/
@Test
public void testGet() {
CloseableHttpClient client = HttpClients.createDefault(); //实例化对象
//String url = "http://localhost:8093/findAll";
String url = "https://www.baidu.com";
HttpGet httpGet = new HttpGet(url);
try {
CloseableHttpResponse response = client.execute(httpGet);
//判断状态码信息是否为200
int status = response.getStatusLine().getStatusCode();
if(status == 200) {
System.out.println("客户端请求服务端正常");
//表示服务端响应正常.
HttpEntity httpEntity = response.getEntity(); //获取服务端响应数据
//将实体对象转化为字符串输出.
String result = EntityUtils.toString(httpEntity,"UTF-8");
System.out.println(result);
}else {
System.out.println("客户端请求服务器异常:"+status);
}
} catch (IOException e) {
System.out.println("客户端请求服务器异常");
}
}
}
说明:根据图中路径发现使用httpClient的方式调用的层级较多.开发效率低.但是该方法是万能用法.
例如: 自己的项目中需要调用支付宝的接口/微信接口/第三方公司的接口.一般都会使用httpClient.
因为http协议是当下最为主要的通信方式.
说明:
域名: http://manage.jt.com/test.html
ajax网址: http://manage.jt.com/test.json
现象:如果域名相同,则可以正确的完成ajax请求,获取返回值结果.
说明:
域名:http://www.jt.com/test.html
ajax网址:ajax网址: http://manage.jt.com/test.json
现象: ajax请求无法正确的获取服务端数据. 请求失败.
说明:浏览器出于安全性的考虑,要求请求必须满足同源策略.
规定: 1.请求协议名称 http/https/tcp等
2. 请求网址 manage.jt.com…等
3. 请求的端口 :80
如果上述的三项都一致则满足同源策略.浏览器可以正确的解析ajax请求.并且解析返回值.
如果上述的三项有一项不同 则违反了同源策略的规定.这时的请求为跨域请求.浏览器默认条件下不予解析返回值.(除非特殊配置)
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的
1.利用javaScript中的src的开放策略实现跨域
<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":"tom"})
<!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>
package com.jt.web.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 该类的主要的作用是实现JSONP跨域访问.
* @author LYJ
*
*/
@RestController //返回的数据要求是json
public class JSONPController {
/**
* 1. 网址:http://manage.jt.com/web/testJSONP?callback=jQuery1111 自动生成自动拼接
* 2.返回值的格式要求: callback(JSON) 规定!!!!!
* @return
*/
@RequestMapping("/web/testJSONP")
public String jsonp(String callback) {
String json = "{'name':'jsonp跨域调用成功!!!!!'}";
return callback + "("+json+")";
}
}
要求在jt-web服务器向jt-sso发起请求,获取user用户信息.
url地址: http://localhost:8093/findAll
<!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地址
//url:"http://manage.jt.com/web/testJSONP",
url:"http://localhost:8093/findAll",
type:"get", //jsonp只能支持get请求
dataType:"jsonp", //dataType表示返回值类型
//jsonp: "callback", //指定参数名称
//jsonpCallback: "hello", //指定回调函数名称
success:function (data){ //data经过jQuery封装返回就是json串
console.log(data);
}
});
})
</script>
</head>
<body>
<h1>JSON跨域请求测试</h1>
</body>
</html>
//是否需要跳转页面 true:@Controller false:@RestController
@RestController
public class UserController {
@Autowired
private UserService userService;
//测试方法 ,查询所有的用户信息
/*@RequestMapping("/findAll")
public List findAll(){
return userService.findAll();
}*/
/*
* 利用跨域的形式获取user数据
*
**/
/*@RequestMapping("/findAll")
public String findAll(String callback) {
List userList = userService.findAll();
String json = ObjectMapperUtil.toJSON(userList);
return callback+"("+json+")";
}*/
/**
* JSONP 高级用法
* @param callback
* @return
*/
@RequestMapping("/findAll")
public JSONPObject findAll(String callback) {
//业务数据是什么
List<User> userList = userService.findAll();
return new JSONPObject(callback, userList);
//返回之后,可以将jsonpObject对象自动的封装为指定的格式
}
}
1.什么是跨域
浏览器解析页面JS,发起的ajax请求.但是该请求违反了同源策略,称之为跨域请求.
2.HttpClient 是万能的请求通讯方式,和浏览器无关. 主要的用途在java代码中发起http请求.
1.通过代码 编辑2个页面,发起2个跨域请求. 返回结果并且alert打印输出.
2.work文档 总结什么是跨域 ,跨域的种类有多少种(多多益善)
最好简述 每种跨域的优点和缺点.