看透Spring MVC

2015/12/17 posted in  Java

缓存的失效可以定期失效,也可以在数据发生变化的时候失效,如果按数据发生变化让缓存失效,还可以分粗粒度失效和细粒度失效。

像快递送货一样,货单上填写地址的规则以及怎么根据填写的内容找到客户,这就相当于IP协议,而送货时要先打电话,然后将货物送过去,最后客户签收时要签字就相当于TCP协议。

三次握手和四次挥手保证了连接的可靠性,不过这种模式也有它的缺点,首先是在传输效率上会比较低,另外三次握手的过程中客户端需要发送两次数据才可以建立连接,这种特征可能被一些别有用心的人利用,比如,发出第一次握手后就不回应第三次握手了,这时服务端会以为是第二次握手的数据在传输过程中丢失了,然后重新发送第二次握手,默认情况下会一直发送五次,如果发送五次后还收不到第三次握手则会丢弃请求。这就是DDOS攻击中的SYN Flood攻击,对于这种攻击的一种应对方法是设置第二次请求的重发次数,不过重发的次数大小也可能导致正常的请求中因为网络没有收到第二次握手而连接失败的情况。

通过TCP/IP协议、HTTP协议已经可以得到数据了,Servlet的作用是对接收到的数据进行处理并生成要返回给客户端的结果。

域名解析有很多种解析的类型,如常用的A记录和CNAME记录。A记录是将域名解析到IP(一个域名可以有多条A记录),CNAME记录是将域名解析到另一个域名(也就是作为另一个域名的别名),查找时会返回目标域名所对应的IP

ServerSocket的使用可以分为三步:
- 创建ServerSocket
- 调用创建出来的ServerSocketaccept方法进行监听。accept方法是阻塞方法,也就是说调用accept方法后程序会停下来等待连接请求,在接收到请求之前程序都不会往下走;当接收到请求后accept方法会返回一个Socket
- 使用accept方法返回的Socket与客户端进行通信

普通Socket处理请求的模式:收到请求,处理,处理好了,收下一个请求。

NIOSocket处理请求的模式:快递并不会一件一件地送,而是将很多件货一起拿去送,而且在中转站都有专门的分拣员负责按配送范围将货物分给不同的送货员,这样效率就提高了很多。

NIOSocket使用中首先要创建ServerSocketChannel,然后注册Selector,接下来就可以用Selector接受请求并处理了。

NIOSocket中服务端的处理过程可以分为5步:
1、创建ServerSocketChannel并设置相应参数
2、创建Selector并注册到ServerSocketChannel
3、调用Selectorselect方法等待请求
4、Selector接收到请求后使用selectedKeys返回SelectionKey集合
5、使用SelectionKey获取到ChannelSelector和操作类型并进行具体操作

// 恢复到初始状态
public final Buffer clear()
{
    position = 0;
    limit = capacity;
    mark = -1;
    return this;
}

// 开启读的模式
public final Buffer flip()
{
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

Servlet接口
- init方法在容器启动时被容器调用(当load-on-startup设置为负数或者不设置时会在Servlet第一次用到时才被调用),只会调用一次
- getServletConfig方法用于获取ServletConfig
- service方法用于具体处理一个请求
- getServletInfo方法可以获取一些Servlet相关的信息,默认返回空字符串
- destroy主要用于在Servlet销毁(一般指关闭服务器)时释放一些资源,只会调用一次

getServletName用于获取Servlet的名字,也就是我们在web.xml中定义的servlet-namegetInitParameter方法用于获取init-param配置的参数;getInitParameterNames用于获取配置的所有init-param的名字集合;getServletContext的返回值代表的是我们这个应用本身。ServletConfigServlet级的,而ServletContextContext(也就是Application)级的。

String contextLocation = getServletConfig().getServletContext().getInitParameter("contextConfigLocation");
String servletLocation = getServletConfig().getInitParameter("contextConfigLocation");

GenericServlet

GenericServletServlet的默认实现,主要是做了三件事:
- 实现了ServletConfig接口,我们可以直接调用ServletConfig里面的方法
- 提供了无参的init方法
- 提供了log方法

GenericServlet实现了Servletinit(ServletConfig config)方法,在里面将config设置给了内部变量config,然后调用了无参的init()方法

public void init(ServletConfig config) throws ServletException {
    this.config = config;
    this.init();
}
public void init() throws ServletException {

}

HttpServlet

HttpServlet是用HTTP协议实现的Servlet的基类。HttpServlet主要重写了service方法。在service方法中首先将ServletRequestServletResponse转换为了HttpServletRequestHttpServletResponse,然后根据Http请求的类型不同将请求路由到了不同的处理方法

Tomcat的顶层结构

Tomcat中最顶层的容器叫Server,代表整个服务器,Server中包含至少一个Service,用于具体提供服务。Service主要包含两部分:ConnectorContainerConnector用于处理连接相关的事情,并提供Socketrequestresponse的转换,Container用于封装和管理Servlet,以及具体处理request请求。

一个Tomcat中只有一个Server,一个Server可以包含多个Service,一个Service只有一个Container,但可以有多个Connectors(因为一个服务可以有多个连接)

Server的启动过程

await方法处理的大概逻辑是首先判断端口号port,然后根据port的值分为三种处理方法:
- port为-2,则会直接退出,不进入循环
- port为-1,则会进入一个while(!stopAwait)的循环,只有在外部调用stop方法才会退出循环
- port为其他值,则也会进入一个while(!stopAwait)的循环,不过同时会在port所在的端口启动一个ServerSocket来监听关闭命令,如果姐收到了则会使用break跳出循环