JavaWeb复习

JavaWeb

1.Servlet

Servlet是一个接口标准,其实现类作为一个小型Java应用运行在服务端。

Servlet通常需要由一个Servlet容器管理,通常使用Tomcat,此容器完成如下任务

  • 解析请求

    Tomcat容器会根据http请求,解析出其中的参数,并封装入HttpRequest对象中,同时会创建HttpResponse对象。

  • 创建Servlet实例

    Tomcat会根据url遍历所有配置的servlet,找出url对应的servletname,之后根据此name找出对应servlet的全限定类名,根据反射的方式创建servlet实例(调用init方法)

  • 交由servlet执行

    将创建好的HttpRequest和HttpResponse对象传给刚创建好的servlet,调用其service方法

    • 查看请求方法

      根据HttpRequest中保存的http方法,决定调用doGet/doPost/doDelete等方法

    • 执行对应方法并将返回信息注入HttpResponse

  • 返回响应信息

    Tomcat将HttpResponse对象转为http的响应报文格式,返回至客户端

  • 销毁servlet

    将执行完成的servlet销毁(调用destroy方法)

2. WEB架构

常用三层模型为WEB层、Service层、DAO(Data Access Object)层

  • WEB层

    常采用MVC的架构,Model、View、Controller,Spring MVC即WEB层的框架

  • Service层

    负责完成具体的业务逻辑

  • DAO层

    持久化层,为Service层查询数据库提供支持

3. Spring MVC

3.1 Spring IoC容器、Spring MVC IoC容器和Tomcat

Spring MVC是WEB层框架,其可以利用Spring的IoC特性,从而更好的管理实例对象

那么Spring的IoC容器、Spring MVC的IoC容器和Tomcat三者之间的关系是如何的呢?

  • Tomcat容器中添加Spring IoC容器

    在SpringBoot之前,Tomcat想要获取到Spring的相关IoC容器需要对Tomcat的web.xml做如下配置

    <!-- servlet定义:前端处理器,接受的HTTP请求和转发请求的类 -->
    <servlet>
        <servlet-name>court</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!-- court-servlet.xml:定义WebAppliactionContext上下文中的bean -->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>court</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    <!-- 配置contextConfigLocation初始化参数:指定Spring IoC容器需要读取的定义了非web层的Bean(DAO/Service)的XML文件路径 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/court-service.xml</param-value>
    </context-param>
    
    <!-- 配置ContextLoaderListerner:Spring MVC在Web容器中的启动类,负责Spring IoC容器在Web上下文中的初始化 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    -----------------------------------------------------------------------------------------------
    作者:猿码架构
    链接:https://juejin.cn/post/6844903537416077320
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

    首先配置DispatcherServlet,并配置一个listener,此listener会在Tomcat创建时介入,执行其中的下面的方法

    public void contextInitialized(ServletContextEvent event) {
       initWebApplicationContext(event.getServletContext());
    }
    

    此方法会更改Tomcat(Servlet上下文)的配置,其中会创建Spring的IoC容器,并调用refresh方法将DAO和Service的Bean注入进来,之后会将Spring IoC容器以ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为key设置到Tomcat(servletContext)中,且Spring IoC容器也会存在一个字段用于保留servletContext的引用

  • Tomcat容器中添加Spring MVC容器

    在listener执行结束之后,Tomcat便完成了加载,由于DispatcherServlet配置在Tomcat启动时创建,因而接下来创建DispatcherServlet,会调用到HttpServletBean#init方法

    public final void init() throws ServletException {
        /*
        */
       // Let subclasses do whatever initialization they like.
       initServletBean();
    }
    

    其中调用FrameworkServlet#initServletBean,

    protected final void initServletBean() throws ServletException {
       try {
          this.webApplicationContext = initWebApplicationContext();
          initFrameworkServlet();
       }
       catch (ServletException | RuntimeException ex) {
       }
    }
    

    其中调用FrameworkServlet#initWebApplicationContext,此方法中会先获取之前创建好的Spring IoC容器,之后将其作为要创建的Spring MVC容器的父对象(继承关系),这样Spring MVC容器就可以获取到父容器(Spring IoC容器)中存储的Bean(DAO/Service),之后调用refresh方法,将Controller的Bean注入到MVC容器中,并将servletContext存入MVC容器中的字段,并将MVC通过setAttribute方法放入到servletContext中

可见,Spring IoC、Spring MVC IoC、servletContext三者的关系如下

  • Spring IoC

    作为MVC IoC的父类,负责统一管理非WEB层的Beans,并保有servletContext的引用

    主要完成Service、DAO层功能,为Controller提供功能支持

  • MVC IoC

    作为Spring IoC的子类,可以获取到其中存储的Beans,且可以独立管理自己的Beans,并保有servletContext的引用

    主要负责完成WEB层的功能,包含着具体的WEB业务逻辑,根据请求的url调用对应的Controller(其中调用Service),并返回ModelAndView

  • servletContext

    作为最外层的WEB容器,其负责创建DispatcherServlet,并保有Spring 、Spring MVC的IoC引用

    主要负责管理Servlet生命周期,解析request,转换response,调用对应的servlet

深入分析Spring 与 Spring MVC容器 (juejin.cn)

Servlet的监听器Listener_重心开始,重新开始-CSDN博客

3.2 Spring MVC调用逻辑

Spring MVC

以DispatcherServlet为中心,负责整个流程的消息分发

4. HTTP

4.1 HTTP和HTTPS的区别

HTTPS即HTTP over SSL/TLS TLS是SSL的进化

HTTP存在如下缺点

  • 通信时使用明文传输,被截获即可解读
  • 不验证通信双方的身份,任何人都可以发起连接,会遭受中间人攻击
  • 无法验证报文的完整性,可能遭到篡改

HTTPs通过在传输层和应用层之间加上SSL/TLS层,提供了安全的通信方式

HTTPS基于对称加密和非对称加密方式

  • 对称加密

    即client和server使用同一个密钥对数据进行加密/解密,从而避免明文传输

  • 非对称加密

    基于RSA算法,采用公钥+私钥的方式,这样server和client可以使用公钥加密、私钥解密的方式进行通信

从上可见,两种加密方式有如下缺点

  • 对称加密

    如果中间人获取到密钥,则通信丧失的安全性

  • 非对称加密

    没有对公钥的来源做认证,如果是攻击者也持有这对公钥+私钥、则通信丧失安全性

使用HTTPs协议通信时,server必须先持有一对公钥和私钥,之后

  • server将公钥传输给client
  • client生成唯一密钥,用公钥对密钥加密,并传输至server
  • server使用私钥对密文解密,得到唯一密钥
  • 之后server和client就使用唯一密钥进行通信

从上可见,HTTPs采用混合加密的方式,解决了对称加密带来的密钥泄露的问题,但是没有解决公钥来源的可靠性验证,因而提出将公钥+私钥的颁发交给可信第三方来完成,也即CA(Certification Authority 证书颁发机构)来提供,这样,server就必须先向CA提交证书申请,这时CA会返回给server证书,其中包括公钥(带签名或水印)+私钥,这样,client在向server请求连接时,client会获得带签名的公钥,通过验证签名的合法性,从而判断这个公钥的来源是否可信,之后再按照混合加密的方式通信即可

4.2 HTTP是无状态的

HTTP协议本身是无状态的,也即没有类似于SMTP协议的握手、认证环节(每一个环节的顺序是固定的,那么通信双方需要记录每一步的状态来决定要进入哪一个环节),那么在两端通信时,都不知道当前通信时连接的状态,也即之前的请求不会对之后的请求造成影响(每次请求没有关联或连续性),也即每个HTTP请求是独立的,但是为了能够在服务端记录客户端的状态,来解决HTTP协议无状态带来的问题,可以通过Session、Cookie来保留会话的信息

  • Cookie

    通过在请求、响应报文中添加首部字段的方式,可以在BS之间共享信息,从而弥补HTTP协议无状态的特性

    • 响应报文

      可以通过在响应报文的header中添加Set-Cookie字段来添加一些信息,如下所示

      HTTP/1.0 200 OK
      Content-type: text/html
      Set-Cookie: name=lins1
      Set-Cookie: time=1
      

      客户端收到响应报文后,就可以从中取出k-v对,在下一次发送时,即可带上此k-v发送出去

    • 请求报文

      如果客户端当前持有服务端发来的cookie,那么需要在请求报文的header中添加Cookie字段,如下所示

      GET /index.html HTTP/1.1
      Host: www.lins1.com
      Cookie: name=lins1;time=1
      

      这样服务端通过从请求报文中取出Cookie即可明确这个客户端是谁

    从上可见,Cookie中保留了相关信息,并存储在客户端

  • Session

    为了能够让一些敏感消息不传送至客户端进行保留,提出采用Session的方式,其实现如下

    • 客户端请求连接

    • 服务端创建Cookie

      此Cookie的k为JSESSIONID,v为一个唯一的id值用于唯一标记一个客户端,并在服务端保留一个Session对象以此id为唯一标记,之后发送至客户端

    • 客户端取出Cookie

      客户端从Cookie中可知JSESSIONID的值,在之后的通信中,需要带上此Cookie

    • 服务端识别客户端

      从客户端发来的Cookie中,可以取出设定好的JSESSIONID,从而取出对应的session对象,可以在此对象中设定一些值(setAttribute)

    从上可见,Session是将相关信息存储在服务端的,且是基于Cookie的

4.3 HTTP的连接

HTTP协议基于TCP连接,其有两种建立连接的方式

  • 长连接

    客户端和服务端建立连接之后,除非有一方主动申请断开连接,则此连接一直会保留

  • 短连接

    客户端每一次请求都需要建立一个新的TCP连接,且获得响应后就断开

在长连接方式下,可以采用pipeline的方式提高通信效率,也即每一次发出请求后,不必等待响应即可发出下一次请求,这样可以利用服务器处理请求的空当发出新的请求

4.4 URL

4.4.1 URL与URI

  • URL(Uniform Resource Locator)

    URL是指从互联网得到资源位置和访问这些资源的定位器,是一个资源的地址

    一般的格式如下

url-1

​ 使用http的url

url-2

​ 默认端口号为80。

  • URI(Uniform Resource Identifier)

    URI是用于唯一标识一个资源的标签,可以是一个地址也可以是一个名称。

URL是一种特殊的URI,也即URL是URI的子集,那么一个URL必定是一个URI

4.4.2 URL编码

url编码(利用utf-8编码方式)

""的unicode编码为\u4f60,其中\u是标记,4f60是十六进制,转换为二进制如下:

unicode二进制形式:100 1111 0110 0000‬

根据utf-8的编码规则,对于12-16个bit的二进制数用三个字节的格式编码,格式如下:

1110xxxx 10xxxxxx 10xxxxxx

从右向左遍历unicode的二进制数,并从右向左填入格式中,空位补零,如下:

utf-8编码的二进制形式:11100100 101111 01 1010 0000‬

url编码是将制定编码方式(此处为utf-8)的二进制形式直接转换为16进制,得到如下:

utf-8的十六进制形式:E4BDA0

之后每两位组成一个字符,并在头部添加%,得到结果如下:

%E4%BD%A0

如果不采用utf-8,而是utf-16编码,则采用utf-16的二进制转16进制并进行编码

总结

url编码是将给定的编码方式的二进制直接转换为16进制并添加%来进行编码,url编码是为了解决和url中已经给定的符号冲突的情况(如=号是url中的关键字符,如果想输入=就必须利用url编码)

utf-8是一种针对unicode字符集而进行格式化的一种编码方式

posted @ 2021-03-09 18:25  Linus1  阅读(124)  评论(0编辑  收藏  举报