netty学习记录(1)

WebSocker是一个保持web客户端与服务器长链接的技术。
两者通信过程中如果服务器有消息发送给客户端,就无需等待web客户端发送一个请求了。

1)@Component的作用 spring
1、@controller 控制器(注入服务)
2、@service 服务(注入dao)
3、@repository dao(实现dao访问)

4、@Component  泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
    (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>)
    
    Bean和@Bean的理解
        @Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名
        用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。
5、@Configuration



@Autowired  
public class Car(Brand benz){  
    this.brand=benz;
}  
Car这个类被标注了,那么spring扫描到之后,发现需要Brand这个类的实例对象,那么spring会去ioc容器中找到类型匹配的对象注入。

延伸问题  1)同一个类型的类有多个不同的bean,注入哪个?
        2)spring有2种注册bean的方式

2) Spring 提供了两种将WebSocket部署在Spring容器中的方法:
方法一:
使用org.springframework.web.socket.server.standard.ServerEndpointExporter.ServerEndpointExporter类。
在Spring容器中添加一个该类的实例:
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
Spring容器会去扫描包,将WebSocket加入容器。此时对于WebSocket则使用Spring的注解:
@ServerEndpoint(value="/getLocation",configurator = SpringConfigurator.class)
@Component
public class TransmissionLocationWebSocket {
xxxx
}

SpringConfigurator.class 为Spring提供的一个类。通过这个类,该WebSocket中就可以注入Spring容器的bean。

方法二:
使用Spring封装的WebSocket接口TextWebSocketHandler。

public class WebSocketHandler extends TextWebSocketHandler {
/**
 * 连接成功时候
 */
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception       { 

}
 /**
  * 连接关闭时候
  */
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {

  }

}
将类添加到Spring容器中,并配置:
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), “/getLocation”).setAllowedOrigins("*");
}

@Bean
public WebSocketHandler myHandler() {
    return new WebSocketHandler();
}

3) @ServerEndpoint注解 @ServerEndpoint("/webSocket")
Encoders and Decoders(编码器和解码器)
WebSocket Api 提供了encoders 和 decoders用于 Websocket Messages 与传统java 类型之间的转换
编码器通常生成json、XML、二进制三种表现形式
解码器执行相反的方法,它读入Websocket消息,然后输出java对象

创建一个编程式的端点,需要继承Endpoint类,重写它的方法。

@ServerEndpoint 主要用于建立websocket场景,建立ws一般是用这种注解,或者继承endpoint类
中实现websocket连接,场景,websocket建立链接

@WebServlet注解用于标注在一个继承了HttpServlet类之上,属于类级别的注解
    一般用于需要有HttpServletRequest请求中带了参数,或者需要filter等场景

@ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址。

onOpen 和 onClose 方法分别被@OnOpen和@OnClose 所注解。这两个注解的作用不言自明:他们定义了当一个新用户连接和断开的时候所调用的方法。

onMessage 方法被@OnMessage所注解。这个注解定义了当服务器接收到客户端发送的消息时所调用的方法。
    注意:这个方法可能包含一个javax.websocket.Session可选参数(在我们的例子里就是session参数)。
    如果有这个参数,容器将会把当前发送消息客户端的连接Session注入进去。

4)session 中文经常翻译为会话 是指从一个浏览器窗口打开到关闭这个期间
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。
因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,
当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。

隐含了“面向连接”和/或“保持状态”这样两个含义

1.session和cookie的区别
    Cookie是把用户的数据写给用户的浏览器。
    Session技术把用户的数据写到用户独占的session中。
    Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。

    
     cookie的内容主要包括:名字,值,过期时间,路径和域。 

       1、session在何时被创建 
        在程序中第一次调用request.getSession()方法时就会创建一个新的Session
        某server端程序调用HttpServletRequest.getSession(true)这样的语句时才被创建
        注意如果JSP没有显示的使用 <%@page session="false"%> 关闭session,
        则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);
        这也是JSP中隐含的session对象的来历。 
        由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。 

       2、session何时被删除 
        a.程序调用HttpSession.invalidate();
        或b.距离上一次收到客户端发送的session id时间间隔超过了session的超时设置;
        或c.服务器进程被停止(非持久session) 

        session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间,

        HTTP协议,无状态协议
        即这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的。但是这种无状态的的好处是快速。
        cookie是把少量的信息存储在用户自己的电脑上,以供读取。 不安全。
        session信息存在于服务器端。

        开启session,并随机生成一个唯一的32位的session_id,区分是谁在访问。
        同时也会自动往cookie里写入一个名字为PHPSESSID的变量,它的值正是session_id,

        再次访问的时候,服务器会去读取这个PHPSESSID的cookie是否有值有没过期,如果能够读取到,则继续用这个session_id,
        如果没有,就会新生成一个session_id,同时生成PHPSESSID这个cookie。
        由于默认生成的这个PHPSESSID cookie是会话,也就是说关闭浏览器就会过期掉,所以,下次重新浏览时,会重新生成一个session_id。

        每一次生成的session_id都会生成一个这样的文件,用来保存这次会话的session信息。

        延伸问题 用redis存储session  reidis主从同步或者redis 集群
                session同步
                web集群

5) CopyOnWriteArrayList 和 CopyOnWriteArraySet
CopyOnWriteArrayList是ArrayList 的一个线程安全的变体,其中所有可变操作(add、set等等)都是通过对底层数组进行一次新的复制来实现的。

    CopyOnWriteArraySet和HashSet继承于共同的父类AbstractSet;
    它是线程安全的无序的集合,不可以放置重复的元素
    CopyOnWriteArraySet是利用CopyOnWriteArrayList来实现的,因为CopyOnWriteArrayList是线程安全的,所以CopyOnWriteArraySet操作也是线程安全的。

    CopyOnWriteArraySet主要方法
        public boolean add(E e);
        public boolean remove(Object o);
    CopyOnWriteArrayList主要方法:
        public void add(int index, E element)
        public E remove(int index)
        public E remove(int index)
        public E get(int index) 
            增删改都需要获得锁,并且锁只有一把,而读操作不需要获得锁,支持并发。
            Vector是增删改查方法都加了synchronized,保证同步,但是每个方法执行的时候都要去获得锁,性能就会大大下降,而CopyOnWriteArrayList 只是在增删改上加锁,但是读不加锁,
            在读方面的性能就好于Vector,CopyOnWriteArrayList支持读多写少的并发情况。
    Copy-On-Write简称COW
    一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改。

    CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy。
    复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。    

    读的时候不需要加锁,如果读的时候有多个线程正在向CopyOnWriteArrayList添加数据,
    读还是会读到旧的数据,因为写的时候不会锁住旧的CopyOnWriteArrayList。

    CopyOnWrite并发容器用于读多写少的并发场景。比如白名单,黑名单,商品类目的访问和更新场景,假如我们有一个搜索网站,用户在这个网站的搜索框中,输入关键字搜索内容,但是某些关键字不允许被搜索。这些不能被搜索的关键字会被放在一个黑名单当中,黑名单每天晚上更新一次。当用户搜索时,会检查当前关键字在不在黑名单当中,如果在,则提示不能搜索。
    CopyOnWrite的缺点 CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。所以如果你希望写入的的数据,马上能读到,请不要使用CopyOnWrite容器。

类名.class
JVM将使用类装载器, 将类装入内存(前提是:类还没有装入内存),不做类的初始化工作.返回Class的对象

匿名内部类有什么用?实现多继承???

抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
所以抽象类必须被继承,才能被使用。





NioEventLoopGroup可以理解为一个线程池,内部维护了一组线程,每个线程负责处理多个Channel上的事件,而一个Channel只对应于一个线程,这样可以回避多线程下的数据同步问题。

1.ServerSocket 用来创建一个服务器。操作对象是某一台主机的某个端口端口

2.Socket 创建一个接受服务器信息的中间对象,这个对象就是客户机和服务器进行交互的中介。
getInputStream() 获取客户机发送过来的信息,
GetOutputStream() 发送给客户机的信息。

close()指令。在我们成功连接服务器并给客户机发送完消息后,这个端口服务器就被重新关闭了。

close()方法它只是关闭了端口的开放状态,但是这个端口还是会作为一个服务器存在
程序终止了,这个端口才会重新被初始化。

netstat -ano
netstat -aon|findstr “端口”
tasklist|findstr “PID号”

快捷键Shift+Ctrl+字母O 自动导入包

服务器类
客户端类
用户信息验证类
聊天室类

java开发过程中经常需要打印日志信息,往往会在每个类的第一行加上形如以下代码:

protected static final Logger logger = LoggerFactory.getLogger(XXX.class);

若是去掉static,那每个类对象就返回一个Logger类,增加了开销
目的:使用指定的类XXX初始化日志对象,方便在日志输出的时候,可以打印出日志信息所属的类。
如:Logger logger = LoggerFactory.getLogger(com.Book.class);
logger.debug(“日志信息”);
将会打印出: com.Book : 日志信息

服务器类:
HappyServer extends (abstract) BaseServer ,BaseServer implements Server

interface Server{
void start();
void shutdown();

抽象类不用全部实现接口中的所有方法

Reactor模型
Reactor模式基于事件驱动

类似生产者消费者模式,即有一个或多个生产者将事件放入一个Queue中,
而一个或多个消费者主动的从这个Queue中Poll事件来处理;

而Reactor模式则并没有Queue来做缓冲,每当一个Event输入到Service Handler之后,
该Service Handler会主动的根据不同的Event类型将其分发给对应的Request Handler来处理。

有多个输入源,有多个不同的EventHandler(RequestHandler)来处理不同的请求,
Initiation Dispatcher用于管理EventHander,
EventHandler首先要注册到Initiation Dispatcher中,
然后Initiation Dispatcher根据输入的Event分发给注册的EventHandler;
然而Initiation Dispatcher并不监听Event的到来,这个工作交给Synchronous Event Demultiplexer来处理。

AWT事件模型

C/S架构 Client/Server架构,即客户端/服务器架构
B/S Browser/Server,即浏览器、服务器

TCP/IP的编程抽象就是Socket! 中文翻译为"套接字" Socket的原意是插口
BIO:阻塞IO
NIO:非阻塞IO
同步IO
异步IO
以及其组合:
同步阻塞IO
同步非阻塞IO
异步阻塞IO
异步非阻塞IO
一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作
阻塞IO和非阻塞IO的区别在于第一步:发起IO请求是否会被阻塞,
如果阻塞直到完成那么就是传统的阻塞IO;如果不阻塞,那么就是非阻塞IO

同步IO和异步IO的区别就在于第二个步骤是否阻塞,
如果实际的IO读写阻塞请求进程,那么就是同步IO,
因此阻塞IO、非阻塞IO、IO复用、信号驱动IO都是同步IO;如果不阻塞,
而是操作系统帮你做完IO操作再将结果返回给你,那么就是异步IO

Netty是一个高性能NIO框架,其是对Reactor模型的一个实现!

Socket之间建立链接及通信的过程:

MultithreadEventLoopGroup是一个线程池
默认的线程数目是 CPU 核数 × 2
真正负责创建线程池的是 MultithreadEventExecutorGroup 构造方法,创建了 nThreads 个子线程池。

DefaultEventLoopGroup:用于只能用于本地传输的EventLoop实现。

NioEventLoopGroup可以理解为一个线程池,内部维护了一组线程,
每个线程负责处理多个Channel上的事件,而一个Channel只对应于一个线程,
这样可以回避多线程下的数据同步问题。

DefaultEventLoopGroup defLoopGroup = new DefaultEventLoopGroup(8,
new ThreadFactory() {
private AtomicInteger index = new AtomicInteger(0);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "DEFAULTEVENTLOOPGROUP_" + index.incrementAndGet());
        }
    });

EventLoopGroup主要负责2个事情
注册Channel和执行一些Runnable任务。

EventLoop又叫事件循环

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值