笔记代码

分割线

基本概念

动/静态 Web

  • 静态 web

    • 比如 hexo 就是静态博客生成器,其生成的 HTML 页面文档树不会发生改变

    • 会因为 js 发生内容性的变化,但也是预设性的,并非动态变化.

    • 只能实现动画,不能实现动态;无后端,也就是无法与数据库交互,数据不能持久化,无法与用户进行信息交互


  • 动态 web

    • 比如 WordPress,客户端加载的内容会随着客户端交互而产生变化

    • 技术栈: Java Servlet/JSP,ASP.NET,PHP,Python,etc.

    • 资源出现问题时可以停机维护,可以与用户交互,操作数据库持久化信息.


  • JavaWeb 应用包含多个部分

    • html,sss,is

    • jsp,servlet

    • Java 程序

    • jar 包

    • 配置文件(Properties)

    20210322100531

后端技术对比

  • ASP

    国内最早流行,业务代码错乱,维护成本高

  • php

    开发速度很快,功能强大,跨平台,代码简单;但是无法承载大访问量的情况

  • JSP/Servlet

    B/S 架构

    语法像 ASP,ASP+Java->JSP

    可以承载三高问题带来的影响


Web 服务器

  • ASP.NET

    Windows 系统自带

  • Tomcat

    Apache 基金会的项目,在中小型并发量场景下普遍使用

    之前有个文章介绍了 😁IDE 选用指北.#Tomcat

    另外,推荐一篇文章: Tomcat 外传

    • Tomcat 项目层级结构

      - webapps :Tomcat服务器的web目录
      - ROOT 网站的根目录
      - kuangstudy :网站的目录名
      - WEB-INF
      - classes : java程序
      - lib : web应用所依赖的jar包
      - web.xml : 网站配置文件
      - index.html : 默认的首页
      - static
      - css
      - style.css
      - js
      - img
      - .....
    • Tomcat 可以 run 的项目只能是webapp,可以通过 Maven 创建这种项目

      • tomcat 可以直接跑起来 root/src/main/webapp这个目录, 或者用 maven package 打包后产生的.war 包

      • 其他形式的都无法用 tomcat 运行.

分割线

HTTP

(超文本传输协议)是一个简单的请求-响应协议,通常运行在 TCP 之上.

请求行

Request URL:https://www.baidu.com/   请求地址
Request Method:GET get方法/post方法
Status Code:200 OK 状态码:200
Remote Address:14.215.177.39:443
  • 请求方式:Get,Post,HEAD,DELETE,PUT,TRACT.…

    • get:请求能够携带的参数比较少,大小有限制,会在浏览器的 URL 地址栏显示数据内容,不安全,但高效

    • post: 请求能够携带的参数没有限制,大小没有限制,不会在浏览器的 URL 地址栏显示数据内容,安全,但不高效;只有表单才能使用.


消息头

Accept:text/html  // 告诉浏览器,它所支持的数据类型
Accept-Encoding:gzip, deflate, br // 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:zh-CN,zh;q=0.9 // 告诉浏览器,它的语言环境
Cache-Control:max-age=0 // 缓存控制
Connection:keep-alive // 请求完成是断开还是保持连接

响应体

...
跟请求相同
...
Refresh:告诉客户端,多久刷新一次
Location:让网页重新定位

响应状态码

20210323084728

分割线

Maven+Tomcat

🐱‍🏍Maven+Tomcat 开发 webapp.

分割线

Servlet

  • Servlet 是 sun 公司开发动态 web 的一门技术,开发 Servlet 程序有两个步骤:

    1. 编写一个类,实现 Serlet 接口

    2. 把开发好 java 类部署到 web 服务器中。

  • 利用 maven 创建一个工程项目(project),在内部创建多个子模块(module)进行学习测试.

分割线

HelloServlet

  • 现在,在 JavaWeb 项目中已经创建好子模块demo-1,我们在这个 demo-1 内练习 HelloServlet,项目结构如下:

    20210324163957
  • 新建 JavaWeb/demo-1/src/main/java/com/weidows/HelloServlet.java

    package com.weidows;

    import java.io.IOException;
    import java.io.PrintWriter;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    public class HelloServlet extends HttpServlet {
    /**
    *
    */
    private static final long serialVersionUID = -6617893791621340358L;

    //get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //ServletOutputStream outputStream = resp.getOutputStream();
    PrintWriter writer = resp.getWriter(); //响应流
    writer.print("Hello,Servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
    }
    }
  • 修改 JavaWeb/demo-1/src/main/webapp/WEB-INF/web.xml

    <!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" >

    <web-app>
    <display-name>Archetype Created Web Application</display-name>

    <!--注册Servlet,使这个类可以产生动态页面-->
    <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.weidows.HelloServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径映射,使路径映射对应类-->
    <servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/weidows</url-pattern>
    </servlet-mapping>

    </web-app>
  • 连接 Tomcat

    • 我们用 tomcat 跑起来这个子模块 (注意跑的是子模块不是整个项目)
    20210324164515
  • 跑起来后

    • 我们可以通过http://localhost:8080/demo_1_war/ 访问到 index.jsp 这个静态页面

    • 也可以通过http://localhost:8080/demo_1_war/weidows 访问到我们用 Servlet 映射的动态页面

      • 注意末尾不能带’/', http://localhost:8080/demo_1_war/weidows/ == http://localhost:8080/demo_1_war/weidows/index.html 因为并没有这个静态页面,会报 404
  • 注意,无论是动态页面还是静态页面,都必须指定编码,否则中文会乱码.


架构原理

20210325090037
  • Tomcat 做的就是接收请求并处理,然后返回响应

  • 我们需要做的是实现 Servlet 接口,处理请求和响应信息


Mapping

  • 一个 Servlet 可以映射一个或多个或正则匹配 url 路径

    • 映射固定地址的优先级最高
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello3</url-pattern>
    </servlet-mapping>
    hello/hello/*hello*.weidows

    ---

    - 例子: 把 404 页面换为我们自定义的

    - src/main/java/com/weidows/ErrorServlet.java

    ```Java
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;

    public class ErrorServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setContentType("text/html");
    resp.setCharacterEncoding("utf8");
    resp.getWriter().print("<h1>404</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
    }
    }

    - 注册并映射 404 页面

    - (注意上下顺序: ServletA MappingA ServletB MappingB 这样写会报错)

    ```xml
    <!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" >

    <web-app>
    <display-name>Archetype Created Web Application</display-name>

    <!--注册Servlet-->
    <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.weidows.HelloServlet</servlet-class>
    </servlet>
    <servlet>
    <servlet-name>ErrorServlet</servlet-name>
    <servlet-class>com.weidows.ErrorServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径-->
    <servlet-mapping>
      <servlet-name>helloServlet</servlet-name>
      <url-pattern>/weidows</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
      <servlet-name>ErrorServlet</servlet-name>
      <url-pattern>/*</url-pattern>
    </servlet-mapping>
    

    ---

    ### ServletContext

    - HttpServlet 对象中常用方法:

    - this.getInitParameter() // 初始化参数

    - this.getServletConfig() // Servlet 配置

    - this.getServletContext() // Servlet 上下文,最常用,这里只介绍这个

    - Web 容器启动时,会创建对应的 ServletContext 对象,代表当前 web 应用, `不同 Servlet 之间共享这个 ServletContext 对象`

    ---

    - 例子: 当访问 `/helloServlet` 时在 servletContext 对象中设置 username 属性,然后访问 `/getServlet` 可以查看设置的 username 属性值.

    - `src/main/java/com/weidows/HelloServlet.java`

    ```Java
    import java.io.IOException;

    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = this.getServletContext();
    String username = “齐下无贰”; //数据
    context.setAttribute(“username”, username); //将一个数据保存在了 ServletContext 中,名字为:username 。值 username
    System.out.println(“username 属性已设置.”);
    }
    }


    ***

    • src/main/java/com/weidows/GetServlet.java

      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;

      public class GetServlet extends HttpServlet {
      @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      doGet(req, resp);
      }

      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      String username = (String) this.getServletContext().getAttribute("username");

      resp.setContentType("text/html");
      resp.setCharacterEncoding("utf8");
      resp.getWriter().print("名字: " + username);
      }
      }

  • web.xml

    <!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" >

    <web-app>
    <display-name>Archetype Created Web Application</display-name>
    <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.weidows.HelloServlet</servlet-class>
    </servlet>
    <servlet>
    <servlet-name>getServlet</servlet-name>
    <servlet-class>com.weidows.GetServlet</servlet-class>
    </servlet>

    <servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/helloServlet</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>getServlet</servlet-name>
    <url-pattern>/getServlet</url-pattern>
    </servlet-mapping>
    </web-app>

初始化参数(了解)

  • 初始化参数在 web.xml 中设置,用 getInitParameter()获取

  • web.xml

    <!DOCTYPE web-app PUBLIC
    "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd" >

    <web-app>
    <display-name>Archetype Created Web Application</display-name>
    <!--配置一些web应用初始化参数-->
    <context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
    </context-param>

    <servlet>
    <servlet-name>helloParameter</servlet-name>
    <servlet-class>com.weidows.HelloParameter</servlet-class>
    </servlet>

    <servlet-mapping>
    <servlet-name>helloParameter</servlet-name>
    <url-pattern>/helloParameter</url-pattern>
    </servlet-mapping>
    </web-app>

  • src/main/java/com/weidows/HelloParameter.java

    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;

    public class HelloParameter extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = this.getServletContext();
    String url = context.getInitParameter("url");
    resp.getWriter().print(url);
    }
    }