netty高性能web服务器介绍

1. 什么是netty

Netty是一个异步的事件驱动网络应用框架。

它的主要用途是构建高性能协议服务器,并通过基于隔离和松耦合的网络和业务逻辑组件的NIO(非阻塞输入输出)技术实现这一点。它可以实现广为人知的Http协议或者我们自定义的协议。

2. netty的核心概念

netty是一个非阻塞式框架,和阻塞式IO相比,它拥有更高的吞吐量。理解非阻塞式IO是掌握Netty的核心组件以及他们之间的关系的关键所在。

2.1 Channel(通道)

Channel是NIO的基石,它代表了一个拥有IO(读和写)处理能力的开放连接。

2.2 Future

对于Netty来说,Channel中的每一个连接都是非阻塞的。

这意味着每个操作在调用之后都会立刻返回。标准Java库中有一个Future的接口,但是它并不能方便的完成Netty的意图,因为我们只能通过这个接口去查询操作是否已完成或者阻塞当前线程直到操作完成。

基于上面的原因,Netty实现了自己的ChannelFuture接口。我们可以通过回调函数告诉ChannelFuture,一旦操作完成,将要执行的操作。

2.3 事件和处理器

Netty使用了基于事件驱动的应用模式,因此数据处理的管道(pipeline)本质上是贯穿处理器(handler)的一连串事件的链(chain)。事件和处理器类似于数据的流入以及流出。流入事件可以是下面的几种:

  • 通道的激活和失活
  • 读事件
  • 异常事件
  • 用户事件

流出事件则比较简单,一般类似于打开或者关闭连接以及写入数据。

Netty应用包含了几个网络和应用的逻辑事件以及他们对应的处理器。channel事件处理器可以使用的基础接口分别是ChannelHandler和它的祖先ChannelOutboundHandler和ChannelInboundHandler。

Netty提供了大量的ChannelHandler接口的实现类。值得注意的是,适配器只是空的实现,例如ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter。我们可以继承这些适配器当我们只需要处理所有事件集合中的子集。

同样,Netty包含了某些指定协议的具体实现,比如Http。HttpRequestDecoder,HttpResponseEncoder,HttpObjectAggregator。你可以通过Netty的javaDoc去了解他们的用法。

2.4 编码器和解码器

当我们使用网络协议时,我们需要对数据进行序列化和反序列化。出于这个目的,Netty引进了一个特殊的解码拓展类ChannelInboundHandler,它可以对进来的数据进行解码。大多数解码器的基类是ByteToMessageDecoder。

为了编码出去的数据,Netty也提供了一个特殊的编码实现类ChannelOutboundHandler。MessageToByteEncoder是大多数编码实现类的基类。通过编码器和解码器,我们可以将信息从字节序列转换成java对象,反之亦然。

jsp-tag-usage-1

curl命令常见用法

发送post请求

  • 参数类型为application/json
  1. 常规用法:

    1
    curl -d '{"key1":"value1", "key2": "value2"}' -H "Content-Type: application/json" -X POST http://localhost:8080/your_interface_name
  2. 使用json文件:

    1
    curl -d "@data.json" -X POST http://localhost:8080/your_interface_name

    data.json


    1
    2
    3
    4
    {
    "key1": "value1",
    "key2": "value2"
    }
  • 参数类型为application/x-www-form-urlencoded
  1. 常规用法:

    1
    curl -d "param1=value1&param2=value2" -X POST http://localhost:8080/your_interface_name
  2. 使用data文件:

    1
    curl -d "@data.txt" -X POST http://localhost/your_interface_name

    data.txt


    param1=value1&param2=value2

  • 发送GET请求
  1. 常规用法:

    1
    curl -X GET http://localhost:8080/user/info?id=1

    如果需要显示响应头信息,则可以加上-i参数。

java知识点速记

java bean和pojo的区别

一、 定义

  • POJOPlain Old Java Object的缩写,它主要用来强调某个对象是一个普通的Java对象,而不是一个特殊的对象,尤其不是一个EJB。

    这个术语以其简单易懂的特性被广泛接受并使用,并用来区别那些复杂的对象框架。

  • 一个JavaBean是一个可以被序列化的POJO。有一个默认的无参构造器,并允许使用Getter和Setter方法访问属性。

    对于EJB来说,JavaBean并不是一个单独的类,而是整个组件模型。

    JavaBean是java构建程序中可重用的软件组件,实际开发过程中,它们是使用java语言编写并符合某个约定的类。它们被用来封装一些对象到单个对象(也就是bean)中。

二、 用法

  • POJO主要被用来表明一个java对象不需要跟随任何java对象模型、约定或者框架。最理想的情况,一个POJO应该是一个不和任何框架绑定的java对象,并遵循以下原则:
    1. 不应该继承某个指定的类,比如HttpServlet;
    2. 不应该实现指定的接口,比如EntityBean;
    3. 不应该包含某些框架的注解。
  • JavaBean应该遵循以下原则:
    1. 必须有一个公共的默认构造器,便于实例化;
    2. 属性必须可以通过Getter和Setter或者其他的可以访问并修改的方法进行控制,并遵循标准的命名规范,以便于框架对其进行自动化管理和状态的更新;
    3. 必须可以被序列化,以便于应用和框架以一种独立于VM和操作系统的方式对其进行可靠的保存、存储以及恢复bean的状态。

对于业务程序员来说,这两种类型的java对象其实可以等同,或者说POJO更多强调的是一种业务概念,而JavaBean则属于java编程语言的特性。

mybatis原理学习笔记

mybatis的执行原理:

通常一个Mapper接口对应一个xml文件,Mapper接口中的方法名对应xml中的标签id,而xml中的每一个标签都会被解析为MapperStatement对象。通过xml中定义的namespace属性,可以和接口方法的执行路径相对应。而这个路径应该具有唯一性,所以Mapper接口中的方法不能被重载。Mapper接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象,代理对象会拦截接口方法,转而执行MapperStatement所代表的sql语句,然后将执行结果返回。

mybatis的分页原理:

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内容分页,而非物理分页。

mybatis-pagehelper插件的实现原理:

使用mybatis提供的插件接口,实现自定义插件,在插件内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

redis命令学习

redis存储string类型的值

  1. 存值:

    1
    set key value
  2. 取值:

    1
    get key
  3. 返回key中的部分字符串:

    1
    getrange key start end

    start从0开始,且返回的内容中包含索引为end的字符。

  4. 取出旧值并返回新值:

    1
    getset key new_value
  5. 取出key对应的值,并返回指定偏移量上的位(bit):

    1
    getbit key offset
  6. 一次性取出多个值

    1
    mget key1 key2 ...
  7. 当key不存在时才设值:

    1
    setnx key value
  8. 删除指定key

    1
    del key
  9. 返回给定key的超时时间

    1
    ttl key
  10. 查看key的类型

    1
    type key

redis系统管理命令

  1. 给redis服务器设置密码
1
2
3
4
5
6
7
8
9
10
11
$ redis-cli
127.0.0.1:6379> config set requirepass my_password
# 获取密码
127.0.0.1:6379> config get requirepass
(error) NOAUTH Authentication required.
# 使用设置过的密码登陆
127.0.0.1:6379> auth my_password
OK
127.0.0.1:6379> config get requirepass
1)"requirepass"
2)"my_password"

需要注意的是,上面的设置方式在redis服务器重启之后便会失效,如果需要重启后仍然有效,则可以修改配置文件

打开/etc/redis/redis.conf,修改如下地方:

1
# requirepass foobared

改成如下内容

1
requirepass my_password

保存之后重启redis服务器即可生效。

redis模糊查询

  1. 查询所有的key

    1
    keys *
  2. 单字符匹配

    1
    keys h?llo # 可以匹配hello、hallo和hxllo等
  3. 多字符匹配

    1
    keys h*llo # 可以匹配hello、heeeello等
  4. 范围内匹配

    1
    keys h[ae]llo # 可以匹配hallo、hello

如何使用openssh进行远程连接

SSH连接的建立方式

ssh可以通过密码和密钥(更加安全)这两种方式建立起客户端与 服务端的连接。

SSH连接的实现过程(假设通过密钥的方式连接)

  1. 当客户端发起一个ssh连接请求时,它首先会告诉服务端需要使用的公钥;
  2. 然后服务端会检查它的~/authorized_keys文件,这个文件中包含了所有已经保存的客户端公钥,一个公钥占据一行,这些公钥所对应的客户端可以实现免验证登录。
  3. 服务端如果在文件中找到了请求客户端所对应的公钥,就会生成一个随机字符串,并使用找到的公钥进行加密。这个加密后的信息只能被请求客户端的私钥所解密,然后服务端将这个加密后的字符串发送给请求客户端,以此来验证该客户端是否拥有私钥。
  4. 客户端收到来自服务端的加密字符串之后,会立即使用自己的私钥进行解密,并将解密后的随机字符串与之前协商好的会话id结合,生成一个md5加密的hash值,并回传给服务端。
  5. 由于服务端已经知道加密之前的随机字符串和会话id,因此,服务端会在本地将这个随机字符串和会话id进行hash,然后和客户端传过来的值进行比较,如果一致,则表示请求客户端确实拥有私钥,并允许建立连接。
阅读更多