关于java:JTday15

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;
@Configuration
public 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、JSONP
2、CORS形式

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理