精华内容
下载资源
问答
  • 1、 SpringMVC中设置消息头,例子如下: @RequestMapping(value="/hasOperatePrivilege") @ResponseBody public Map hasOperatePrivilege(HttpServletRequest request, HttpServletResponse response,String web

    1、  SpringMVC中设置消息头,例子如下:

    @RequestMapping(value="/hasOperatePrivilege")

    @ResponseBody

    public Map<String, Object> hasOperatePrivilege(HttpServletRequest request,

             HttpServletResponse response,String websiteId) {

       Map<String,Object> paramMap = new HashMap<String,Object>();

      

       //设置消息头信息

       setResponeInfo(response);

      

       try {

          //用以标识是否有操作的权限

          String hasOperatePrivilege = templateService.hasOperatePrivilege(getSessionUserId(request),websiteId);

         

          paramMap.put("flag", "success");

          paramMap.put("info",hasOperatePrivilege);

       } catch (Exception e) {

          paramMap.put("flag", "error");

          e.printStackTrace();

       }

       return paramMap;

    }

    其中setResponeInfo(response);的内容如下:

    /**

     * 设置response的时候返回的消息头信息 

     * @param response

     * @attention只需要传递竟来一个response就可以了

     * @author toto

     * @date 2016-5-16

     * @note  begin modify by 涂作权 2016-05-16 原始创建

     */

    protected void setResponeInfo(HttpServletResponse response) {

       //下面的表示以普通文本的方式解析

       response.setContentType("text/plain;charset=UTF-8");

       response.reset();

       response.setHeader("Expires", "-1");

    }

    2、其它相关说明:

    response.setHeader()下载中文文件名乱码问题收藏  1.HTTP消息头

    1)通用信息头

    即能用于请求消息中,也能用于响应信息中,但与被传输的实体内容没有关系的信息头,Data,Pragma

    主要:Cache-Control , Connection , Data , Pragma , Trailer , Transfer-Encoding ,Upgrade

    2)请求头

    用于在请求消息中向服务器传递附加信息,主要包括客户机可以接受的数据类型,压缩方法,语言,以及客户计算机上保留的信息和发出该请求的超链接源地址等.

    主要: Accept, Accept-Encoding , Accept-Language , Host ,

    3)响应头

    用于在响应消息中向客户端传递附加信息,包括服务程序的名称,要求客户端进行认证的方式,请求的资源已移动到新地址等.

    主要:Location , Server , WWW-Authenticate(认证头)

    4)实体头

    用做实体内容的元信息,描述了实体内容的属性,包括实体信息的类型,长度,压缩方法,最后一次修改的时间和数据的有效期等.

    主要:Content-Encoding , Content-Language , Content-Length , Content-Location ,Content-Type

    4)扩展头

    主要:Refresh,Content-Disposition

    2. 几个主要头的作用

    1Content-Type的作用

    该实体头的作用是让服务器告诉浏览器它发送的数据属于什么文件类型。

    例如:当Content-Type 的值设置为text/htmltext/plain,前者会让浏览器把接收到的实体内容以HTML格式解析,后者会让浏览器以普通文本解析.

    2Content-Disposition 的作用

    Content-Type的类型为要下载的类型时, 这个信息头会告诉浏览器这个文件的名字和类型。

    在讲解这个内容时,张老师同时讲出了解决中文文件名乱码的解决方法,平常想的是使用getBytes(), 实际上应使用email的附件名编码方法对文件名进行编码,IE不支持这种作法(其它浏览器支持) , 使用javax.mail.internet.*包的MimeUtility.encodeWord("中文.txt")的方法进行编码。

    Content-Disposition扩展头的例子:

    <%@ pagepageEncoding="GBK" contentType="text/html;charset=utf-8"import="java.util.*,java.text.*" %>

    <%=DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT, Locale.CHINA).format(new Date())

    %>

    <%

                  response.setHeader("Content-Type","video/x-msvideo");

                  response.setHeader("Content-Disposition","attachment;filename=aaa.doc");

    %>

    Content-Disposition中指定的类型是文件的扩展名,并且弹出的下载对话框中的文件类型图片是按照文件的扩展名显示的,点保存后,文件以filename的值命名,保存类型以Content中设置的为准。

    注意:在设置Content-Disposition头字段之前,一定要设置Content-Type头字段。

    3Authorization头的作用

    Authorization的作用是当客户端访问受口令保护时,服务器端会发送401状态码和WWW-Authenticate响应头,要求客户机使用Authorization来应答。

    例如:

    <%@ pagepageEncoding="GBK" contentType="text/html;charset=utf-8"import="java.util.*,java.text.*" %>

    <%=DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT, Locale.CHINA).format(new Date())

    %>

    <%

    response.setStatus(401);

    response.setHeader("WWW-Authenticate","Basic realm=/"Tomcat Manager Application/"");

    %>

    3.如何实现文件下载

    要实现文件下载,我们只需要设置两个特殊的相应头,它们是什么头?如果文件名带中文,该如何解决?

    两个特殊的相应头:

    ----Content-Type:      application/octet-stream

    ----Content-Disposition:attachment;filename=aaa.zip

    例如:

    response.setContentType("image/jpeg");response.setHeader("Content-Disposition","attachment;filename=Bluehills.jpg");

    如果文件中filename参数中有中文,则就会出现乱码。

    解决办法:

    1MimeUtility.encodeWord("中文.txt");//现在版本的IE还不行

    2newString("中文".getBytes("GB2312"),"ISO8859-1");//实际上这个是错误的

    4. 测试并分析文件名乱码问题

    response.setHeader()下载中文文件名乱码问题

    response.setHeader("Content-Disposition","attachment; filename=" + java.net.URLEncoder.encode(fileName,"UTF-8"));

    下载的程序里有了上面一句,一般在IE6的下载提示框上将正确显示文件的名字,无论是简体中文,还是日文。不过当时确实没有仔细测试文件名为很长的中文文件名的情况。现如今经过仔细测试,发现文字只要超过17个字,就不能下载了。分析如下:

    . 通过原来的方式,也就是先用URLEncoder编码,当中文文字超过17个时,IE6 无法下载文件。这是IEbug,参见微软的知识库文章 KB816868。原因可能是IE在处理 ResponseHeader 的时候,对header的长度限制在150字节左右。而一个汉字编码成UTF-89个字节,那么17个字便是153个字节,所以会报错。而且不跟后缀也不对.

    . 解决方案:将文件名编码成ISO8859-1是有效的解决方案,代码如下:

    response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("gb2312"), "ISO8859-1" ) );

    在确保附件文件名都是简体中文字的情况下,那么这个办法确实是最有效的,不用让客户逐个的升级IE。如果台湾同胞用,把gb2312改成big5就行。但现在的系统通常都加入了国际化的支持,普遍使用UTF-8。如果文件名中又有简体中文字,又有繁体中文,还有日文。那么乱码便产生了。另外,在上Firefox(v1.0-en)下载也是乱码。

    . 参看邮件中的中文附件名的形式,用outlook新建一个带有中文附件的邮件,然后看这个邮件的源代码,找到:

    Content-Disposition:attachment;

    filename="=?gb2312?B?0MK9qCDOxLG+zsS1tS50eHQ=?="

    用这个filename原理上就可以显示中文名附件,但是现在IE并不支持,Firefox是支持的。尝试使用 javamailMimeUtility.encode()方法来编码文件名,也就是编码成=?gb2312?B?xxxxxxxx?= 这样的形式,并从RFC1522 中找到对应的标准支持。

    折中考虑,结合了一、二的方式,代码片断如下:

    StringfileName = URLEncoder.encode(atta.getFileName(), "UTF-8");

    /*

    *see http://support.microsoft.com/default.aspx?kbid=816868

    */

    if (fileName.length() > 150) {

    StringguessCharset = xxxx

    //根据requestlocale 得出可能的编码,中文操作系统通常是gb2312

    fileName= new String(atta.getFileName().getBytes(guessCharset), "ISO8859-1");

    }

    response.setHeader("Content-Disposition","attachment; filename=" + fileName);

    编码转换的原理:

    首先在源程序中将编码设置成GB2312字符编码,然后将源程序按Unicode编码转换成字节码加载到内存中(java加载到内存中的字节码都是Unicode编码),然后按GB2312编码获得中文字符串的字节数组,然后生成按ISO8859-1编码形式的Unicode字符串(这时的4个字节就变成了8个字节,高位字节补零),

    当在网络中传输时,因为setHeader方法中的字符只能按ISO8859-1传输,所以这时候就又把Unicode字符转换成了ISO8859-1的编码传到浏览器(就是把刚才高位补的零全去掉),这时浏览器接收到的ISO8859-1码的字符因为符合GB2312编码,所以就可以显示中文了。

    5. jsp翻译成class时的编码问题

    记事本中代码块1

    <%=

          "a中文".length()

    %>

    代码块2

    <%@ pagepageEncoding="gbk"%>

    <%=

          "a中文".length()

    %>

    为什么上面的输出值为5,改成下面的则输出3

    因为上面的代码没有添加该文件的编码说明 , WEB应用程序在将jsp翻译成class文件时 , 把该字符串的内容按默认的保存方式指定的编码ASCII码来算的,在UTF-8中,原ASCII字符占一个字节,汉字占两个字节,对应两个字符,长度就变成了5, 而下面的是GBK编码, 一个汉字和一个英文都对应一个字符,得到结果就为3.

    response.setHeader(...)文件名中有空格的时候

    String fileName = StringUtils.trim(file.getName());

    String formatFileName =encodingFileName(name);//在后面定义方法encodingFileName(StringfileName);

    response.setHeader("Content-Disposition","attachment; filename=" + formatFileName );

    //处理文件名中出现的空格  

    //其中%20是空格在UTF-8下的编码

    public static StringencodingFileName(String fileName) {        

         StringreturnFileName = "";        

         try {           

            returnFileName= URLEncoder.encode(fileName, "UTF-8");           

            returnFileName= StringUtils.replace(returnFileName, "+", "%20");           

            if(returnFileName.length() > 150) {               

                  returnFileName= new String(fileName.getBytes("GB2312"), "ISO8859-1");               

                  returnFileName= StringUtils.replace(returnFileName, " ", "%20");           

             }       

        } catch (UnsupportedEncodingException e) {           

            e.printStackTrace();           

            if (log.isWarnEnabled()) {               

                   log.info("Don't support this encoding ...");           

            }        

        }        

        return returnFileName;    

    }

    展开全文
  • 一 场景 发送者Alice要对消息签名,接收方Bob要签名进行验证。...用私钥加密得到的密文就是Alice这条消息的签名,由于只有Alice才持有自己的私钥,因此除Alice外,其他人是无法生成相同的签名(密文...

    一 场景

    发送者Alice要对消息签名,接收方Bob要对签名进行验证。

    二 签名和验证过程

    Alice需要先生成一个包括公钥和私钥的密钥对,而需要验证签名的Bob需要得到Alice的公钥。签名过程如下:

    1 Alice用自己的私钥对消息进行加密

    用私钥加密得到的密文就是Alice对这条消息的签名,由于只有Alice才持有自己的私钥,因此除Alice外,其他人是无法生成相同的签名(密文)的。

    2 Alice将消息和签名发送给Bob

    3 Bob用Alice的公钥对收到的签名进行解密

    如果收到的签名确实是Alice的私钥加密得到的密文(签名),那么用Alice的公钥应该能够正确解密。其他情况无法解密。

    4 Bob将签名解密后得到的消息与Alice直接发送的消息进行对比

    如果两者一致,则签名验证成功;如果两者不一致,则签名验证失败。

    展开全文
  • 笔者在前面几篇文章中,一口气分别介绍了【对称加密算法、非对称加密算法、信息摘要算法】,从中读者能大致了解到各种算法的应用场景是怎么样的。这一次,我们将进一步介绍【非对称加密算法】和【消息摘要算法】的...

             笔者在前面几篇文章中,一口气分别介绍了【对称加密算法、非对称加密算法、信息摘要算法】,从中读者能大致了解到各种算法的应用场景是怎么样的。这一次,我们将进一步介绍【非对称加密算法】和【消息摘要算法】的综合应用:数字签名和消息验签。通过本文的阅读,你可以了解到以下知识:

    • 数字签名是什么?
    • 为什么数字签名采用非对称算法和信息摘要算法?
    • 数字签名的操作步骤是什么?
    • 消息验签的操作步骤是什么?
    • 数字签名算法的分类
    • 数字签名的核心应用场景:https网络通讯

    预备知识


            在阅读本文之前,笔者假设读者已熟知非对称加密算法和信息摘要算法的基本知识,如对此块知识有缺漏,可自行前往 【算法大杂烩】常见算法的归类和总结——非对称加密算法 以及 【算法大杂烩】常见算法的归类和总结——消息摘要算法 学习相关算法的基础知识。

            这里再次补充下,【非对称加密算法】的核心内容:密钥有公钥和私钥之分;公钥对外公开,私钥私有保密;公钥加密对应私钥解密,私钥加密对应公钥解密;加密解密的输入数据长度一般有限制,像RSA算法,输入数据长度应等于模长。【信息摘要算法】的核心内容:不同的数据输入,产生不同的摘要输出,但是摘要的长度是一定的;摘要相同意味着输入数据的原文相同。


    数字签名是什么?


           签名,一个在日常生活中,很经常听到并使用的名字。在平时,我们经常会签署各式各样的文件,在我国的法律中,亲笔签名在一定程度上是具有法律效力的,表示当事人对签署的文件知悉并且认可,一旦“签名”生成后,它具备了法律意义。又比如,我们在POS机消费后打印的消费单据上签署自己的姓名,则表示持卡人认同这笔消费交易,银行或收单机构拿到这张经消费者签名的单据,就可以完全最终消费款项的清算。在我国,POS机消费时,大部分时候,我们都要输入银行卡密码,打印消费单据后还需要签署自己的姓名;而在国外,由于他们的征信系统较为发达,往往在POS机消费时,是不需要输入银行卡密码的,而消费的唯一凭证确认,就是消费单据上签署的签名。在此种情况下POS机的操作员,有义务确认消费者签署的姓名与卡片背部的参照签名笔迹是否一致;同时,操作员也有权利,当发现消费者签署的姓名笔迹与卡片后背签名笔迹差异较大时,拒绝此卡片消费。通过以上的一些生活例子,我们可以了解到【签名】是一个很重要的玩意,一定程度就代表了本人的认可和无异议。

           那么,在数字信息领域,究竟什么是【数字签名】呢?数字签名(又称公钥数字签名、电子签章)是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。(摘自: 百度百科 数字签名

           从密码学的角度来说,【数字签名】主要解决了两个核心问题:发送的消息是完整的,未被篡改的;接收的消息一定就是对应发送者发送的,别人无法仿制。前者体现的是数据的完整性,后者体现的是数据的不可抵赖性


    为什么数字签名采用非对称算法和信息摘要算法?


           从上一小结,我们可以知道【数字签名】的两个核心特点:不可抵赖性和完整性。通过对之前学习的非对称加密算法和信息摘要算法的基础知识一对比,我们可以发现:

           非对称加密算法正好解决了不可抵赖性的问题,因为在非对称算法体系中,经私钥加密的数据只有私钥对应的公钥才能解开,别人的公钥是无法解密出原文的,这就是不可抵赖的体现,即任何人都无法冒充发送者。

           信息摘要算法恰好解决了数据完整性的问题,因为在信息摘要算法中,不同的数据输入,产生的摘要是不一样的;当摘要数据一样时,我们就可以认为数据原文是一致的,也就认可了数据是完整的,没有被篡改的。

           两者一结合,恰好就诞生了【数字签名】这个最佳实践,达到了数据传输中不可修改性的安全要求。


    数字签名的操作过程


           前面的讲解,我们知道了【数字签名】的特性。在实际的应用过程中,数字签名的应用公式如下所示,其中M表示消息原文,S表示数字签名,P表示非对称算法的私钥运算,D表示信息摘要算法的运算。

    • P(D(M [with any length])) = S [with fixed length]

           具体来说,发送方产生一个数据签名,需要经过以下几个步骤:

    • 使用【信息摘要算法】,对任意长度的信息原文做摘要运算,得到一段固定长度的摘要数据;
    • 如果该摘要数据的长度,没有达到非对称加密算法做加解密运算的输入长度,通常还需要使用填充标准对摘要数据进行必要的填充,以达到非对称算法的运算条件;常用的填充标准有PKCS1-padding;
    • 使用【非对称加密算法】的私钥对填充后的摘要数据做加密运算,得到一段固定长度的数字签名;
    • 发送方将数字签名拼接在信息原文的尾部,一同发送给接收方,完成数据的单方向传输。

           经过以上的步骤后,发送方就成功将信息原文和对应的数字签名,传递给了接收方;剩余的事,就是接收方对数据的验签操作。


    消息验签的操作过程


            接收方收到发送方发送的数据报文(信息原文+数字签名)后,需要经历以下步骤来完成对报文消息的验签操作:

    • 首先,对数据报文进行分解,提取出信息原文部分和数字签名部分;
    • 与产生数字签名流程一样,使用相同的信息摘要算法对信息原文做摘要运算,得出消息原文的摘要D1;
    • 与产生数字签名流程相反,使用【非对称加密算法】中签名私钥对应的公钥对数字签名部分做解密运算,解密后得到原始发送方发送的经填充后的摘要D2;
    • 与产生数字签名流程相反,使用相同的数据填充标准对摘要D2做去填充操作,得到原始消息的附带的摘要D3;
    • 比较D3和D1;如果两者相等,则表示对数字签名的验签是OK的,消息原文的数据是可信任的;反之,若D3不等于D1,则可以认为消息原文是不可信任的,数字签名中的【完整性】和【不可抵赖性】可能遭到了破坏;我们应该摒弃信息原文。

    数字签名算法的分类


           数字签名算法,就是使用RSA、MD5、SM2、SHA、SM3等非对称算法和信息摘要算法进行混搭组合。数字签名算法的基本表示格式为:xxxWithYYYEncryption,其中xxx表示信息摘要算法,yyy表示非对称加密算法。常见有的以下几种:

    • md5WithRSAEncryption:摘要运算采用MD5,非对称算法使用RSA;
    • sha1WithRSAEncryption:摘要运算采用SHA1,非对称算法使用RSA;
    • sha256WithRSAEncryption:摘要运算采用SHA256,非对称算法使用RSA;【常用】
    • sm3WithSM2Encryption:摘要运算采用SM3,非对称算法使用SM2。

    数字签名的核心应用场景:https网络通讯


           经以上的各小结,我们基本掌握了数字签名的主要内容,这一小节,我们介绍下数字签名的核心应用:https网络通讯。

           HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

           由它的定义可知,要想实现https,除了应用层需要有http的支持,还需要在传输层支持SSL。SSL正是为了解决网络通讯的安全性问题而诞生的,简单的说,通过SSL的加入,在浏览器和网页服务器之间的数据都是加密的,而不像之前http那样,数据完全在网络上裸奔。目前网络安全问题越来越突出,越来越多的网络信息泄露的案例爆发出来,正是由于这些安全性问题的暴露,SSL的应用得到了越来越多的支持。

            限于篇幅原因,本小结不对SSL的具体细节做阐述,仅仅是简要描述数字签名在SSL中的应用方法;后续笔者会写一篇专门的文章来进一步解释SSL通讯的前前后后,敬请关注。

           说到数字签名在SSL的应用,它主要是帮助发送方和接收方协商必要的数据,比如网络通讯的加密密钥。我们知道,网络数据是庞大的,而非对称算法的加密速度是远远比对称加密算法慢的,所以在网络通讯的报文不太适合直接使用非对称算法做加密,比较合适的做法的通讯报文还是采用对称加密算法加密,但是对称加密算法使用的对称密钥是发送方和接收方在正式通讯前进行在线协商的;密钥协商的过程使用数字签名的技术,保证协商的密钥是完整的(保证是没被篡改的),并且是不可抵赖的(保证是发送方的)。在密钥协商时,通讯双方分别利用自己的私钥和公钥,结合数字签名技术,完成协商动作。

           上面讲消息验签的时候,我们提到消息验签必须要使用签名方的公钥做解密运算,这个公钥一定程度上代表了签名方的身份;但是,我们如何知道我们拿到的公钥,就是我们认为的那个签名方的公钥,而不是网络攻击“中间人”的公钥呢?这就需要CA (Certificate Authority)帮助我们确认这个公钥的合法性。具体的做法是,我们拿到签名方的公钥时,它并不仅仅是一个公钥,而公钥+经CA签名的数字签名,这叫做公钥证书。我们对公钥证书,先用CA的公钥对公钥证书的数字签名进行验签,如果验签成功,则表示我们拿到的公钥是可信任的。那么,CA的公钥,我们又通过谁来保证它是可信任的呢?

           这似乎是一个无穷无尽的问题?究竟是怎么回事呢?笔者在这里先卖个关子,有兴趣的读者,可以关注笔者后续有关SSL通讯的详细介绍。


           本文通过对非对称算法和信息摘要算法的简要回顾,进而引出【数字签名】的两个核心问题,阐述了数字签名的操作流程以及消息验签的操作过程,读者阅读完本文,应该对数字签名的相关知识有了更多的了解。最后,笔者引出了数字签名在https通讯的核心应用,并抛出有关CA的疑问,希望有更多的读者参与本文的思考和总结。文中的观点,仅代表笔者之愚见,难免有纰漏之处,希望有心的读者诚心指正,互相学习,共同进步。感谢感谢。

    展开全文
  • Handler消息机制的理解

    千次阅读 2014-09-28 21:59:55
    Handler消息机制中无非都是围绕着:Handler,MessageQueue,Looper来做文章的,那么这三者的概念就首先你要清楚它是什么,为什么,怎么办.围绕这三个问题那么问题就不断的被一层一层的深入,最后也就解开了问题的谜题了,...

    Handler消息机制中无非都是围绕着:Handler,MessageQueue,Looper来做文章的,那么这三者的概念就首先你要清楚它是什么,为什么,怎么办.围绕这三个问题那么问题就不断的被一层一层的深入,最后也就解开了问题的谜题了,对于初学者来说Handler是一个神奇的东西,鸡肋吧,有人说我只要会用sendMessage()就好啦,其实不然


    handler:生成,发送,处理消息
    Message:数据载体
    MessageQueue:Message的队列,FIFO
    Looper:轮询器,用来轮询MessageQueue,调用Message中的数据

    Android消息机制的概述
         在刚刚自学android的时候,对android的消息机制相信和很多的刚入门同学一样就知道一个sendMessage()和handlerMessage();但是它的内部又是怎么去实现呢?自己在网上查了很多资料也看了很多csdn大牛的文章,但是有句话不是说嘛"书上得来终觉浅,觉知此时要躬行" ,最后决定还是要把我对android消息机制的艰(zuo)辛(si)历程记录下来.
       首先要学一样东西,对这个东西的定义是最为重要的,试问你都不知道其为何物,那你还谈什么去深入呢?
       要想知道你对消息机制的知识到底掌握的怎么样,只要你能回答下面的几个问题那么就算你掌握了:
            1.:一个handler是不是只能对应一个looper?
            2.:一个looper是不是只能对应一个handler?
            3.:MessageQueue和looper是一对一对应的,looper也可以在子线程中用?
        问题的答案嘛,只要你读完这篇博客你就懂了心里有答案了,到博文的最后一处作死的小编也会把答案贴出来,所以同学们不妨在阅读下文的时候,带这三个问题,我相信你会在看着看着的时候就跟我一样恍然大悟的.

          在Android4.0以后不能在UI线程访问网络,子线程也不能更新UI.举个实际的例子,就拿下载东西的进度来说,下载任务是一个耗时的操作,好那么把下载任务放在子线程,如果将耗时操作放在UI线程的话会造成"卡顿"现象,那么就把下载的耗时操作放在子线程,那么问题又来了下载任务的ui又要怎么去更新呢?在子线程可不能够更新ui,google的开发者是聪明的,他们就研制出一种"Handler消息机制"的药,那么问题就解决了.

    Handler消息消息机制主要包括4个关键对象: Message,MessageQueue,Looper,Handler        
           Message: 数据载体
                  Message是在线程间消息传递的载体,Message的what字段可以携带整型信息,obj字段可以携带一个对象             
          
            MessageQueue:Message队列,采用FIFO(先进先出,Ps:虽然是采用先进先出的原理,但是它的具体实现不是用队列而是单链表实现的)
                  
           Looper: 轮询器,用来轮询MessageQueue,调用Message中的数据
                     Looper是直接对每个MessageQueue负责的,当Looper调用loop()方法后,就会进入一个无限循环的过程,当发现有存在一条消息的时候Looper就会将MessageQueue的消息取出,并且将其传递到Handler的handlerMessage()方法中去.还有一点需要提醒的是每个线程中只会有一个looper对象,在ActivityThread中会默认的开启一个Looper,在子线程中需要Looper.loop()手动开启 , 不断从 MessageQueue 中抽取 Message 执行。因此,一个线程中的 MessageQueue 需要一个 Looper 进行管理。 Looper 是当前线程创建的时候产生的( UI Thread 即主线程是系统帮忙创建的 Looper ,而如果在子线程中,需要手动在创建线程后立即创建 Looper[ 调用 Looper.prepare() 方法 ] )。也就是说,会在当前线程上绑定一个 Looper 对象。

           Handler :生成,发送,处理消息流程图

    图解:Handler消息处理需要在UI线程中创建一个Handler对象.在子线程中通过调用Handler的sendMessage()方法,将消息存放到 UI线程 的消息队列中,通过Looper对象将消息取出,最后再分发会Handler的handlerMessage()中;
    Ps:Handler不仅只有handlerMessage()它还有一个很常用的方法post()方法,在做图片的轮播的时候就要用到这个方法,这个本来是打算到后面讲Handler消息机制应用的时候给同学们讲的



    接下再把Handler消息自己的时序图贴上来,心中围绕着这两个图想问题



    首先Handler会生成Message.然后通过sendMessage()方法将Message发送到消息队列MessageQueue中去;还有一点需要说明的是,轮询器Looper是一直在轮询状态的,一直对消息队列MessageQueue进行轮询,如果一旦发现有Message,将Message返回;然后通过Message中Target拿到Handler实力,进行调用dispatchMessage() 将Looper拿到的message分发出去,最后Handler拿到消息,执行handlerMessage()方法


    接下来通过解读源码告诉大家,为什么在子线程中跟新UI会抛异常
    void checkThread(){
         if(mThread != Thread.currentThread()){
              throw new CalledFromWrongThreadException(
                "Only the original thread that created a view hierarchy can 
                   touch its views");
         }
    }
    相信同学们刚刚接触android的时候对这句异常" " Only the original thread that created a view hierarchy can touch its views " "一点也不陌生吧?怎么现在是不是变得越来越有意思了呢
      针对checkThread抛出的异常,会导致程序出现ANR异常,那么怎么解决这个问题呢?就引进Handler机制了,这也是系统之所以会提供Handler,主要就是为了解决子线程中无法访问UI,那大家有没想过为什么子线程不让访问ui呢?原因很简单,会导致系统出现很多无法预知的状态.那么为甚不对线程加锁呢?加锁不就完事了吗?加锁的话会又会出现:降低了UI的访问效率,也就是我们常说的卡顿,还有就是加锁后程序的逻辑又会变得复杂.那么为何不用Handler切换一些UI就完事了呢?

    2.Android消息机制的内部实现原理(Handler,MessageQueue,Looper的协调工作)
    当Handler创建完后,它内部的Looper和MessageQueue就可以和Handler协同工作,再通过Handler的post方法将一个Runnable放到Handler内部的Looper中处理,.当然啦你也可以通过send方法去发送一个消息.post方法最终也是通过调用send方法来实现的,Looper是运行在Handler所在的线程中的

    这里需要强调一点的就是,如果你是在主线程中处理message,那么在主线程中创建handler对象,系统的Looper已经准备好了,且MessageQueue也初始化了,并且轮询器的轮询方法loop默认是开启的;但是,如果你是在子线程中创建handler,那么就需要显示的调用Looper的prepaer()和loop()方法,来进行初始化Looper和开启轮询器
    下面给一个实例代码
    public class MainActivity2 extends Activity implements OnClickListener{
        private Button send;
    	private TextView recieve;
    	private Handler handler = new Handler(){
    		@Override
    		public void handleMessage(Message msg) {
    			super.handleMessage(msg);
    			recieve.setText((String) msg.obj);
    		}
    	};
    	@Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
           send = (Button) findViewById(R.id.bt_send);
            recieve = (TextView) findViewById(R.id.tv_recieve);
           send.setOnClickListener(this);
            recieve.setOnClickListener(this);
    	}
    	@Override
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case R.id.bt_send:
    			new Thread(){
    				public void run() {
    					Message msg = new Message();
    					msg.obj = "您有新的消息,请注意查收"+ System.currentTimeMillis();
    					handler.sendMessage(msg);
    				}
    			}.start();
    			break;
    		}
    	}
    }


    这里头有两道很典型的题目,解答出来,Handler机制基本就了解; 
    Android中Looper的实现原理,为什么调用Looper.prepare()就在当前线程关联了一个Loopepr对象,它是如何实现的?
      1.线程的通信机制
      首先,looper handler MessageQueue 三者共同实现了android系统中线程通信的机制.假如在A B 两个线程中要进行消息传递,首先给每个子线程绑定一套handler looper MessageQueue机制,然后这撒个对象都与其所属的对象对应.然后A线程通过调用B线程的Handler对象,发送消息.这个消息会被Handler发送到B中的MessageQueue,而B线程中的Looper对象一直在for循环里无限遍历.MessageQueue一旦发现消息队列里头接收到新的消息,就会的消息进行处理,处理的过程中会回调自身Handler的HandlerMessage方法,从而实现了不同线程间的通信.
      2.Looper实现通信的原理
      首先Looper类里头包含一个消息队列和一个线程对象.当创建Looper时,会自动的创建一个消息队列,通信将内部线程对象指向创建Looper的线程.当开启looper后(looper.loop()),会自动进入无限for循环中,不断的遍历消息队列,如果没有消息阻塞,有消息则会回调handler的handlerMessage()方法进行处理消息.
       3.Looper.prepare(),是一个绑定的过程,将Handler创建的looper对象的消息队列和空线程指向当前线程中
       首先,要使用Looper机制一般都会在当前线程中创建Handler对象,里面会自动创建一个looper对象和消息队列,这里的消息队列属于当前线程空间中,但此时的looper还不会去遍历,也没有绑定到当前的线程中.期中looper对象内部也包含一个空消息队列对象和空线程.通过looper.prepare()方法,先让消息队列指向当前线程的消息队列,让空线程也指向当前线程.从而实现绑定




    android是如何处理UI与耗时操作的通信?
    主要有三种方法,一为Handler,二为AsyncTask,三为自己开子线程执行耗时操作,然后调用Activity的runOnUiThread()方法更新ui;
    handler机制是,在主线程中创建handler对象,
    当执行耗时操作时,新建一个线程,在这个线程中执行耗时操作,通过调用handler的sendMessage,post等方法,更新ui界面;

    AsyncTask本质上是一个线程池,所有的异步任务都会在这个线程池中的工作线程中执行,当需要操作ui界面时,会和工作线程通过handler传递消息。

    自己开子线程执行耗时操作,然后调用Activity的runOnUiThread()方法更新ui,这种方法需要把context对象强制转换成activity后使用

    handler机制的优点是  结构清晰,功能明确,但是代码过多;
    asyncTask简单,快捷,但是可能会新开大量线程,消耗系统资源,造成FC
    第三种方法最好用,代码也非常简单,只是需要传递context对象
    展开全文
  • 消息队列手动确认Ack

    千次阅读 2020-01-17 14:42:20
    以RabbitMQ为例,默认情况下 RabbitMQ是自动ACK机制,就意味着 MQ 会在消息发送完毕后,自动帮我们去ACK,然后删除消息信息。 这样依赖就存在这样一个问题: 如果消费者处理消息需要较长时间,最好的做法是消费端...
  • 透传消息和非透传消息

    万次阅读 2016-03-10 12:03:46
    透传消息就是消息体格式及内容,对于传递的通道来说是不去过问的,通道只负责消息的传递,对消息不做任何处理,当客户端接收到透传消息后,由客户端自己来决定如何处理消息。正是因为透传消息可以自定义消息体,也...
  • 环境需求:假如某人有5个女朋友(有点复杂),每天晚上都会给他的女朋友打电话说晚安,那么每给一个女朋友打电话,其他女朋友都要进入等待状态。...此原理就是消息队列。 一、什么是中间件  非底层操作系...
  • 深入解析Android中Handler消息机制

    千次阅读 2017-02-13 01:08:26
    Android提供了Handler 和 ...Handler消息机制可以说是Android系统中最重要部分之一,所以,本篇博客我们就来深入解析Android中Handler消息机制。Handler的简单使用为什么系统不允许子线程更新UI因为的UI控件不是线程安
  • 消息透传

    千次阅读 2018-04-20 20:33:54
     透传消息:对于传递的通道来说无需理会消息体格式及内容,通道只负责消息的传递,对消息不做任何处理,当客户端接收到透传消息后,由客户端自己来决定如何处理消息。正是因为透传消息可以自定义消息体,也可以...
  • 消息系统NATS常见的几个问题

    千次阅读 2016-04-03 16:35:04
    消息系统NATS常见的几个问题作者:chszs,未经博主允许不得转载。经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs1)Request()和Publish()之间的不同Publish()发送一条消息到gnatsd,是使用它的地址...
  • 程序中是可以通过使用指针的引用来传递消息。当调用时,对应的方法会查看传入的地址中的具体数值。 -setTune: (struct tune *)aSong { Tune= * aSong; … } 同样地,指针也可以被用来返回信息
  • Windows 消息机制

    千次阅读 2013-05-20 20:22:20
     每个窗口会有一个称为窗口过程的回调函数(WndProc),它带有四个参数,分别为:窗口句柄(Window Handle),消息ID(Message ID),和两个消息参数(wParam, lParam), 当窗口收到消息时系统就会调用此窗口过程来处理消息。...
  • 安卓推送技术手册——透传消息

    千次阅读 2015-06-03 11:05:27
    透传消息就是消息体格式及内容,对于传递的通道来说是不去过问的,通道只负责消息的传递,对消息不做任何处理,当客户端接收到透传消息后,由客户端自己来决定如何处理消息。正是因为透传消息可以自定义消息体,也...
  • (Microsoft.SqlServer.Express.Smo)点击“消息”:ADDITIONAL INFORMATION:执行 Transact-SQL 语句或批处理时发生了异常。 (Microsoft.SqlServer.Express.ConnectionInfo) 靠~~~这东东能让人看懂吗?
  • JMS消息服务 API解析

    千次阅读 2020-06-10 00:07:25
      JMS(Java Message Service)消息服务,具体详解请参看系列文章第一张,JMS的原理其实很简单,用过JDBC,可能理解JMS更加容易,JMS只提供API定义,具体由不同厂商或产品实现,如:AactiveMQ、Tomcat JMS、...
  • uml时序图中消息分调用消息和信号消息。若在调用消息中发送了信号消息。 比如两个对象,一个对象a,一个对象b,对象b调用对象a中的方法send_picture,send_picture中调用了sendto函数将...画法如图所示,如有不对,请指出
  • 分布式系统的现代消息传递

    千次阅读 2019-06-13 15:29:27
    论文《分布式系统的现代消息传递》Modern Messaging for Distributed Sytems L Magnoni 通过IOP出版有限公司出版许可物理学学报:会议系列,608卷,第1会议 作者电子邮件 luca.magnoni@cern.ch 作者隶属...
  • 控件通知消息

    千次阅读 2011-02-12 15:00:00
    控件通知消息 2008年04月06日 星期日 00:09控件通知消息有很多种,但是有一种是很常用,但是又不是很容易掌握的,那就是WM_NOTIFY,我试着对此做一下比较全面的论述,有不对的地方,还希望各路大虾批评...
  • 我们都知道,Android UI是线程不安全的,如果在子线程中尝试进行UI操作,...这种处理方式被称为异步消息处理线程,虽然我相信大家都会用,可是你知道它背后的原理是什么样的吗?今天我们就来一起深入探究一下Handler和
  • 昨天从朋友圈得知一位老同学离职的消息,深感惊讶。同学在一家贸易公司IT部门做数据分析,工作5年了,一直很稳定,突然离职实在令人费解,遂找她私聊了解了一下近况,想知道她为什么离职。结果发现她不是主动离职,...
  • 由此,我们可以绘制继承关系图(图中nil的地址不对,不重新绘制了) 综合上述两个例子,我们绘制出完整的isa和superClass图 提高方法查找机制效率-Class Cache 通过上文我们知道,在OC中,方法是...
  • 一、消息队列概述 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。 目前在生产环境,...
  • 京东JMQ如何保证消息顺序消费

    千次阅读 2017-01-13 19:39:24
    如果为每一个消息维护一个有序的ID,发送和存储消息无序,消费逻辑会变得非常复杂,消费端要对消息进行重新编排,会影响消费的性能。为了保证消息发送、保存、消费三个环节都有顺序,就要求在同一个时刻只能有一个...
  • kafka实战篇(二):消息消费实战

    千次阅读 多人点赞 2020-04-24 16:00:44
    前文: kafka实战篇(一):Producer消息发送实战 与本文实战内容相关的kafka架构核心知识点: 深入分析Kafka架构(三):消费者消费方式、三种分区分配策略、offset维护 通过上一篇文章,我们已经熟练掌握怎么把...
  • Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因素。 这些数据通常是由于...
  • EMQ百万级MQTT消息服务(小技巧)

    万次阅读 2018-04-08 15:11:04
    附上: ... 1.ACL鉴权规则化 在正常业务使用下对于客户端的行为可以使用ACL进行限制,比如A客户端只能订阅 /A/get 队列消息和向 /A/set 发布内容 但是在MYSQL里面处理这样的鉴权就需要写入两条...
  • java消息机制

    千次阅读 2015-11-28 00:51:59
    java消息机制 1、问: 什么是 Java 消息服务? 答: Java 消息服务(Java Message Service,JMS) API 是一个用于访问企业消息传递系统的 API。是 Java 2 Platform, Enterprise(J2EE)的一部分。 2...
  • 微信消息体加解密及EncodingAESKey

    万次阅读 2014-10-23 09:39:01
    公众平台消息体签名及加解密方案概述 1.新增消息体签名验证,用于公众平台和公众账号验证消息体的正确性 2.针对推送给微信公众账号的普通消息和事件消息,以及推送给设备公众账号的设备消息进行加密 3....
  • 消息推送分类:通知和透传

    千次阅读 2017-12-28 14:44:05
    透传消息就是消息体格式及内容,对于传递的通道来说是不去过问的,通道只负责消息的传递,对消息不做任何处理,当客户端接收到透传消息后,由客户端自己来决定如何处理消息。正是因为透传消息可以自定义消息体,也...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 77,119
精华内容 30,847
关键字:

信息就是消息对不对