1、Redis集群阐明

1.1 分片、哨兵有哪些毛病

1、分片毛病:分片的次要的性能是实现内存的扩容,然而没有高可用的成果
2、哨兵毛病:数据没有扩容,哨兵自身没有高可用机制
需要:既能够实现内存数据的扩容,同时实现高可用机制(不必第三方)

1.2 Redis集群搭建


复制Redis的redis.conf
命令:cp redis.conf cluster/7000/

批改redis.conf文件

1、正文本地绑定IP地址

2、敞开保护模式

3、批改端口号

4、启动后盾启动

5、批改pid文件

6、批改长久化文件门路

7、设定内存优化策略

8、敞开AOF模式

9、开启集群配置

10、开启集群配置文件

11、批改集群超时工夫

12、7000里的redis.conf复制到7001、7002、7003、7004、7005
13、批改

把文件7001里的redis.conf文件里的7000批改为7001
把文件7002里的redis.conf文件里的7000批改为7002
把文件7003里的redis.conf文件里的7000批改为7003
把文件7004里的redis.conf文件里的7000批改为7004
把文件7005里的redis.conf文件里的7000批改为7005

把文件内容里的7000全副改为7002
命令::%s/7000/7002/g

1、首先敞开所有的Redis服务器

2、查看配置文件编辑是否正确
3、删除多余的配置文件

4、重启redis服务器

5、搭建redis集群
执行命令:

redis-cli --cluster create --cluster-replicas 1 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


编辑开启服务器脚本

开启服务 命令:sh start.sh

编辑敞开服务器脚本

命令:sh stop.sh

1.3 集群入门案例

@Test    public void testCluster(){        Set<HostAndPort> sets = new HashSet<>();        sets.add(new HostAndPort("192.168.126.129", 7000));        sets.add(new HostAndPort("192.168.126.129", 7001));        sets.add(new HostAndPort("192.168.126.129", 7002));        sets.add(new HostAndPort("192.168.126.129", 7003));        sets.add(new HostAndPort("192.168.126.129", 7004));        sets.add(new HostAndPort("192.168.126.129", 7005));        JedisCluster jedisCluster = new JedisCluster(sets);        jedisCluster.set("jedis", "集群赋值");        System.out.println(jedisCluster.get("jedis"));    }

1.4 面试题

1、redis集群中一共能够存储16384个key???
不对的
答:16384只是槽位的数量,只负责布局这个数据归谁治理的问题,至于数据如何存储,是由redis内存决定的

2、redis集群中最多能够有多少台主机
16384台主机

3、redis中如果遇到多线程操作,是否有线程安全性问题?
没有
因为:redis服务器是单过程线程操作,每次操作都是由一个线程执行,所以不会有线程安全性问题

4、redis如何实现内存数据的优化?
LRU、LFU、随机算法、TTL

1.5 SpringBoot整合redis集群

1.5.1 编辑properties文件

阐明:将redis集群的节点写入pro配置文件中

#redis集群配置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.5.2 编辑配置类

package com.jt.config;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import redis.clients.jedis.HostAndPort;import redis.clients.jedis.JedisCluster;import java.util.HashSet;import java.util.Set;@Configuration//标识我是配置类@PropertySource("classpath:/properties/redis.properties")public class RedisConfig {    @Value("${redis.nodes}")    private String nodes;                                             //node,node,node //实现redis集群操作 @Bean public JedisCluster jedisCluster(){        Set<HostAndPort> nodeSet=new HashSet<>();        String[] nodeArray=nodes.split(",");        for (String node:nodeArray) {                                //host:port String host=node.split(":")[0];            int port=Integer.parseInt(node.split(":")[1]);            nodeSet.add(new HostAndPort(host,port));        }        return new JedisCluster(nodeSet);    }     /* SpringBoot整合Redis分片,本质:ShardedJdeis对象,交给容器治理 *///    @Bean//    public ShardedJedis shardedJedis(){//        List<JedisShardInfo> shards=new ArrayList<>();//        String[] nodeArray=nodes.split(",");                  //截取//        for (String node:nodeArray) {                                //node=ip:port//            String host=node.split(":")[0];                   //截取//            int port=Integer.parseInt(node.split(":")[1]);    //转化为int类型//            //筹备分片节点信息//            JedisShardInfo info=new JedisShardInfo(host,port);//            shards.add(info);//        }//        return new ShardedJedis(shards);//    }//    @Value("${redis.host}")//    private String host;//    @Value("${redis.port}")//    private Integer port;////    @Bean//    public Jedis jedis(){//        return new Jedis(host,port);//    }}

1.5.3 编辑AOP配置

在AOP中注入Redis缓存对象

package com.jt.aop;import com.jt.anno.CacheFind;import com.jt.util.ObjectMapperUtil;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import redis.clients.jedis.JedisCluster;import java.util.Arrays;@Aspect //标识我是一个切面@Component //交给spring容器治理public class CacheAOP {    @Autowired private JedisCluster jedis;                   //实现集群的注入 //private ShardedJedis jedis;                 //实现分片对象的注入 //private Jedis jedis; /* 注意事项:当有多个参数时,joinPoint参数必须位列第一位 需要: 1、筹备key=注解的前缀 + 用户的参数 2、从redis中获取数据 有:从缓存中获取数据之后,间接返回值 没有:查询数据库之后再次保留到缓存中即可 办法: 动静获取注解的类型,看上去是注解的名称,然而本质是注解的类型,只有切入点表达式满足条件 则会传递注解对象类型 */ @Around("@annotation(cacheFind)")    public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind) throws Throwable {        Object result=null;                                             //定义返回值对象 String preKey=cacheFind.preKey();                               //获取key String key=preKey+"::"+ Arrays.toString(joinPoint.getArgs());   //拼接key //1、校验redis中是否有数据 if(jedis.exists(key)){            //如果数据存在,须要从redis中获取json数据,之后间接返回 String json=jedis.get(key);                                 //获取该数据 //1、获取办法对象 2、获取办法的返回值类型 MethodSignature methodSignature= (MethodSignature) joinPoint.getSignature();//MethodSignature该办法里有获取该办法的返回值类型 //2、获取返回值类型 Class returnType=methodSignature.getReturnType();           //获取返回值类型 result=ObjectMapperUtil.toObject(json,returnType);          //将JSON转化为对象 System.out.println("AOP查问缓存");        }else {            //代表没有数据,须要查询数据库 result=joinPoint.proceed();            //将数据转化为JSON String json= ObjectMapperUtil.toJSON(result);               //转化为JSON if (cacheFind.seconds()>0){                jedis.setex(key,cacheFind.seconds(),json);              //如果有设定工夫,则执行 }else{                jedis.set(key, json);                                   //没有设定工夫执行 }            System.out.println("AOP查询数据库");        }        return result;                                                  //返回该数据 }/* @Around("@annotation(com.jt.anno.CacheFind)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { //1.获取指标对象的Class类型 Class targetClass = joinPoint.getTarget().getClass(); //2.获取指标办法名称 String methodName = joinPoint.getSignature().getName(); //3.获取参数类型 Object[] argsObj = joinPoint.getArgs(); Class[]  argsClass = null; //4.对象转化为class类型 if(argsObj.length>0){ argsClass = new Class[argsObj.length]; for(int i=0;i<argsObj.length;i++){ argsClass[i] = argsObj[i].getClass(); } } //3.获取办法对象 Method targetMethod = targetClass.getMethod(methodName,argsClass); //4.获取办法上的注解 if(targetMethod.isAnnotationPresent(CacheFind.class)){ CacheFind cacheFind = targetMethod.getAnnotation(CacheFind.class); String key = cacheFind.preKey() + "::" +Arrays.toString(joinPoint.getArgs()); System.out.println(key); } Object object = joinPoint.proceed(); System.out.println("盘绕开始后"); return object; }*/ //切面 = 切入点表达式 + 告诉办法 //@Pointcut("bean(itemCatServiceImpl)") //@Pointcut("within(com.jt.service.ItemCatServiceImpl)") //@Pointcut("within(com.jt.service.*)")// .*一级包门路 ..*所有子孙后代包 //@Pointcut("execution(返回值类型 包名.类名.办法名(参数列表))") //@Pointcut("execution(* com.jt.service.*.*(..))") //正文:返回值类型任意类型 在com.jt.service下的所有子孙类  以add结尾的办法,任意参数类型//    public void pointCut(){//    } /* 需要: 1、须要获取以后指标办法的门路 2、获取指标办法的参数 3、获取指标办法的名称 *///    @Before("pointCut()")//    public void before(JoinPoint joinPoint){//        String classNamePath=joinPoint.getSignature().getDeclaringTypeName();//        String methodName=joinPoint.getSignature().getName();//        Object[] args=joinPoint.getArgs();//        System.out.println("办法的门路"+classNamePath);//        System.out.println("办法的名称"+methodName);//        System.out.println("办法的参数"+ Arrays.toString(args));//    }////    @Around("pointCut()")//    public Object around(ProceedingJoinPoint joinPoint){//        try {//            System.out.println("盘绕告诉开始");//            Object obj=joinPoint.proceed();            //如果有下一个告诉,就执行下一个告诉,如果没有就执行指标办法(业务办法)//            System.out.println("盘绕告诉完结");//            return obj;//        } catch (Throwable throwable) {//            throwable.printStackTrace();//            throw new RuntimeException(throwable);//        }//    }}

2、京淘前台我的项目搭建

2.1 京淘架构图设计

2.2 JT-WEB我的项目创立

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">    <!--我的项目坐标--> <modelVersion>4.0.0</modelVersion>    <artifactId>jt-web</artifactId>    <!--打war包--> <packaging>war</packaging>    <!--父级工程--> <parent>        <artifactId>jt2007</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插件--> <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build></project>

2.2.3 导入动态资源文件

阐明:将课前材料中的文件src目录导入到jt-web中

2.2.4 对于主启动类阐明

阐明:jt-web服务器启动时会加载数据源的自动化配置,然而web服务器没有配置数据源,所以报错

启动类上增加数据源启动

2.2.5 配置工作目录

2.3 域名反向代理

需要:要求用户通过http://www.jt.com拜访localhost:8092服务器

2.3.1 批改hosts文件

2.3.2 批改Nginx配置文件

#配置前台服务器    server {        listen 80;        server_name www.jt.com;        location / {            proxy_pass http://localhost:8092;        }    }

批改之后,重启nginx服务器

2.3.3 页面成果展示

2.4 谷歌浏览器禁用HTTPS

键入地址:

chrome://net-internals/#hsts:


批改实现之后,先清空缓存之后重启浏览器

2.5 开启后缀类型匹配

阐明: 因为京东商城的商品展示时通过
url:https://item.jd.com/100213774...

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;@Configurationpublic class MvcConfigurer implements WebMvcConfigurer{      //开启匹配后缀型配置 @Override public void configurePathMatch(PathMatchConfigurer configurer) {            configurer.setUseSuffixPatternMatch(true);   }}

URL地址小结:
1、http://www.jt.com/index 该申请会被Controller进行拦挡
2、http://www.jt.com/index.html 该申请默认条件下示意获取动态资源文件,不会被拦挡
个别条件下:Controller只拦挡前缀类型的申请. 如果须要拦挡后缀类型的申请须要独自配置

3、登录注册页面跳转

3.1 实现通用的页面跳转

url1:http://www.jt.com/user/login.... 跳转页面login.jsp
url2:http://www.jt.com/user/regist... 跳转页面register.jsp
需要: 是否利用一个Controller办法.实现通用页面的跳转?

package com.jt.config.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 {    /* 实现用户登录、注册页面的跳转 url1:   http://www.jt.com/user/login.html 跳转页面login.jsp url2:   http://www.jt.com/user/register.html 跳转页面register.jsp */     @RequestMapping("/{moduleName}")    public String module(@PathVariable String moduleName){            return moduleName;    }}

3.2 伪动态

伪动态是绝对实在动态来讲的,通常咱们为了加强搜索引擎的敌对性,都将文章内容生成动态页面,然而有的敌人为了实时的显示一些信息。或者还想使用动静脚本解决一些问题。不能用动态的形式来展现网站内容。然而这就损失了对搜索引擎的敌对性。怎么样在两者之间找个两头办法呢,这就产生了伪动态技术。伪动态技术是指展现进去的是以html一类的动态页面模式,但其实是用ASP一类的动静脚本来解决的。

总结:以.html结尾的一种动静页面的模式

作业

1、预习什么是跨域?

1、JSONP2、CORS形式