JAVAWeb——Web的基本概念

1. 基本概念

Web开发:

  • Web:网页的意思
  • 分类:
    • 静态Web:如html css,提供给所有人看的数据始终不变
    • 动态Web:提供给所有人看的数据都不一样,如Servlet/ISP,ASP,PHP。
  • JAVA中,动态web资源开发的技术统称为javaweb

1.2 Web应用程序

Web应用程序:可以提供浏览器访问的程序

  • a.html, b.html 等多个web资源,这些web资源可以被外界访问,为外界资源提供服务
  • 一个web应用程序由多个部分组成
    • html css js
    • jsp servlet
    • java应用程序
    • jar包
    • 配置文件(properities)

1.3 静态Web

  • *.htm *.html都是网页的后缀,如果服务器上存在这些,就可以进行读取。
  • 缺点
    • 无法动态更新,所有用户看到的都是一个页面
    • 无法与数据库交互

1.4 动态Web

页面会动态展示:”Web的页面展示效果因人而异”

缺点:

  • 假如服务器动态web资源出现错误,需要重新编写后台程序
    • 停机维护

优点:

  • 可以动态更新
  • 可以与数据库交互(数据持久化:注册,商品信息,用户信息)

2. Web服务器

2.1 技术讲解

ASP:

  • 微软:国内最早留下的就是ASP

  • 在HTML中,嵌入了VB的脚本 ASP + COM

  • 在ASP开发中,基本一个页面

  • C#

    1
    2
    3
    4
    5
    6
    7
    <h1>
    <h1>
    <%
    System.out.println()
    %>
    </h1>
    </h1>

JSP/Servlet:

  • sun公司主推的B/S架构
  • 基于JAVA语言(所有大公司)
  • 承载三高问题带来的影响
  • 语法像ASP

php:

  • 开发速度快,功能强大,跨平台,代码简单

  • 无法承载大访问量的情况

2.2 Web服务器

服务器是一种被动的操作,用来处理用户的一些请求和给用户的一些响应。

IIS:微软 ASP… Windows自带的

Tomcat:免费的开发源代码的Web应用服务器,属于轻量级应用服务器

3. Tomcat

3.1 安装

1
2
3
4
5
6
7
8
9
bin: 启动 关闭 脚本

conf:配置

lib:依赖包

logs:日志

webapps:存放网站

启动Tomcat: startup.bat

http://localhost:8080/

关闭:shutdown.bat

3.2 配置

server.xml:

  • 启动的端口号:默认 8080
  • 主机的名称:localhost -> 127.0.0.1

网站是如何进行访问的?

  1. 输入一个域名:回车
  2. 检查本机的hosts配置下有无这个域名映射:
    • 有: 直接返回对应的ip地址,这个地址里,有我们响应访问的web程序
    • 无:去DNS服务器找,找到就返回

image-20241116212213835

3.3 配置环境变量

3.4 发布一个web网站

把自己写的网站 放到服务器Tomcat指定的web应用的文件夹wenapps下,就可以访问了

网站的结构:

1
2
3
4
5
6
7
8
--webapps:Tomcat服务器的web目录
-ROOT
-study:网站的目录名
- WEB-INF:
- classes: java程序
- lib: web程序依赖的jar包
- web.xml: 网站配置文件
- index.html 默认的首页

4. Http

超文本传输协议:请求-响应协议,运行在TCP之上

超文本:图片、音乐、视频、定位、地图

HTTP端口:80

HTTPs端口:443 (安全的)

4.1 两个时代

  • http1.0
    • HTTP/1.0:客户端与web服务器连接,只能获取一个web资源,断开连接
  • http2.0
    • HTTP/1.1:客户端与web服务器连接,只能获取多个web资源

4.2 http请求

  • 客户端–发请求–服务器
1
2
3
4
5
Request URL: https://www.sougou.com/
Request Method: GET (请求方法 get / post)
Status Code: 301 Moved Permanently 状态码
Remote Address: 60.205.56.208:443
Referrer Policy: strict-origin-when-cross-origin
  • 请求行:

    请求方式:GET / POST, HEAD,DELETE PUT TRACT

    • get:请求能够携带的参数少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,更高效
    • post:请求能够携带的参数多,大小无限制,不会在浏览器的URL地址栏显示数据内容,安全,不高效
  • 消息头:

    1
    2
    3
    4
    5
    6
    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
    Accept-Encoding: gzip, deflate, br, zstd
    Accept-Language: zh-CN,zh;q=0.9
    Connection: keep-alive // 告诉浏览器请求后是断开还是保持连接
    Host: www.baidu.com
    Sec-Ch-Ua: "Not(A:Brand";v="24", "Chromium";v="122"

4.3 http响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Connection: keep-alive  // 连接
Content-Encoding: gzip
Content-Security-Policy:
frame-ancestors 'self' https://chat.baidu.com http://mirror-chat.baidu.com https://fj-chat.baidu.com https://hba-chat.baidu.com https://hbe-chat.baidu.com https://njjs-chat.baidu.com https://nj-chat.baidu.com https://hna-chat.baidu.com https://hnb-chat.baidu.com http://debug.baidu-int.com;
Content-Type: text/html; charset=utf-8
Date: Tue, 19 Nov 2024 10:38:15 GMT
Isprivate: 1
Server: BWS/1.1
Set-Cookie:
H_PS_PSSID=61027_60851_61130_61128_61113_61141_61160; path=/; expires=Wed, 19-Nov-25 10:38:14 GMT; domain=.baidu.com
Traceid: 1732012695368569345016542627085320563493
Transfer-Encoding: chunked
X-Ua-Compatible: IE=Edge,chrome=1
X-Xss-Protection: 1;mode=block

  • 响应状态码:

    200:响应成功

    404:找不到资源

    3**:请求重定向

    • 重定向:去指定的新位置

    5**:服务器代码错误 500 502(网关错误)

当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?

5. Maven

maven的作用?

  1. 在javaweb开发中,需要导入大量jar包
  2. 需要自动导入和配置jar包

5.1 Maven项目架构管理工具

用于 方便导入jar包

核心思想:约定大于配置

会规定该如何编写java程序

5.2 阿里云镜像

1
2
3
4
5
6
7
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

5.3 本地仓库

在本地的仓库: <localRepository>D:/programdown/apache-maven-3.9.4/repo</localRepository>

远程仓库

5.4 maven仓库

servlet jar包:https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api/4.0.1

6. Servlet

  • servlet是用于开发动态web的一门技术
  • 这些API中提供了一个接口:Servlet
    • 编写一个类实现Servlet接口
    • 把开发好的java类部署到web服务器中

把实现了Servlet接口的java程序叫做Servlet

6.1 HelloServlet

Servlet接口有两个默认的实现类:HttpServlet

  1. 构建一个Maven项目,删除src目录,

  2. 关于Maven父子工程的理解:

    父项目存在:

    1
    2
    3
    <modules>
    <module>servlet_01</module>
    </modules>

    子项目存在:

    1
    2
    3
    4
    5
    <parent>
    <groupId>com.tu</groupId>
    <artifactId>javaweb_03</artifactId>
    <version>1.0-SNAPSHOT</version>
    </parent>

    父项目中的java 子项目可以直接使用

  3. Maven环境优化

    • 修改web.xml为最新的
    • 将maven的结构搭建完整
  4. 编写一个servlet程序

    • 编写一个普通类

    • 实现Servlet接口,这里直接继承HttpServlet

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      package com.tu.servlet;

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

      public class HelloServlet extends HttpServlet {

      // get post 只是请求实现的不同方式,可以相互调用
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

      // 响应流
      PrintWriter writer = resp.getWriter();
      writer.println("hello, Servlet");


      }

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

  5. 编写Servlet的映射

    为什么需要映射:我们写的是java程序,但是要通过浏览器访问,故需要web服务中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
    http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
    version="4.0"
    metadata-complete="true">
    <!-- 注册servlet-->
    <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.tu.servlet.HelloServlet</servlet-class>
    </servlet>
    <!-- 编写Servlet请求路径-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
    </servlet-mapping>


    </web-app>

  6. 配置Tomcat

    配置项目发布的路径

  7. 启动测试

6.2 Servlet原理

Servlet由Web服务器调用

image-20241120205741100

6.3 mapping

  1. 一个Sevlet请求可以指定一个映射路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!--    注册servlet-->
    <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.tu.servlet.HelloServlet</servlet-class>
    </servlet>
    <!-- 编写Servlet请求路径-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
  2. 一个Sevlet请求可以指定多个映射路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!--    注册servlet-->
    <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.tu.servlet.HelloServlet</servlet-class>
    </servlet>
    <!-- 编写Servlet请求路径-->
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
  3. 一个Sevlet请求可以指定通用的映射路径

    1
    2
    3
    4
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
  4. 默认请求路径

    1
    2
    3
    4
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/*</url-pattern>
    </servlet-mapping>
  5. 指定一些后缀或者前缀

    注意:*前面不能加项目映射的路径

    1
    2
    3
    4
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>*.wendy</url-pattern>
    </servlet-mapping>
  6. 优先级问题

    指定了固定的映射路径 其优先级最高,没有的话就走默认的处理请求。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <servlet>
    <servlet-name>Error</servlet-name>
    <servlet-class>com.tu.servlet.Error</servlet-class>
    </servlet>

    <servlet-mapping>
    <servlet-name>Error</servlet-name>
    <url-pattern>/*</url-pattern>
    </servlet-mapping>

6.4 ServletContext

web容器在启动时,为每个web程序创建一个ServletContext对象,它代表了当前应用。

  • 共享数据

    HelloServlet放置数据到ServletContext中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.tu.servlet;

    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 HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //this.getInitParameter() 获取初始化参数
    //this.getServletConfig() Servlet配置
    //this.getServletContext() Servlet上下文

    ServletContext servletContext = this.getServletContext();
    String username = "tjl"; //数据
    servletContext.setAttribute("username", username); //将数据保存在context中 以键值对的形式

    System.out.println("hello");
    }
    }

​ GetServlet读取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.tu.servlet;

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 GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String username = (String)servletContext.getAttribute("username");


resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("username: " + username);


}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">


<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.tu.servlet.HelloServlet</servlet-class>

</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>getcon</servlet-name>
<servlet-class>com.tu.servlet.GetServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>getcon</servlet-name>
<url-pattern>/tu</url-pattern>
</servlet-mapping>


</web-app>
  • 获取初始化参数

    在xml中设置初始化参数:

    1
    2
    3
    4
    5
    <!--配置web应用的初始化参数-->
    <context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
    </context-param>

    ServletDemo3 获取web应用的初始化参数,返回输出到界面上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.tu.servlet;

    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 ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext = this.getServletContext();
    String url = servletContext.getInitParameter("url");
    resp.getWriter().println(url);
    }

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

  • 请求转发

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext = this.getServletContext();
    System.out.println("进入了ServletDemo4");

    // 将当前请求转发到另一个Servlet去处理
    RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/gp");//转发的请求
    requestDispatcher.forward(req, resp); //调用forward实现请求转发



    image-20241121180843612

  • 读取资源文件

    资源都被打包到/classes下,俗称为class路径

    从class路径中获取一个文件流 InputStream

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
    Properties properties = new Properties();
    properties.load(resourceAsStream);
    String username = (String)properties.get("username");
    String password = properties.getProperty("password");

    resp.getWriter().println(username+":" + password);

    }

6.5 HttpServletResponse

web服务器接收到客户端的http请求,会针对这个请求,分别创建一个代表请求的HttpServletRequest对象和一个代表响应的HttpServletResponse对象

如果要获取客户端请求过来的参数,找HttpServletRequest

如果要给客户端响应一些信息,找HttpServletResponse

  1. 简单分类

    负责向浏览器发送数据的方法:

    • ServletOutputStream getOutputStream() throws IOException;
      PrintWriter getWriter() throws IOException;
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20

      负责向浏览器发送响应头的方法:

      ```java
      void setCharacterEncoding(String var1);

      void setContentLength(int var1);

      void setContentLengthLong(long var1);

      void setContentType(String var1);
      void setDateHeader(String var1, long var2);

      void addDateHeader(String var1, long var2);

      void setHeader(String var1, String var2);

      void addHeader(String var1, String var2);

      void setIntHeader(String var1, int var2);

    响应的状态码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int SC_OK = 200;
    int SC_CREATED = 201;
    int SC_ACCEPTED = 202;
    int SC_NON_AUTHORITATIVE_INFORMATION = 203;
    int SC_NO_CONTENT = 204;
    int SC_RESET_CONTENT = 205;
    int SC_PARTIAL_CONTENT = 206;
    int SC_MULTIPLE_CHOICES = 300;
    int SC_MOVED_PERMANENTLY = 301;
    int SC_MOVED_TEMPORARILY = 302;
    int SC_FOUND = 302;
    int SC_SEE_OTHER = 303;
    int SC_NOT_MODIFIED = 304;
    int SC_USE_PROXY = 305;
    int SC_TEMPORARY_REDIRECT = 307;
    int SC_BAD_REQUEST = 400;
    int SC_UNAUTHORIZED = 401;
    int SC_PAYMENT_REQUIRED = 402;
    int SC_FORBIDDEN = 403;
    int SC_NOT_FOUND = 404;
  2. 常见应用

    • 向浏览器输出消息

    • 下载文件

      1. 获取下载文件路径
      2. 下载文件名
      3. 设置想办法让浏览器能支持下载我们需要的东西
      4. 获取下载文件的输入流
      5. 创建缓冲区
      6. 获取OutputStream对象
      7. 将FileOutPutStream流写入缓冲区
      8. 使用OutputStream将缓冲区中的数据输出到客户端
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      String realPath = "D:\\learn_java\\javaweb_03\\t3\\src\\main\\resources\\p1.png";
      System.out.println("路径:"+realPath);
      String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
      // 想办法让浏览器能够支持下载我们需要的东西,中文文件名encode编码,否则会乱码
      resp.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "utf-8"));
      FileInputStream fileInputStream = new FileInputStream(realPath);
      int len = 0;
      byte[] buffer = new byte[1024];
      ServletOutputStream outputStream = resp.getOutputStream();
      while(fileInputStream.read(buffer) != -1){
      outputStream.write(buffer, 0, fileInputStream.read(buffer));

      }
      outputStream.close();;
      fileInputStream.close();



      }
    • 验证码功能

      • 前端实现

      • 后端实现:需要java的图片类,产生一个图片验证码

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        public class ImageServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 让浏览器3秒自动刷新一次
        resp.setHeader("refresh", "3");
        // 在内存中创建一个图片
        BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        // 得到图片
        Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics();
        //设置图片背景颜色
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0,0,80,80);
        //给图片写数据
        graphics.setColor(Color.BLUE);
        graphics.setFont(new Font(null, Font.BOLD, 20));
        graphics.drawString(makeNum(), 0,20);

        //告诉浏览器这个请求用图片的方式打开
        resp.setContentType("image/png");
        //网站存在缓存,不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control", "no-cache");
        resp.setHeader("Pragma", "no-cache");
        //把图片写给浏览器
        boolean write = ImageIO.write(bufferedImage, "png", resp.getOutputStream());



        }

        private String makeNum(){
        Random random = new Random();
        String s = random.nextInt(999999999) + "";
        StringBuffer sb = new StringBuffer();
        // 必须保证是7位数
        for(int i=0; i<7 - s.length(); i++){
        sb.append("0");
        }

        String s1 = sb.toString() + s;
        return s1;
        }
        }
    • 实现重定向

      image-20241121195220419

      一个web资源B收到客户端A请求后,会通知客户端A去访问另一个‘web

      资源C。

      常见重定向:

      • 用户登录

        1
        2
        void sendRedirect(String var1) throws IOException;

        测试:

        1
        2
        3
        4
        5
        6
        7
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 重定向
        resp.sendRedirect("/t3_war/img");


        }

        image-20241121200317834

    • 重定向与转发的区别:

      相同点:

      • 页面会实现跳转

      不同点:

      • 请求转发时,url不会产生改变 307
      • 重定向时,url地址栏会改变 302

6.6 HttpServletRequest

HttpServletRequest代表用户通过HTTP协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息

  1. 获取前端传递的参数

  2. 请求转发

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    req.setCharacterEncoding("utf-8");

    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String[] hobbies = req.getParameterValues("hobbies");
    System.out.println("=====================");
    System.out.println(username);
    System.out.println(password);
    System.out.println(Arrays.toString(hobbies));

    resp.setCharacterEncoding("utf-8");

    req.getRequestDispatcher("/success.jsp").forward(req, resp);

7. Cookie, Session

7.1 会话

会话:用户打开一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,整个过程相当于一次会话。

有状态会话:一个同学来过教室,下次再来,我们能知道这个同学曾经来过

一个网站怎么证明你来过?

服务器 客户端 来过

  1. 服务端给客户端一个 信件,客户端下次访问服务端带上信件就可以了;

  2. 服务器登记你来过了,下次你来时服务端来匹配你

7.2 保存会话的两种技术

cookie

  • 客户端技术(响应,请求)

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息,可以把信息或者数据放在session中

常见场景:网站登录后,第二次直接访问就上去了

image-20241122160754429

  1. 从请求中拿到cookie信息
  2. 服务端响应客户端cookie
1
2
3
4
5
6
7
8
// cookie 服务器从客户端获取
Cookie[] cookies = req.getCookies(); //cookie有多个
cookie.getName()
cookie.getValue()
new Cookie("lastLoginTime", System.currentTimeMillis() + "");
//设置有效期为一天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);//响应给客户端

cookie:会保存在本地的用户目录的appdata下

一个网站cookie是否存在上限?

  • 一个cookie只能保存一个信息
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
  • 300个cookie浏览器上限
  • cookie大小由限制 4kb

删除cookie:

  • 不设置有效期,关闭浏览器,自动失效
  • 设置有效期为0

编码解码:

1
2
URLEncoder.encode("中文", "utf-8")
URLDecoder.decode("中文", "utf-8")

7.4 Session(重点)

  • 服务器会给每一个用户(浏览器)创建一个Session对象
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
  • 用户登录之后,整个网站都可以访问了–>保存用户的信息;保存购物车的信息

Session和Cookie的区别

  • Cookie:把用户的数据写入数据的浏览器,浏览器保存(可以保存多个)
  • Session:把用户的数据写到用户独占的Session,服务器端保存
  • Session对象由服务器创建

Session使用场景:

  • 保存一个用户登录的信息
  • 购物车信息
  • 在整个网站中经常会使用的数据,保存在Session中

使用Session:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// 得到session,写入session
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset = utf-8");
//得到Session
HttpSession session = req.getSession();
//给Session中存东西
session.setAttribute("name", new Person("tjl", 1));
//获取session的id
String id = session.getId();
//判断session是不是新创建的
if(session.isNew()){
resp.getWriter().write("session is created, id:"+id);
}
else{
resp.getWriter().write("session 已经存在, id:"+id);

}
// session创建时:
// 创建了一个cookie(增加sessionid)

}

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


// 获取session
public class SessionDemo02 extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset = utf-8");
//得到Session
HttpSession session = req.getSession();
//获取session里面的东西
Person name = (Person)session.getAttribute("name");
System.out.println(name.toString());



}
}


// 注销session
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
// 手动注销Session
session.invalidate();

}


会话自动过期:

1
2
3
<session-config>
<session-timeout>15</session-timeout>
</session-config>

image-20241122160903230

8. JSP

8.1 什么是JSP

Java Server Pages:服务器端页面,也和Servlet一样,用于动态web技术

特点:

  • 写jsp就像html
  • 区别:
    • html只有静态数据
    • jsp页面中可以嵌入java代码,提供动态数据

8.2 JSP原理

  • 服务器内部工作

    tomcat由一个work目录

    IDEA中使用tomcat会在IDEA的tomcat中产生一个work目录

    1
    "C:\Users\TJL\AppData\Local\JetBrains\IntelliJIdea2023.2\tomcat\3e481f8a-25bf-4dfc-88df-0b869c9043b4\work\Catalina\localhost\ROOT\org\apache\jsp\index_jsp.java"

    浏览器向服务器发送请求,不管访问什么资源,都是在访问Servlet

    JSP最终也会转成java类

    1. 判断请求

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      final java.lang.String _jspx_method = request.getMethod();
      if ("OPTIONS".equals(_jspx_method)) {
      response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
      return;
      }
      if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
      response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
      return;
      }
      }
    2. 内置对象

      1
      2
      3
      4
      5
      6
      final javax.servlet.jsp.PageContext pageContext;
      javax.servlet.http.HttpSession session = null;
      final javax.servlet.ServletContext application;
      final javax.servlet.ServletConfig config;
      javax.servlet.jsp.JspWriter out = null;
      final java.lang.Object page = this;
    3. 输出页面前增加的代码

      1
      2
      3
      4
      5
      6
      7
      8
      response.setContentType("text/html");
      pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;
    4. 以上这些对象可以在jsp中直接使用

image-20241122163818815

JSP页面中,只要时java代码就会原封不动输出

JTML代码,变成out.write(“\r\n”)

8.3 JSP基础语法

JSP表达式

1
2
3
4
5
<%--用于将程序的输出 输出到客户端
<%= 变量或者表达式 %>
--%>

<%= new java.util.Date() %>

脚本片段

1
2
3
4
5
6
7
8
9
10
<%--jsp脚本片段--%>
<%
int sum =0;
for (int i = 0; i < 100; i++) {
sum+=i;

}
out.println("<h1>sum="+sum+"</h1>");

%>

脚本片段再实现

1
2
3
4
5
6
7
8
<%--在代码中嵌入html--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h1>hello <%= i%> </h1>
<%
}
%>

JSP声明 (写 类中的其他方法)

1
2
3
4
5
6
7
8
9
10
<%!
static {
System.out.println("loading servlet");
}
private int globalVar = 0;

public void jspInit(){
System.out.println("进入了初始化方法");
}
%>

其他的编译会被生成到_jspService方法中

在jsp中嵌入java代码

EL表达式

1
2
<%--类似 <%= %> -->
${i}

JSP注释式不在源码上显示的

8.4 JSP指令

1
2
3
4
5
6
7
<%--指定错误页面 500 404 --%>
<%@page errorPage="error/500.jsp" %>

<%-- 提取公共页面 --%>
<%@include file="common/header.jsp"%>
<jsp:include page="/common/header.jsp"/>

8.5 九大内置对象

  • PageContext:存东西
  • Request:存东西
  • Response
  • Session:存东西
  • Application (ServletContext) :存东西
  • conifg (ServletConfig)
  • out
  • page
  • exception
1
2
3
4
5
6
7
<%--内置对象--%>
<%
pageContext.setAttribute("name1", "1号"); //保存到数据只在一个页面中有效
request.setAttribute("name2", "2号");//只在一次请求中有效,在请求转发中有效
session.setAttribute("name3", "3号");//在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4", "4号");//在服务器中有效,从打开服务器到关闭服务器
%>

request:客户端向服务器发送的请求,产生的数据,用户看完没用,如新闻

session:客户端向服务器发送的请求,产生的数据,用户看完还有用,如购物车

application:客户端向服务器发送的请求,产生的数据,一个用户用完了,其他用户还能使用,如聊天数据

8.6 JSP标签、JSTL标签、EL表达式

导包:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

EL表达式${}

  • 获取数据 ${param.参数名}
  • 执行运算
  • 获取web开发常用对象

JSP标签

转发 并 携带参数

1
2
3
4
5
<%--http://localhost:8088/jsptag.jsp?v1=value1&v2=value2--%>
<jsp:forward page="jsptag2.jsp">
<jsp:param name="v1" value="value1"/>
<jsp:param name="v2" value="value2"/>
</jsp:forward>

JSTL标签

为了弥补HTML标签的不足,自定义了很多标签,标签的功能和java代码一样

核心标签库:<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

image-20241123195712908

使用步骤:

  • 引入对应taglib
  • 使用其中方法

if测试

1
2
3
4
5
6
7
8
9
10
11
<form action="coreif.jsp" method="get">
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>

<%--判断如果提交的用户名是管理员,提交成功--%>
<c:if test="${param.username == 'admin'}" var="isAdmin" >
<c:out value="管理员欢迎您!"/>
</c:if>

<c:out value="${isAdmin}"></c:out>

when

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<c:set var="score" value="85"/>

<c:choose>
<c:when test="${score>=90}">
你的成绩为优秀
</c:when>
<c:when test="${score>=80}">
你的成绩为良好
</c:when>
<c:when test="${score>=60}">
你的成绩为一般
</c:when>
<c:when test="${score<60}">
你的成绩为差
</c:when>
</c:choose>

foreach

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

<%
ArrayList<String> strings = new ArrayList<>();
strings.add(0,"张三");
strings.add(1,"李四");
strings.add(2,"王五");
strings.add(3,"赵六");
strings.add(4,"前七");
request.setAttribute("list", strings);
%>
<%--
var: 每次遍历出来的遍历
items:要遍历的对象
--%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>


<hr>

<c:forEach begin="1" end="3" step="2" var="people" items="${list}">
<c:out value="${people}"/> <br>

</c:forEach>

9. JavaBean

实体类 javabean(pojo, entity)

有特定写法:

  • 必须有一个无参构造
  • 属性必须私有化
  • 必须有get/set方法

一般用来和数据库的字段做映射 ORM

ORM : 对象关系映射

  • 表 –> 类
  • 字段 –> 属性
  • 行记录 –> 对象

People表

id name age address
1 t1 3 青岛
2 t2 10 武汉
3 t3 12 武汉
1
2
3
4
5
6
7
8
9
10
class People{
private int id;
priavte String name;
private int age;
private String address;
}

class A{
new People(1, "t1", 3, "青岛");
}

10. MVC三层架构

什么是MVC: Model View Controller 模型 视图 控制器

10.1 以前早期的架构

image-20241123211739569

用户直接访问控制层,控制层就可以操作数据库

1
2
3
4
5
6
7
servlet -- CRUD --> 数据库
弊端:程序十分臃肿,不利于维护
servlet: 处理请求,响应,处理JDBC,处理业务代码,处理逻辑代码

架构:没有什么加一层是解决不了的
如:jdbc作为中间件可用连接各种数据库

10.2 MVC三层架构

image-20241123212403806

Model

  • 业务处理:业务逻辑(Service)
  • 数据持久层:CRUD (Dao)

View

  • 展示数据
  • 提供连接发起Service请求

Controller (Servlet)

  • 接收用户请求 (req,:请求参数 Session信息)

  • 交给业务层处理对应代码

  • 控制视图跳转

    1
    登录 ---> 接收用户的登录请求 ---> 处理用户的请求(获取用户登录的参数,username, password) ---> 交给业务层处理登录业务(判断密码是否正确) ---> Dao层 查询用户名和密码是否正确 ---> 数据库

11. Filter (重点)

Filter:过滤器,用于过滤网站 的数据

image-20241124191119895

  • 处理中文乱码
  • 登录验证

开发步骤:

  1. 导包

  2. 编写过滤器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    package com.tu.filter;

    import javax.servlet.*;
    import java.io.IOException;

    public class CharacterEncodingFilter implements Filter {
    // 初始化
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    System.out.println("初始化");
    }

    @Override
    // chain :
    /*
    * 1. 过滤中的所有代码,在过滤特定请求的时候都会执行
    * 2. 必须要让过滤器继续同行
    */
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    servletRequest.setCharacterEncoding("utf-8");
    servletResponse.setCharacterEncoding("utf-8");
    servletResponse.setContentType("text/html; charset=UTF-8");
    System.out.println("characterEncodingFilter执行前");
    filterChain.doFilter(servletRequest,servletResponse); //让请求继续走,如果不写,程序到这里九停止了
    System.out.println("characterEncodingFilter执行后");
    }

    @Override
    public void destroy() {
    // web服务器停止才会销毁
    System.out.println("销毁");
    }
    }

  3. 在xml中配置过滤器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>com.tu.filter.CharacterEncodingFilter</filter-class>
    </filter>

    <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <!-- 只要是/servlet下的任何请求 都会经过这个过滤器-->
    <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>

12. 监听器

实现一个监听器的接口:

  1. 编写一个监听器

    实现监听器的接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    package com.tu.listener;

    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;

    // 统计网站在线人数:统计session
    public class OnlineCountListener implements HttpSessionListener {

    @Override
    // 创建session监听
    // 一旦创建session就会触发这个事件
    public void sessionCreated(HttpSessionEvent se) {
    ServletContext servletContext = se.getSession().getServletContext();
    Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");

    if(onlineCount == null){
    onlineCount = new Integer(1);
    }
    else{
    int count = onlineCount.intValue();
    onlineCount = new Integer(count + 1);
    }

    servletContext.setAttribute("OnlineCount", onlineCount);


    }

    @Override
    // 销毁session监听
    // 一旦销毁session就会触发
    public void sessionDestroyed(HttpSessionEvent se) {
    ServletContext servletContext = se.getSession().getServletContext();
    Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");

    if(onlineCount == null){
    onlineCount = new Integer(0);
    }
    else{
    int count = onlineCount.intValue();
    onlineCount = new Integer(count - 1);
    }

    servletContext.setAttribute("OnlineCount", onlineCount);

    }
    }

    //session销毁:
    // 1. 手动销毁
    // 2. 自动销毁:设置销毁时间

  2. 在web.xml中注册监听器

    1
    2
    3
    <listener>
    <listener-class>com.tu.listener.OnlineCountListener</listener-class>
    </listener>

JAVAWeb——Web的基本概念
https://wendyflv.github.io/2024/11/07/JAVAWeb——Web的基本概念/
作者
Wendyflv
发布于
2024年11月7日
许可协议