精华内容
下载资源
问答
  • SpringMVC和Struts2中拦截器的实现思想思路

    SpringMVC中拦截器的实现思想
    springMVC中拦截器的实现主要是通过doFilte()方法的返回值(boolean)来控制拦截器是否继续向下执行,如果返回true执行,则放行到下一个拦截器或者放行到最终处理请求的方法中。如果在执行中途返回了false,则触发执行triggerAfter()方法,否则就一直执行完处理请求的那个方法再触发执行triggerAfter()方法。(注:after()方法和before()方法是在拦截请求之前和之后可以做一些事情,这里是通过拦截器来实现的,其实还可以用动态代理来实现,但是这里不进行讲述)
    package org.springmvcinterceptor;

    import java.util.ArrayList;
    import java.util.List;

    public class InterceptorExecutor {

    private List<Interceptor> interceptorList=new ArrayList<>();
    private int interceptorIndex=-1;
    
    public InterceptorExecutor(){
        interceptorList.add(new Interceptor1());
        interceptorList.add(new Interceptor2());
        interceptorList.add(new Interceptor3());
    }
    
    /**
     * 控制执行所有过滤器中的方法
     */
    public void execute(){
        for(int i=0;i<interceptorList.size();i++){
            if(interceptorList.get(i).doFilter()){
                interceptorList.get(i).before();
                interceptorList.get(i).doFilter();
                //记录好程序执行到哪个拦截器
                interceptorIndex=i;
            }else{
                triggerAfter();
            }
        }
    
    }
    
    /**
     * 当doFilter方法返回false时(即程序被拦截不放行时)
     * 触发执行之前执行过doFilter方法的拦截器的after方法
     */
    public void triggerAfter(){
        for(int j=interceptorIndex-1;j>0;j--){
            interceptorList.get(j).after();
        }
    }
    

    }

    package org.springmvcinterceptor;

    public interface Interceptor {

    boolean before();
    
    boolean doFilter();
    
    void after();
    

    }

    package org.springmvcinterceptor;

    public class Interceptor1 implements Interceptor {
    @Override
    public boolean before() {
    return true;
    }

    @Override
    public boolean doFilter() {
        return false;
    }
    
    @Override
    public void after() {
    
    }
    

    }

    package org.springmvcinterceptor;

    public class Interceptor2 implements Interceptor {
    @Override
    public boolean before() {
    return true;
    }

    @Override
    public boolean doFilter() {
        return false;
    }
    
    @Override
    public void after() {
    
    }
    

    }

    package org.springmvcinterceptor;

    public class Interceptor3 implements Interceptor {
    @Override
    public boolean before() {
    return false;
    }

    @Override
    public boolean doFilter() {
        return false;
    }
    
    @Override
    public void after() {
    
    }
    

    }


    Struts2中拦截器的实现
    struts2中的拦截器是通过递归的方式来实现的,假设有一个A,在类的构造方法中将所有元素放到list集合中,在A方法中调用类B的bm1()方法,并将A对象自身(this)传给B类,在B类中又调用A类中的am1()方法,在B类调用A类am1()方法之前可以做一些事情,类似于拦截器的before()方法,在之后做的事情类似于拦截器的after()方法,跳出递归的条件相当于执行完了最终处理请求的方法。

    public class A {

    private  C c = new C();
    List<B> bList = new ArrayList<>();
    public A(){
        bList.add(new B(1));
        bList.add(new B(2));
        bList.add(new B(3));
        bList.add(new B(4));
    }
    
    private  int i = -1;
    public  void am1(){
        i++;
        if(i>= bList.size()) {
            c.cm1();
        }else {
    
    
            B b = bList.get(i);
            b.bm1(this);
            //System.out.println("method 1 in a----" + i);
        }
    }
    

    }

    public class B {
    private int id;

    public B(int id) {
        this.id = id;
    }
    
    public  void bm1(A a){
        System.out.println("method 1 in B before*****" + id);
        a.am1();
        System.out.println("method 1 in b after -----"  + id);
    }
    

    }

    public class Main {
    public static void main(String[] args) {
    A a = new A();
    a.am1();
    }
    }

    执行结果:

    method 1 in B before*****1
    method 1 in B before*****2
    method 1 in B before*****3
    method 1 in B before*****4
    method 1 in c—–
    method 1 in b after —–4
    method 1 in b after —–3
    method 1 in b after —–2
    method 1 in b after —–1

    展开全文
  • 排他思想的几种思路

    2020-05-30 22:37:10
    排他思想的优化版` Document 哼哼 哼哼 哼哼 哼哼 哼哼 <script> //第一种思路 : 好理解,代码效率不高 (存在重复设置) 先无条件的把所有按钮的样式全部取消 for (var j = 0; j < ...

    排他思想的优化版`

    Document 哼哼 哼哼 哼哼 哼哼 哼哼
    <script>
      //第一种思路 : 好理解,代码效率不高 (存在重复设置)
                先无条件的把所有按钮的样式全部取消
                for (var j = 0; j < buttonList.length; j++) {
                buttonList[j].style.backgroundColor = '';
                 buttonList[j].innerText = '哼哼';
               };
                 设置this的样式
               this.style.backgroundColor = 'pink';
               this.innerText = '哈哈';
    </script>
    
    ``` 排他思想的核心思路是: 1.获取按钮元素,然后遍历此元素得到一个伪数组; 2.我们先把所有的按钮背景颜色去掉 (干掉所有人); 3.再重新给我们点击的按钮添加背景颜色(留下我自己);

    这种写法有个致命的缺点,就是每次运行此代码都会遍历一次数组去掉每个元素的样式(包括自己),然后在给我么需要的元素添加样式,浏览器的重复执行了很多任务,代码运行效率不高。那么我们能不能只给我们需要按钮修改样式。

    第二种思路

    //第二种思路 : 不好理解,代码效率高
    //排他思想 : 遍历每一个按钮,判断这个按钮与this是不是同一个

                for (var j = 0; j < buttonList.length; j++) {
                    if (buttonList[j] == this) {//是自己
                        buttonList[j].style.backgroundColor = 'pink';
                        buttonList[j].innerText = '哈哈';
        
                    } else {//不是自己
                        buttonList[j].style.backgroundColor = '';
                        buttonList[j].innerText = '哼哼';
                    };
                };
    

    第二种排他思想跟第一种没上面太大的区别,只是增加了if判断;即,判断是自己就修改样式,不是自己就设置默认样式,大大提高了代码效率

    展开全文
  • 坐标型动态规划 poj1191棋盘分割 poj1088滑雪 noi过河卒 动态规划的解题思想思路
  • 2014届毕业生就业质量报告目录序言1一就业工作的指导思想和工作思路2二就业基本状况与特色工作32.1就业基本状况32.2就业特色工作42.2.1培养为基统筹互动加强就业对招生人才培养的反馈42.2.
  • 设计测试思路思想

    千次阅读 2018-01-06 17:59:35
    区分测试模块比重 1.首先,分析哪些功能对用户来说是核心且重要的...设计测试用例的思想 1.分析需求点,列出正向测试用例:例如A对象通过B对象进行操作,最后的操作结果正确 2.根据正向测试用例,将测试对象分离出来

    区分测试模块比重

    1.首先,分析哪些功能对用户来说是核心且重要的功能,必须保证其准确性,需要考虑全面;

    2.其次,区分哪些模块是存在复杂逻辑的关键性模块,需要分派测试设计和思考的时间应该比较长;

    3.最后,对于简单模块分派测试时间相对较少;

    设计测试用例的思想

    1.分析需求点,列出正向测试用例:例如A对象通过B对象进行操作,最后的操作结果正确

    2.根据正向测试用例,将测试对象分离出来

    3.分别对每个测试对象列出测试点,例如容量大小(长度)、不同格式等

    4.列出容错性测试点:例如人为操作产生中断、遇到特殊情况导致中断、被操作对象坏掉、被操作对象被限制了一部分权限等

    5.列出性能测试点:例如连续性操作、响应速度等

    6.兼容性测试点:例如不同长度(大小)、不同规格、不同的方式等

    7.发散性测试点:对已有用例分解,执行完一部分操作步骤之后,重复某一个步骤、跳过步骤、重复某一步骤、等待一段时间之后在操作、立即操作等

    8.其他测试点:对空列表、0、之前旧数据等特殊情况的处理

    疑惑:

    1.怎样区分模块的重要性?

    2.怎样设计测试用例,既能最大程度的覆盖所有测试点,又不会产生冗余的测试用例?


    展开全文
  • 浅谈HDFS的设计思想和实现思路

    千次阅读 2020-04-12 20:07:31
    ​ 本文不涉及HDFS的具体细节,只是谈谈HDFS的设计思想与实现思路,帮助更好的理解HDFS的总体架构。以下内容为原创,有描述不足或者错误的地方麻烦评论区说明一下,万分感激!

    前言

    本文隶属于专栏《1000个问题搞定大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

    本专栏目录结构和参考文献请见1000个问题搞定大数据技术体系

    本文不涉及HDFS的具体细节,只是谈谈HDFS的设计思想与实现思路,帮助更好的理解HDFS的总体架构。

    设计思想

    诞生背景

    ​ 伴随着互联网的迅速发展,需要计算处理的数据量急速膨胀。在稍微大一点的互联网企业,需要计算处理的数据量常常以 PB 计。一台计算机所能调度的网络带宽(通常数百 MB)、内存容量(通常几十 GB )、磁盘大小(通常数 TB)、CPU 运算速度是不可能满足这种计算要求的。

    ​ 此时就产生了这样一个需求背景:

    我们需要一个文件系统,可以支持海量数据的存储与计算,并且对外提供一个统一的读写API。
    

    面临的问题

    ​ 要想支持海量数据的存储与计算,我们需要解决几个核心问题:

    1.数据存储容量的问题。

    ​ 既然大数据要解决的是数以 PB 计的数据计算问题,而一般的服务器磁盘容量通常 1~2TB,那么如何存储这么大规模的数据呢?

    2.数据读写速度的问题。

    ​ 一般磁盘的连续读写速度为几十 MB,以这样的速度,几十 PB 的数据恐怕要读写到天荒地老。

    3.数据可靠性的问题。

    ​ 磁盘大约是计算机设备中最易损坏的硬件了,通常情况一块磁盘使用寿命大概是一年,如果磁盘损坏了,数据怎么办?

    思维的火种

    垂直伸缩 VS 水平伸缩

    ​ 在计算机领域,实现更强的计算能力和更大规模的数据存储有两种思路,

    • “垂直伸缩”(scaling up),通过升级 CPU、内存、磁盘等将一台计算机变得更强大;

    • “水平伸缩”(scaling out),添加更多的计算机到系统中,从而实现更强大的计算能力。

      显然垂直伸缩意味着更高的成本,而且垂直伸缩是有极限的,水平伸缩则没有(或者说极限远比垂直伸缩更高)。所以,我们要想解决我们的问题,只能从水平伸缩下手。

    水平伸缩能不能满足我们的需求

    ​ 目前来看,我们只能走水平伸缩的路子,那么水平伸缩就一定可以满足需求吗?

    用户请求方面

    ​ 网站实时处理通常针对单个用户的请求操作,虽然大型网站面临大量的高并发请求,但是每个用户之间的请求是独立的,只要网站的分布式系统能将不同用户的不同业务请求分配到不同的服务器上,我们在每台服务器上启动一个进程去处理这些请求,同时只要这些分布式的服务器之间耦合关系足够小,就可以通过添加更多的服务器去处理更多的用户请求及由此产生的用户数据,保障了系统的可伸缩性。

    移动计算比移动数据更划算

    ​ 面对着PB级别的数据,程序本身可能只有KB或者MB级别。既然数据量比程序本身要庞大的多,那么将数据发送给程序是不划算的。我们可以换一种思路,将程序通过网络传输发送给数据所在的地方,这一点实际上是和水平伸缩的思路符合的。

    RAID

    如果说我看得比别人更远些,那是因为我站在巨人的肩膀上。 ——牛顿

    ​ 上面这段话基本上每个人都听过,技术发展亦是如此。每一项流行性新技术的诞生不仅意味着一个亟待解决的技术难题,同时也是对前人技术的不断总结与创新。

    RAID(独立磁盘冗余阵列)技术是将多块普通磁盘组成一个阵列,共同对外提供服务。主要是为了改善磁盘的存储容量、读写速度,增强磁盘的可用性和容错能力。
    

    ​ 这里不探讨RAID的具体实现细节,只描述下RAID碰到我们上面说的3个问题是怎样去解决的?

    毕竟实现细节可能各种各样,百花齐放,但是设计思维是共通的,是永恒的,这也是我写这篇文章的目的,从设计思维出发来帮助我们更好的理解HDFS的各种细节。

    1.数据存储容量的问题:RAID 使用了 N 块磁盘构成一个存储阵列,如果使用 RAID 5,数据就可以存储在 N-1 块磁盘上,这样将存储空间扩大了 N-1 倍。

    2.数据读写速度的问题。RAID 根据可以使用的磁盘数量,将待写入的数据分成多片,并发同时向多块磁盘进行写入,显然写入的速度可以得到明显提高;同理,读取速度也可以得到明显提高。

    3.数据可靠性的问题。使用 RAID 10、RAID 5 或者 RAID 6 方案的时候,由于数据有冗余存储,或者存储校验信息,所以当某块磁盘损坏的时候,可以通过其他磁盘上的数据和校验数据将丢失磁盘上的数据还原。

    ​ 上面这段话比较长,其实总结起来就3个关键字:

    N块磁盘构成存储阵列

    并发写入

    冗余备份

    完善

    ​ 经过上面的探讨,我们其实已经有了一点较为完善的思路,可以帮助我们去解决刚开始提到的3个问题。

    1.数据存储容量的问题:多台服务器对外呈现一个统一的文件系统,综合CPU,磁盘,内存,网络带宽等,对外提供统一的读写API。

    2.数据读写速度的问题:我们把数据分成多块,并发的写入系统。

    3.数据可靠性的问题:我们对每个分块都进行冗余备份,一个数据块对应多个副本。

    以上内容我总结成了下面的思维导图。

    在这里插入图片描述

    实现思路

    ​ 学习任何一门新技术,我推荐从问题出发,一步步的来解决问题。

    ​ 还是回到刚开始的三个问题:

    一、数据存储容量的问题(分布式)

    1.分布式集群中怎么知道哪些服务器存储了哪些数据?

    ​ 这个不难想出,分布式集群中最常见的主从架构

    ​ 客户端先和主服务器通信,获取具体的存储位置,客户端再和从服务器请求相应的数据。

    ​ 更进一步,主服务器负责和客户端进行交互,从服务器来负责存储具体的数据。

    2.主服务器怎么知道从服务器存储了哪些数据?

    ​ 从服务器启动后,从本地配置文件中获取主服务器的地址,和主服务器通信,汇报本机存储信息。
    ​ 主服务器存储着元数据信息,包括文件系统树、整棵树所有的文件和目录、每个文件的块列表、块所在的节点信息等。

    ​ 为了照顾到使用性和容错性,数据分别保存在内存和磁盘中。

    3.从服务器挂掉怎么办?某块磁盘损坏怎么办?主服务器怎么知道?

    ​ 这里也使用一个比较经典的思维——心跳机制,从服务器定时和主服务器通信,一旦超时连接,则认为从服务器挂掉了。
    ​ 这里不得不提到冗余备份。主服务器一旦确定从服务器挂掉,从本地内存中获取该从服务器拥有的存储信息,然后新建一个备份。如果从服务器确定磁盘损坏,则会将该磁盘存储信息报告给主服务器,主服务器查到了相同的信息存储在哪些其他的服务器,只需要新建一个备份就行。相应的请求也会转移到备份的从服务器上面。

    ​ 这实际上体现了一种常见的保障系统可用性的思维——失效转移

    4.主服务器挂掉怎么办?

    ​ 主从热备,共享元数据信息,当主的挂掉后,备份服务器立马转正,从而保证系统的可用性。

    5.如何从故障中快速恢复过来?

    ​ 1.首先我们应该能想到,可以直接将整个文件系统打成镜像,系统重启后直接加载镜像就好了;

    ​ 2.但是这样会有一个问题,打一个镜像得很长时间,这段时间系统不就不可用了?

    这里也有一个经典的解决方案:

    我们可以将每次写入的操作都记录到日志文件里面,这样另起一个线程专门用来将日志合并到镜像里面不就好了。

    ​ 3.这样还有一个问题,如果主服务器突然挂了,日志文件的数据写入没有合并到镜像文件里面,这样系统重启后,系统还是很长时间不可用怎么办?

    ​ 遇到这个问题,有个常见的解决方案,就是设置检查点 ,每隔一定时间将日志文件里面的写入操作合并到镜像文件里面,为了加强系统的容错性,检查点要放到另外一台服务器上面,这台服务器专门用来负责处理将日志文件合并到镜像文件。定时的将新生成的镜像文件发送给主服务器,并且覆盖主服务器的老镜像。

    ​ 当然,还有一种解决方案也比较常见,就和我们每次装系统一样,每隔一段时间,生成一份快照,注意这里的快照不同于上面的镜像。

    6.单台主服务器面对海量的数据,内存不够怎么办?

    ​ 一台的内存不够,那我加一台;两台还不够,我再加!这其实就是上面讲到的水平伸缩的思想。

    7.元数据磁盘故障了怎么办?

    ​ 又是老问题了,相信你能脱口而出:冗余备份!没错,我一台服务器上面一个数据准备几个副本不就行了,当然还有一种更好的方案:在多台主服务器使用共享存储或者使用分布式编辑日志。

    二、数据读写速度的问题(数据分块)

    1.数据怎么分块?

    ​ 数据按照固定大小进行切分,要是大小不足怎么办?大小不足也算一个块,这样管理起来不就方便啦

    2.数据块大小比较合适呢?

    ​ 数据块不能太小——首先数据块对应的元数据信息都差不多,数据块太小主服务器内存就不够用了,其次,数据块太小,对于机械硬盘来讲,每个数据块都是连续的地址,切换数据块,寻址耗时太长。

    ​ 数据块不能太大——太大了怎么达到并发写入的要求呢?别忘了数据分块的目的就是为了并发写入的啊

    3.如果碰到海量小数据怎么办?

    ​ 这个思路也比较常见,合并和压缩呗。

    三、数据可靠性的问题(冗余备份)

    1.数据要放到哪些节点呢?

    ​ 节点不能太近——一挂可能全部挂

    ​ 节点也不能太远——距离越远传输时间越长,这是根据香农定理得出来的。

    2.读取数据的时候具体要选择哪个副本呢?

    ​ 这个考虑到香农定理,显然越近越好,因为根据前面的结论,数据是客户端在从服务器上面下载的,所以指的是客户端和从服务器之间的距离。

    3.怎么保证数据的完整性呢?

    ​ 这里也有一个经典的思维,既然数据量越大,网络传输越不可靠,我们就想办法把数据往小了切分 。

    ​ 我们使用校验和来保障数据的完整性, 由于校验和的大小远小于数据的大小,所以校验和的可靠性要比数据高得多。

    ​ 读数据——客户端读完了数据的校验和 与 主服务器内存里面的校验和比较,就知道数据读取是否成功了。

    ​ 写数据——对于数据块来讲,数据往小了切,一段一段的写入,每一段都包括数据和校验值,对于每一段数据,我们每个备份节点一台一台的写,每一台写完了直接校验。

    具体到HDFS

    ​ 实际上HDFS就是按照上面的思路来设计的,当然上面的思路只能粗略的帮你理解HDFS的设计思想,更具体的内容以后我再写篇文章来描述。

    ​ 上面每一个问题都对应了HDFS中的一个或几个知识点,具体的请看下面的思维导图。
    实现思路

    展开全文
  • 哈夫曼编码的思想思路

    千次阅读 2018-05-17 13:56:05
    写的比较乱(哈哈),但是理解起来应该还好//哈夫曼构建 #define n 50 //叶子节点个数 //哈夫曼重点在于它是用数组存储结构的,也是用数组序列化(构建)的 //它需要一个指明节点权值数组和节点自身字符数组的就...
  • 为推进高校宣传思想工作的发展,文章就总结经验与认识世界等八个方面的关系进行了探讨,并将深化这八个关系作为高校宣传思想工作发展的新思路
  • 题目如下 薯队长写了n篇笔记,编号...题目思路: 动态规划思想。 dp[i]表示前i篇笔记点赞总数最多。cnt[i]表示笔记的笔记总数。 #include<vector> #include<iostream> #include<string> #include<
  • Win32 核心 DPC 设计思想和实现思路浅析 http://www.blogcn.com/user8/flier_lu/index.html?id=1397656&run=.09D4C2F  x86架构设计在上是基于中断思想的,因而从DOS到Win32,操作
  • 有你想要的编程思想,开拓你的编程思路,这里的资源是PDF格式的,里面关于C++的讲解很详细
  • Hibernate比较适合对数据进行增,删,改的操作,而iBatis适合进行数据 查询,...这里有个新的实现思路:利用JAVA动态编译功能将拼SQL的JAVA代码配置到XML中,实现SQL和JAVA代码的分离;   另外IBATIS的分页是使用
  • java面向对象思想编写原谅帽小游戏 原谅帽游戏思路解析: 面向对象思想 类(游戏端)继承Frame; 首先要创建一个方法去让游戏开始和结束 使用text执行这个游戏的方法(需要有游戏标题和游戏的界面) 创建一个背景...
  • 我们平时已经用习惯了面向对象的编程思想,基本上理解为万物皆对象的概念,那么如果用Autolayout布局的话,Masonry就肯定会用过,每个优秀的框架都有一套自己的编程思想,这就是经典的链式编程思想,既然都会用了,...
  • 1.将原问题分解为子问题 将原问题分解为若干个子问题,子问题和原问题形式相同或类似,只不过规模变小了。子问题都解决,原问题即解决。 子问题的解一旦求出就会被保存,所以每个子问题只需求解一次。...
  • 本文讲解涉及到的核心思想: 机器学习与深度学习: 1:线性回归问题。 2:优化搜索时,步长选取的重要性。 3:为什么神经网络可以拟合任意的曲线函数。 4:图像识别网络中,为什么浅层网络只能识别出一些...
  •  两三年前就想把这个读取配置文件的,进行一次彻底得改造,一直没精力或者能力还不到位,说实话整体编写代码的能力不够的原因应该是占主要成分,由于这两三年,一直想把这个做好,所以想了很久了,思路成熟时...
  • 在本篇文章中,我将在评论区写下我在初学C语言中碰到的一些算法(解题思路),主要出自谭浩强C语言第四版,并给出这些算法解决常见问题的程序代码(文章链接),如筛选法求素数,选择法给整数排序等。也会总结一些对...
  • 1 分层; 2 封装; 3 发现问题本质,方法解决转化 4 字符串的拼接 5 一张表一个dao类一个servlet 6 根据隐含参数判断数据来源 7 数据放在哪,从哪取 8 命名统一 规范问题 ...二 针对上述介绍中,部分一般性规律: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,754
精华内容 9,101
关键字:

思想思路