JavaWeb知识梳理(可收藏)
阅读原文时间:2022年04月06日阅读:1

**JavaWeb相关知识 **

1、Servlet

1、1xx 请求信息

Http状态码

Http Status Code

Http状态码含义中文说明

100

100 Continue

请继续请求

101

101 Switching Protocols

请切换协议

102

102 Processing

将继续执行请求

2、2xx 成功状态

这一组状态码表明客户端的请求已经被服务器端成功接收并正确解析。

Http状态码

Http Status Code

Http状态码含义中文说明

200

200 OK

请求成功

201

201 Created

请求已被接受,等待资源响应

202

202 Accepted

请求已被接受,但尚未处理

203

203 Non-Authoritative Information

请求已成功处理,结果来自第三方拷贝

204

204 No Content

请求已成功处理,但无返回内容

205

205 Reset Content

请求已成功处理,但需重置内容

206

206 Partial Content

请求已成功处理,但仅返回了部分内容

207

207 Multi-Status

请求已成功处理,返回了多个状态的XML消息

208

208 Already Reported

响应已发送

226

226 IM Used

已完成响应

3、3xx 重定向状态

这一组状态码表示客户端需要采取更进一步的行动来完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。

Http状态码

Http Status Code

Http状态码含义中文说明

300

300 Multiple Choices

返回多条重定向供选择

301

301 Moved Permanently

永久重定向

302

302 Found

临时重定向

303

303 See Other

当前请求的资源在其它地址

304

304 Not Modified

请求资源与本地缓存相同,未修改

305

305 Use Proxy

必须通过代理访问

306

306 (已废弃)Switch Proxy

(已废弃)请切换代理

307

307 Temporary Redirect

临时重定向,同302

308

308 Permanent Redirect

永久重定向,且禁止改变http方法

4、4xx 客户端错误

这一组状态码表示客户端的请求存在错误,导致服务器无法处理。除非响应的是一个HEAD请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。这些状态码适用于任何请求方法。浏览器应当向用户显示任何包含在此类错误响应中的实体内容。

Http状态码

Http Status Code

Http状态码含义中文说明

400

400 Bad Request

请求错误,通常是访问的域名未绑定引起

401

401 Unauthorized

需要身份认证验证

402

402 Payment Required

-

403

403 Forbidden

禁止访问

404

404 Not Found

请求的内容未找到或已删除

405

405 Method Not Allowed

不允许的请求方法

406

406 Not Acceptable

无法响应,因资源无法满足客户端条件

407

407 Proxy Authentication Required

要求通过代理的身份认证

408

408 Request Timeout

请求超时

409

409 Conflict

存在冲突

410

410 Gone

资源已经不存在(过去存在)

411

411 Length Required

无法处理该请求

412

412 Precondition Failed

请求条件错误

413

413 Payload Too Large

请求的实体过大

414

414 Request-URI Too Long

请求的URI过长

415

415 Unsupported Media Type

无法处理的媒体格式

416

416 Range Not Satisfiable

请求的范围无效

417

417 Expectation Failed

无法满足的Expect

418

418 I'm a teapot

愚人节笑话

421

421 There are too many connections from your internet address

连接数超限

422

422 Unprocessable Entity

请求的语义错误

423

423 Locked

当前资源被锁定

424

424 Failed Dependency

当前请求失败

425

425 Unordered Collection

未知

426

426 Upgrade Required

请切换到TLS/1.0

428

428 Precondition Required

请求未带条件

429

429 Too Many Requests

并发请求过多

431

431 Request Header Fields Too Large

请求头过大

449

449 Retry With

请重试

451

451 Unavailable For Legal Reasons

访问被拒绝(法律的要求)

499

499 Client Closed Request

客户端主动关闭了连接

5、5xx 服务器错误状态

这一组状态码说明服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。除非这是一个HEAD请求,否则服务器应当包含一个解释当前错误状态以及这个状况是临时的还是永久的解释信息实体。浏览器应当向用户展示任何在当前响应中被包含的实体。

Http状态码

Http Status Code

Http状态码含义中文说明

500

500 Internal Server Error

服务器端程序错误

501

501 Not Implemented

服务器不支持的请求方法

502

502 Bad Gateway

网关无响应

503

503 Service Unavailable

服务器端临时错误

504

504 Gateway Timeout

网关超时

505

505 HTTP Version Not Supported

服务器不支持的HTTP版本

506

506 Variant Also Negotiates

服务器内部配置错误

507

507 Insufficient Storage

服务器无法存储请求

508

508 Loop Detected

服务器因死循环而终止操作

509

509 Bandwidth Limit Exceeded

服务器带宽限制

510

510 Not Extended

获取资源策略未被满足

511

511 Network Authentication Required

需验证以许可连接

599

599 Network Connect Timeout Error

网络连接超时

在收到请求之后,服务器会进行如下工作:

**JavaWeb相关知识 **

1、Servlet

1、1xx 请求信息

Http状态码

Http Status Code

Http状态码含义中文说明

100

100 Continue

请继续请求

101

101 Switching Protocols

请切换协议

102

102 Processing

将继续执行请求

2、2xx 成功状态

这一组状态码表明客户端的请求已经被服务器端成功接收并正确解析。

Http状态码

Http Status Code

Http状态码含义中文说明

200

200 OK

请求成功

201

201 Created

请求已被接受,等待资源响应

202

202 Accepted

请求已被接受,但尚未处理

203

203 Non-Authoritative Information

请求已成功处理,结果来自第三方拷贝

204

204 No Content

请求已成功处理,但无返回内容

205

205 Reset Content

请求已成功处理,但需重置内容

206

206 Partial Content

请求已成功处理,但仅返回了部分内容

207

207 Multi-Status

请求已成功处理,返回了多个状态的XML消息

208

208 Already Reported

响应已发送

226

226 IM Used

已完成响应

3、3xx 重定向状态

这一组状态码表示客户端需要采取更进一步的行动来完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。

Http状态码

Http Status Code

Http状态码含义中文说明

300

300 Multiple Choices

返回多条重定向供选择

301

301 Moved Permanently

永久重定向

302

302 Found

临时重定向

303

303 See Other

当前请求的资源在其它地址

304

304 Not Modified

请求资源与本地缓存相同,未修改

305

305 Use Proxy

必须通过代理访问

306

306 (已废弃)Switch Proxy

(已废弃)请切换代理

307

307 Temporary Redirect

临时重定向,同302

308

308 Permanent Redirect

永久重定向,且禁止改变http方法

4、4xx 客户端错误

这一组状态码表示客户端的请求存在错误,导致服务器无法处理。除非响应的是一个HEAD请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。这些状态码适用于任何请求方法。浏览器应当向用户显示任何包含在此类错误响应中的实体内容。

Http状态码

Http Status Code

Http状态码含义中文说明

400

400 Bad Request

请求错误,通常是访问的域名未绑定引起

401

401 Unauthorized

需要身份认证验证

402

402 Payment Required

-

403

403 Forbidden

禁止访问

404

404 Not Found

请求的内容未找到或已删除

405

405 Method Not Allowed

不允许的请求方法

406

406 Not Acceptable

无法响应,因资源无法满足客户端条件

407

407 Proxy Authentication Required

要求通过代理的身份认证

408

408 Request Timeout

请求超时

409

409 Conflict

存在冲突

410

410 Gone

资源已经不存在(过去存在)

411

411 Length Required

无法处理该请求

412

412 Precondition Failed

请求条件错误

413

413 Payload Too Large

请求的实体过大

414

414 Request-URI Too Long

请求的URI过长

415

415 Unsupported Media Type

无法处理的媒体格式

416

416 Range Not Satisfiable

请求的范围无效

417

417 Expectation Failed

无法满足的Expect

418

418 I'm a teapot

愚人节笑话

421

421 There are too many connections from your internet address

连接数超限

422

422 Unprocessable Entity

请求的语义错误

423

423 Locked

当前资源被锁定

424

424 Failed Dependency

当前请求失败

425

425 Unordered Collection

未知

426

426 Upgrade Required

请切换到TLS/1.0

428

428 Precondition Required

请求未带条件

429

429 Too Many Requests

并发请求过多

431

431 Request Header Fields Too Large

请求头过大

449

449 Retry With

请重试

451

451 Unavailable For Legal Reasons

访问被拒绝(法律的要求)

499

499 Client Closed Request

客户端主动关闭了连接

5、5xx 服务器错误状态

这一组状态码说明服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。除非这是一个HEAD请求,否则服务器应当包含一个解释当前错误状态以及这个状况是临时的还是永久的解释信息实体。浏览器应当向用户展示任何在当前响应中被包含的实体。

Http状态码

Http Status Code

Http状态码含义中文说明

500

500 Internal Server Error

服务器端程序错误

501

501 Not Implemented

服务器不支持的请求方法

502

502 Bad Gateway

网关无响应

503

503 Service Unavailable

服务器端临时错误

504

504 Gateway Timeout

网关超时

505

505 HTTP Version Not Supported

服务器不支持的HTTP版本

506

506 Variant Also Negotiates

服务器内部配置错误

507

507 Insufficient Storage

服务器无法存储请求

508

508 Loop Detected

服务器因死循环而终止操作

509

509 Bandwidth Limit Exceeded

服务器带宽限制

510

510 Not Extended

获取资源策略未被满足

511

511 Network Authentication Required

需验证以许可连接

599

599 Network Connect Timeout Error

网络连接超时

在收到请求之后,服务器会进行如下工作:

 <!--注册服务器name =  "HelloServet"-->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.Aaron.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径 urlPatterns = "/Aason",loadOnStartup = 15-->
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/Aaron</url-pattern>
    </servlet-mapping>



<?xml version="1.0" encoding="UTF-8"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<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">

</web-app>

   pom依赖
         <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>

如果启动Tomcat后文件运行正常,但是单独运行文件JSP显示代码,那么就是xml文件配置了Servlet,可以在Java文件中单独写头部。如下图

  1. 一个Servlet可以指定一个映射路径

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron</url-pattern>
        </servlet-mapping>
  2. 一个Servlet可以指定多个个映射路径

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron</url-pattern>
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron1&lt;/url-pattern&gt;
    
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron2&lt;/url-pattern&gt;
    
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron3&lt;/url-pattern&gt;
    
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron4&lt;/url-pattern&gt;
    
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron5&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;</code></pre></li>
  3. 一个Servlet可以指定通用映射路径(/*权限很高)

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron/*</url-pattern>权限很高
        </servlet-mapping>
  4. 默认请求路径路径


    HelloServlet
    /*

  5. 指定一些前后缀

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>*.Aaron</url-pattern>  <!-- 可以自定义后缀请求映射,但是前面*不可加/ -->
        </servlet-mapping>
  6. 优先级问题

    指定了固有的映射路径优先级最高,如果找不到就会走默认的请求;

    <!--Error错误服务器注册-->
    <servlet>
        <servlet-name>ErrorServlet</servlet-name>
        <servlet-class>com.Aaron.servlet.ErrorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ErrorServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

2、 ServletContext

2.3.1 共享数据

​ web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web容器;

  • 共享数据,保存数据,达到共享;

2.3.2 setAttribute转发

测试访问结果,先访问set ,获取值后在访问get,强转换String

​ String username = (String)context.getAttribute("username");

package com.Aaron.servlet; /**
 * @Author: Alskaboo
 * @Date: 2022-03-29 19:40
 **/

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

//@WebServlet(name = "HelloServlet", value = "/HelloServlet")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//        this.getInitParameter();初始化值
//        this.getServletConfig();servlet配置
//        this.getServletContext();servlet上下文衔接对象
        ServletContext context = this.getServletContext();

        String username = "菜菜";//数据
        context.setAttribute("username", username);//键值对的形式,将数据保存在了ServletContext中,名字叫username;与后面的key名必须相同
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

package com.Aaron.servlet;

import sun.security.timestamp.HttpTimestamper;

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

/**
 * @Author: Alskaboo
 * @Date: 2022-03-29 21:13
 **/

public class getServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String)context.getAttribute("username");

        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().print("名字"+username);

    }

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

    }
}



<?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">
    <!--注册服务器name =  "HelloServet"-->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.Aaron.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径 urlPatterns = "/Aason",loadOnStartup = 15-->
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/Aaron</url-pattern>
    </servlet-mapping>

    <!--Error错误服务器注册-->
    <servlet>
        <servlet-name>getc</servlet-name>
        <servlet-class>com.Aaron.servlet.getServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getc</servlet-name>
        <url-pattern>/getc</url-pattern>
    </servlet-mapping>
</web-app>

2.3.3 请求转发

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        context.getRequestDispatcher("/Demo_02").forward(req,resp);//请求转发的路径并且调用forward实现请求转发
    }

重定向:A找B要东西,B没有,但是B告诉A,C那里有你需要的,那么A直接根据路径找C(路径改变);

2.3.4 读取资源文件

properties类:

生成在classpath路径中

    <!--在build中配置resources,来防止我们资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

3、 HttpServletResponse

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

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要给客户端响应一些信息:找HttpservletResponse

2.4.1. 简单分类

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

servletoutputstream getoutputstream() throws IOException;
Printwriter getwriter() throws IOException;

Http相应

Cache-Control: private    缓存控制
Connection:Keep-Alive     连接
Content-Encoding:gzip     编码
Content-Type:text/html    类型

2.4.2 文件下载

  1. 向浏览器输出消息

  2. 下载文件

    package com.Aaron;

    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.URLEncoder;

    /**

    • @Author: Alskaboo

    • @Date: 2022-03-30 17:39
      **/
      public class FileServelet extends HttpServlet {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //1. 要获取下载文件的路径,realpath是用来将参数path所指的相对路径转换成绝对路径,然后存于参数resolved_path所指的字符串数组或指针中的一个函数
      // String realPath = this.getServletContext().getRealPath("/ycCity.jpg");
      String realPath = "F:\Code\ideacode\JavaClassWeb\Maven02\response_01\src\main\resources\ycCity.jpg";
      System.out.println("下载文件路径:" + realPath);
      //2. 下载的文件名是啥?
      String fielname = realPath.substring(realPath.lastIndexOf("\") + 1);//直接截取字符串,截取最后一个"/"的下一个就是那个文件名
      //3. 设置想办法让浏览器能够支持下载我们需要的东西
      resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fielname,"UTF-8"));
      //4. 获取下载文件的输入流
      FileInputStream fileInputStream = new FileInputStream(realPath);
      //5. 创建缓冲区
      int len = 0;
      byte[] buffer = new byte[1024];
      //6. 获取OutputStream对象
      ServletOutputStream outputStream = resp.getOutputStream();
      //7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
      while ((len = fileInputStream.read(buffer)) != -1) {
      outputStream.write(buffer, 0, len);
      }
      //8.关闭流
      fileInputStream.close();
      outputStream.close();

      }

      filedown com.Aaron.FileServelet
      filedown /filedown

2.4.3 验证码功能

  1. 验证怎么来的?

    • 前端实现

    • 后端实现,需要用到Java的图片类,生产一个图片

    package com.Aaron;

    import javax.imageio.ImageIO;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;

    /**

    • @Author: Alskaboo

    • @Date: 2022-03-30 22:06
      **/
      public class ImageServlet extends HttpServlet {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //如何让浏览器5秒自动刷新一次
      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, 20);
      //给图片写数据
      graphics.setColor(Color.RED);
      graphics.setFont(new Font(null, Font.BOLD, 20));//BOLD粗体
      graphics.drawString(setRandom(), 0, 20);
      //告诉浏览器这个请求用图片的形式打开
      resp.setContentType("image/jpg");
      //网站是有缓存的,不让浏览器缓存
      resp.setDateHeader("expires", -1);
      resp.setHeader("Cache-Control", "no-Cache");
      resp.setHeader("Pragma", "no-Cache");
      //把图片写给浏览器
      boolean write = ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());

      }

      //生成随机数
      private String setRandom() {
      Random random = new Random();
      String num = random.nextInt(999_9999) + " ";
      StringBuffer stringBuffer = new StringBuffer();//StringBuffer 字符串拼接
      for (int i = 0; i < 7 - num.length(); i++) {
      stringBuffer.append("0");//保证输出七位数,不足用0填充
      }
      String s = stringBuffer.toString() + num;
      return num;
      }

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

      ImageServlet com.Aaron.ImageServlet
      ImageServlet /img

2.4.4 重定向

定义:B一个web资源收到客户端A请求后,B他会通知A客户端去访问另外一个web资源,这个过程叫重定向

常见场景:

  • 用户登录

测试

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
        resp.setHeader("Location","/response/img");
        resp.setStatus(302);
         */

        resp.sendRedirect("/response/img");
    }

面试题

重定向和转发的区别:

相同点:

  • 页面都会跳转

不同点:

  • 请求转发的时候,URL不会发生变化

  • 重定向的时候,URL会发生变化

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入这个请求了");
        //处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
    //重定向一定要注意路径问题
    resp.sendRedirect("/response/LoginSuccess.jsp");
    }

    <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>

    主页

    Login Success!


    <servlet>
        <servlet-name>RequestText</servlet-name>
        <servlet-class>com.Aaron.send.RequestTest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestText</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

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

2.5.1 获取前端的参数,并且请求转发

 @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //后台接收乱码问题
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String[] hobbies = request.getParameterValues("hobbies");

        //打出
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(hobbies));

        //请求转发
        request.getRequestDispatcher("success.jsp").forward(request, response);

    }

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

面试题

重定向和转发的区别:

相同点:

  • 页面都会跳转

不同点:

  • 请求转发的时候,URL不会发生变化;307
  • 重定向的时候,URL会发生变化;302

4、 Cookie和Session(重点)

1、Cookie

  1. 从服务器请求中拿到Cookie信息
  2. 服务器相应给客户端cookie

1、cookie会话

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话

有状态会话:访问网站,下次访问有记录的情况

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

客户端 服务端

  1. 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了; cookie
  2. 服务器登记你来过了,下次你来的时候我来匹配你;session

2、保存会话的两种技术

cookie

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

session

  • 服务器技术,利用这个技术,可以保存会话的信息,我们把它保存到Session中

    //Cookie,服务器端从客户端获取呀;
    Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个
    cookie.getName();//获得cookie
    cookie.getValue();//获得cookie中的Value
    Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");//新建一个cookie
    cookie.setMaxAge(24 * 62 * 60); //cookie有效期
    resp.addCookie(cookie);//响应给客户端一个cookie

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

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

删除Cookie:

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

解决cookie乱码

编码解码

Cookie cookie = new Cookie("name", URLEncoder.encode("秦疆", "UTF-8"));
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));

相关源码

package com.Aaron.Servlet;

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

import static java.lang.System.out;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-01 19:35
 **/
//保存 用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //服务器告诉你,你来的时间,把这个这个时间封装,下次你来带来我就知道你来了
        //解决中文乱码
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=UTF-8");

        PrintWriter out = resp.getWriter();
        //Cookie,服务器端从客户端获取呀;
        Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个
        //判断Cookie是否存在
        if (cookies != null) {
            //如果存在怎么办
            out.write("您上一次访问本站的时间是:");
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //获取cookie的名字
                if (cookie.getName().equals("lastLoginTime")) {
                    //获取cookie中的值
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastLoginTime);
                    out.write(date.toLocaleString());
                }
            }
        } else {
            out.write("这是您第一次访问本站");
        }
        //服务给客户端响应一个cookie;
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
        //cookie有效期为一天
        cookie.setMaxAge(24 * 62 * 60);
        resp.addCookie(cookie);
    }

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



package com.Aaron.Servlet;

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

/**
 * @Author: Alskaboo
 * @Date: 2022-04-01 21:01
 **/
public class CookieDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建和刚才的cookie名字一样
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
        cookie.setMaxAge(0);
        resp.addCookie(cookie);
    }

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



<?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>CookieDemo01</servlet-name>
        <servlet-class>com.Aaron.Servlet.CookieDemo01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieDemo01</servlet-name>
        <url-pattern>/c1</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>CookieDemo02</servlet-name>
        <servlet-class>com.Aaron.Servlet.CookieDemo02</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieDemo02</servlet-name>
        <url-pattern>/c2</url-pattern>
    </servlet-mapping>
</web-app>

2、Session(重点)含销毁时间

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话

什么是session:

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

使用场景:

  • 保存一个登录用户的信息
  • 购物车信息
  • 整个网站中经常使用的信息

相关代码:

//得到Session
HttpSession session = req.getSession();

//给Session存东西
Person person = new Person("秦疆",10);
session.setAttribute("name", person);



//得到Session
HttpSession session = req.getSession();

//给Session存东西
Person name = (Person) session.getAttribute("name");
System.out.println(name);


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

    }

会话关闭web配置文件

    <!--设置Session默认的失效时间-->
    <session-config>
        <!--设置Session失效时间,以分钟为单位 24*60-->
        <session-timeout>1440</session-timeout>
    </session-config>
  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务创建;

5、JSP

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

最大的特点:写JSP就像在写HTML

HTML和JSP最大的区别:

  • HTML只给用户静态的
  • JSP页面中可以嵌入java代码,为用户提供动态数据

思路:JSP怎么运行?

  • 代码层面没有问题

  • 服务器内部工作

    Tomcat中的work目录

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

JSP最终也会被转换成JAVA类

JSP本质上就是一个Servlet

在JSP中:

只要是Java代码就会原封不动的输出;

如果是HTML代码,就会被转换

out.write("<html>\r\n");

这样的格式输出到前端。

任何语言都有自己的语法,JSP作为java技术的一种应用,它拥有一些自己扩充的语法(了解),Java所有语法都支持

JSP表达式

<%--JSP表达式
作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式 %>
--%>
  <%= new java.util.Date()%>

jsp脚本片段

<%--脚本片段--%>
<%
    int sum = 0;
  for (int i = 0; i <= 100; i++) {
    sum += i;
  }
    out.println("<h1>Sum=" + sum + "</h1>");
%>

<%
    for (int i = 0; i < 5; i++) {
%>
<h2>Hello,World! <%=i%>//${i}
</h2>
<%
    }
%>

JSP指令

1.错误页面

<%@ page errorPage= "路径" %>

或者单独创建图片

<img src="路径" alt="500">

或者配置文件

<error-page>
<error-code>404</error-code>
<location> /error/404.jsp</ location></error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>

网站主体:拼接页面

jsp注释

1.隐藏注释

下面介绍一种隐藏注释,注释格式如下:

<%--注释内容--%>

2.HTML中的注释

JSP 文件是由 HTML 标记和嵌入的 Java 程序段组成的,所以在 HTML 中的注释同样可以在 JSP 文件中使用。这种注释虽然在客户端浏览页面时不会看见,但它却存在于源代码中,可通过在客户端查看源代码看到被注释的内容。所以严格来说,这种注释并不安全。注释格式如下:

<!--注释内容-->

3.<% %>脚本片段

其中写的内容会翻译在Servlet的Service方法中,显然我们可以在Service方法中定义局部变量或者调用其他方法,但是不能

在Service中再定义其他的方法,也就是我们可以在<%%>中定义局部变量或者调用方法,但不能定义方法。在jsp页面可以有多个脚本片段,但是多个脚本片段之间要保证结构完整。

4.<%!%>声明

其中写的内容将来会直接翻译在Servlet类中,因为我们可以在类中定义方法和属性以及全局变量,所以我们可以在<%!%>中声

明方法、属性、全局变量。

5.<%=%>称作jsp表达式,用于将已经声明的变量或者表达式输出到网页上面。

  • PageContext 存东西

  • Request 存东西

  • esponse

  • Session 存东西

  • Application 【SerlvetContext】存东西

  • config【serlvetConfig】

  • out

  • page

  • exception

    <% pageContext.setAttribute("name1", "秦疆1号");//保存的数据只在一个页面中有效 request.setAttribute("name2", "秦疆2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据 //跨页面 session.setAttribute("name3", "秦疆3号");//保存的数据只在一次会话中有效,打开到关闭浏览器 application.setAttribute("name4", "秦疆4号");//保存的数据只在服务器有效,从打开到关闭服务器 %>

作用域:

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

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

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

  1. EL表达式:${}
  • 获取数据
  • 执行运算
  • 获取Web开发的常用对象
  1. JSP标签

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

转发携带参数

<%--
http: //localhost:8e80/jsptag.jsp?name=kuangshen&age=12
--%>

<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="kuangshen"></jsp:param>
    <jsp: param name="age" value="12"></jsp:param>
</jsp:forward>

取到参数

<%--取出参数--%>
名字:<%=request.getParameter( name: "name")%>年龄:<%=request.getParameter("age")%>
  1. JSTL表达式

JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和ava代码一样!

JSTL标签库使用步骤:

  • 引入对应的taglib

  • 使用其中的方法

  • 在Tomcat也需要引入jstl的包,否则会报错:JSTL解析错误

    if测试


    <%-- EL表达式获取表单中的数据 ${param.参数名} --%>

    <%--判晰断如果提交的用户名是管理员,则登录成功--%>

    <%--自闭he--%>

实体类

JavaBean有特定的写法:

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法;

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

ORM:对象关系映射

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

6、MVC三层架构

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

用户直接访问控制层,控制器直接操作数据库

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理DBc、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!

Model

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

View展示数据

  • 提供链接发起Servlet请求(a,form,img…)

controller (Servlet)

  • 接收用户的请求: (req:请求参数、Session信息….)

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

  • 控制视图的跳转

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

  • 解决中文乱码

  • 登陆验证

JAVA代码:实现接口、重写方法

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

public class CharacterEncodingFilter implements Filter {
    //初始化:web服务器启动就开始初始化,随时等待更新过滤对象
    public void init(FilterConfig config) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    //销毁:服务器关闭
    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }

    @Override
    //Chain: 链
    /*
    1.过滤器中的所有代码,在过滤特定请求的时候都会执行
    2.必须让过滤器继续同行
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");

        System.out.println("CharacterEncodingFilter执行前");
        chain.doFilter(request, response);//让程序继续走
        System.out.println("CharacterEncodingFilter执行后");
    }
}

xml中配置过滤器代码

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.Aaron.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>ShowServlet</servlet-name>
        <servlet-class>com.Aaron.servlet.ShowServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/show</url-pattern>
    </servlet-mapping>

实现一个监听器的接口;(有N种)

1.编写一个监听器

实现监听器的接口

//监听网站人数
public class onlineListener implements  HttpSessionListener{
@Override
    public void sessionCreated(HttpSessionEvent se) {
        /* Session is created. */
        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
    public void sessionDestroyed(HttpSessionEvent se) {
        /* Session is destroyed. */
        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.手动销毁 getSession().invalidate();
        2.自动销毁
         */

    }
}

2.web.xml中注册监听器

    <listener>
        <listener-class>com.Aaron.OnlineListener.onlineListener</listener-class>
    </listener>

监听器:GUI编程中经常使用;

package com.Aaron;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-05 12:45
 **/
public class TestPanel {
    public static void main(String[] args) {
        Frame frame = new Frame("管理");
        Panel panel = new Panel(null);
        frame.setLayout(null);

        frame.setBounds(500, 300, 500, 700);
        frame.setBackground(new Color(0, 0, 255));

        panel.setBounds(50, 50, 200, 100);
        panel.setBackground(new Color(0, 255, 0));

        frame.add(panel);
        frame.setVisible(true);

        //监听事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
                System.exit(0);
            }
        });
    }
}

用户登录后进入,注销后不能进入主页,过滤器实现

  1. 用户登录之后,向Sesison中放入用户的数据

  2. 进入主页的时候要判断用户是否已经登录;要求:在过滤器中实现!

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;
    
    if(request.getSession().getAttribute(constant.USER_SESSION) == null){
        response.sendRedirect("/error.jsp");
    }
    
    chain.doFilter(req, resp);
    }

7、JDBC

        <!--连接数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>

1.加载驱动

2.连接数据库,代表数据库

3.向数据库发送SQL的对象Statement : CRUD

4.编写SQL(根据业务,不同的SQL)

5.执行SQL

6.关闭连接

package com.Aaron.test;

import java.sql.*;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-05 16:32
 **/
public class TestJDBC {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.向数据库发送SQL的对象Statement
        Statement statement = connection.createStatement();

        //4.编写SQL
        try {
            String sql = "select * from users";

            //5.执行查询操作,返回一个结果集
            ResultSet rs = statement.executeQuery(sql);
            while (rs.next()) {
                System.out.println("id=" + rs.getInt("id"));
                System.out.println("name=" + rs.getString("name"));
                System.out.println("password=" + rs.getString("password"));
                System.out.println("birthday=" + rs.getString("birthday"));
            }
            //6.关闭连接,释放资源*  先开后关
            rs.close();
            statement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

预编译代码

package com.Aaron.test;

import java.sql.*;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-05 17:06
 **/
public class TestJDBC2 {
    public static void main(String[] args) throws Exception {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.编写SQL
        try {
            String sql = "insert into users(id,name,password,email,birthday)values (?,?,?,?,?);";

            //4.预编译
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            preparedStatement.setInt(1, 5);
            preparedStatement.setString(2, "小菜");
            preparedStatement.setString(3, "123");
            preparedStatement.setString(4, "2694247423@qq.com");
            preparedStatement.setString(5, "2001-03-17");

            //5.执行SQL

            int i = preparedStatement.executeUpdate();
            if (i > 0) {
                System.out.println("插入成功");
            }

            //6.关闭连接,释放资源*  先开后关
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

要么都成功,要么都失败!

ACID原则:保证数据的安全。

开启事务
事务提交 commit()
事务回滚 ro11back()
关闭事务

转账:
A :1000
B :1000

 A(900)--100-->B(1100)

junit单元测试

依赖

<!--单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

简单使用

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行

package com.Aaron.test;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-05 17:35
 **/
public class TestJDBC3 {

    @Test
    public void hello() {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
        String username = "root";
        String password = "root";

        Connection connection = null;
        //1.加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            //2.连接数据库
            connection = DriverManager.getConnection(url, username, password);

            //3.通知数据库开启事务,false开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money - 100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();

            //制造错误
//            int i = 1 / 0;

            String sql1 = "update account set money = money + 100 where name = 'B'";
            connection.prepareStatement(sql1).executeUpdate();

            connection.commit();
            System.out.println("success");

        } catch (Exception e) {
            try {
                //如果异常数据库回滚事务
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}


 <!--注册服务器name =  "HelloServet"-->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.Aaron.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径 urlPatterns = "/Aason",loadOnStartup = 15-->
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/Aaron</url-pattern>
    </servlet-mapping>



<?xml version="1.0" encoding="UTF-8"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<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">

</web-app>

   pom依赖
         <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>

如果启动Tomcat后文件运行正常,但是单独运行文件JSP显示代码,那么就是xml文件配置了Servlet,可以在Java文件中单独写头部。如下图

  1. 一个Servlet可以指定一个映射路径

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron</url-pattern>
        </servlet-mapping>
  2. 一个Servlet可以指定多个个映射路径

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron</url-pattern>
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron1&lt;/url-pattern&gt;
    
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron2&lt;/url-pattern&gt;
    
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron3&lt;/url-pattern&gt;
    
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron4&lt;/url-pattern&gt;
    
        &lt;servlet-name&gt;HelloServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/Aaron5&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;</code></pre></li>
  3. 一个Servlet可以指定通用映射路径(/*权限很高)

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>/Aaron/*</url-pattern>权限很高
        </servlet-mapping>
  4. 默认请求路径路径


    HelloServlet
    /*

  5. 指定一些前后缀

        <servlet-mapping>
            <servlet-name>HelloServlet</servlet-name>
            <url-pattern>*.Aaron</url-pattern>  <!-- 可以自定义后缀请求映射,但是前面*不可加/ -->
        </servlet-mapping>
  6. 优先级问题

    指定了固有的映射路径优先级最高,如果找不到就会走默认的请求;

    <!--Error错误服务器注册-->
    <servlet>
        <servlet-name>ErrorServlet</servlet-name>
        <servlet-class>com.Aaron.servlet.ErrorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ErrorServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

2、 ServletContext

2.3.1 共享数据

​ web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web容器;

  • 共享数据,保存数据,达到共享;

2.3.2 setAttribute转发

测试访问结果,先访问set ,获取值后在访问get,强转换String

​ String username = (String)context.getAttribute("username");

package com.Aaron.servlet; /**
 * @Author: Alskaboo
 * @Date: 2022-03-29 19:40
 **/

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

//@WebServlet(name = "HelloServlet", value = "/HelloServlet")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//        this.getInitParameter();初始化值
//        this.getServletConfig();servlet配置
//        this.getServletContext();servlet上下文衔接对象
        ServletContext context = this.getServletContext();

        String username = "菜菜";//数据
        context.setAttribute("username", username);//键值对的形式,将数据保存在了ServletContext中,名字叫username;与后面的key名必须相同
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

package com.Aaron.servlet;

import sun.security.timestamp.HttpTimestamper;

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

/**
 * @Author: Alskaboo
 * @Date: 2022-03-29 21:13
 **/

public class getServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String)context.getAttribute("username");

        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().print("名字"+username);

    }

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

    }
}



<?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">
    <!--注册服务器name =  "HelloServet"-->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.Aaron.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径 urlPatterns = "/Aason",loadOnStartup = 15-->
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/Aaron</url-pattern>
    </servlet-mapping>

    <!--Error错误服务器注册-->
    <servlet>
        <servlet-name>getc</servlet-name>
        <servlet-class>com.Aaron.servlet.getServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getc</servlet-name>
        <url-pattern>/getc</url-pattern>
    </servlet-mapping>
</web-app>

2.3.3 请求转发

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        context.getRequestDispatcher("/Demo_02").forward(req,resp);//请求转发的路径并且调用forward实现请求转发
    }

重定向:A找B要东西,B没有,但是B告诉A,C那里有你需要的,那么A直接根据路径找C(路径改变);

2.3.4 读取资源文件

properties类:

生成在classpath路径中

    <!--在build中配置resources,来防止我们资源导出失败的问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

3、 HttpServletResponse

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

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要给客户端响应一些信息:找HttpservletResponse

2.4.1. 简单分类

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

servletoutputstream getoutputstream() throws IOException;
Printwriter getwriter() throws IOException;

Http相应

Cache-Control: private    缓存控制
Connection:Keep-Alive     连接
Content-Encoding:gzip     编码
Content-Type:text/html    类型

2.4.2 文件下载

  1. 向浏览器输出消息

  2. 下载文件

    package com.Aaron;

    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.URLEncoder;

    /**

    • @Author: Alskaboo

    • @Date: 2022-03-30 17:39
      **/
      public class FileServelet extends HttpServlet {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //1. 要获取下载文件的路径,realpath是用来将参数path所指的相对路径转换成绝对路径,然后存于参数resolved_path所指的字符串数组或指针中的一个函数
      // String realPath = this.getServletContext().getRealPath("/ycCity.jpg");
      String realPath = "F:\Code\ideacode\JavaClassWeb\Maven02\response_01\src\main\resources\ycCity.jpg";
      System.out.println("下载文件路径:" + realPath);
      //2. 下载的文件名是啥?
      String fielname = realPath.substring(realPath.lastIndexOf("\") + 1);//直接截取字符串,截取最后一个"/"的下一个就是那个文件名
      //3. 设置想办法让浏览器能够支持下载我们需要的东西
      resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fielname,"UTF-8"));
      //4. 获取下载文件的输入流
      FileInputStream fileInputStream = new FileInputStream(realPath);
      //5. 创建缓冲区
      int len = 0;
      byte[] buffer = new byte[1024];
      //6. 获取OutputStream对象
      ServletOutputStream outputStream = resp.getOutputStream();
      //7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
      while ((len = fileInputStream.read(buffer)) != -1) {
      outputStream.write(buffer, 0, len);
      }
      //8.关闭流
      fileInputStream.close();
      outputStream.close();

      }

      filedown com.Aaron.FileServelet
      filedown /filedown

2.4.3 验证码功能

  1. 验证怎么来的?

    • 前端实现

    • 后端实现,需要用到Java的图片类,生产一个图片

    package com.Aaron;

    import javax.imageio.ImageIO;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;

    /**

    • @Author: Alskaboo

    • @Date: 2022-03-30 22:06
      **/
      public class ImageServlet extends HttpServlet {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //如何让浏览器5秒自动刷新一次
      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, 20);
      //给图片写数据
      graphics.setColor(Color.RED);
      graphics.setFont(new Font(null, Font.BOLD, 20));//BOLD粗体
      graphics.drawString(setRandom(), 0, 20);
      //告诉浏览器这个请求用图片的形式打开
      resp.setContentType("image/jpg");
      //网站是有缓存的,不让浏览器缓存
      resp.setDateHeader("expires", -1);
      resp.setHeader("Cache-Control", "no-Cache");
      resp.setHeader("Pragma", "no-Cache");
      //把图片写给浏览器
      boolean write = ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());

      }

      //生成随机数
      private String setRandom() {
      Random random = new Random();
      String num = random.nextInt(999_9999) + " ";
      StringBuffer stringBuffer = new StringBuffer();//StringBuffer 字符串拼接
      for (int i = 0; i < 7 - num.length(); i++) {
      stringBuffer.append("0");//保证输出七位数,不足用0填充
      }
      String s = stringBuffer.toString() + num;
      return num;
      }

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

      ImageServlet com.Aaron.ImageServlet
      ImageServlet /img

2.4.4 重定向

定义:B一个web资源收到客户端A请求后,B他会通知A客户端去访问另外一个web资源,这个过程叫重定向

常见场景:

  • 用户登录

测试

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
        resp.setHeader("Location","/response/img");
        resp.setStatus(302);
         */

        resp.sendRedirect("/response/img");
    }

面试题

重定向和转发的区别:

相同点:

  • 页面都会跳转

不同点:

  • 请求转发的时候,URL不会发生变化

  • 重定向的时候,URL会发生变化

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入这个请求了");
        //处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
    //重定向一定要注意路径问题
    resp.sendRedirect("/response/LoginSuccess.jsp");
    }

    <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>

    主页

    Login Success!


    <servlet>
        <servlet-name>RequestText</servlet-name>
        <servlet-class>com.Aaron.send.RequestTest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestText</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

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

2.5.1 获取前端的参数,并且请求转发

 @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //后台接收乱码问题
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String[] hobbies = request.getParameterValues("hobbies");

        //打出
        System.out.println(username);
        System.out.println(password);
        System.out.println(Arrays.toString(hobbies));

        //请求转发
        request.getRequestDispatcher("success.jsp").forward(request, response);

    }

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

面试题

重定向和转发的区别:

相同点:

  • 页面都会跳转

不同点:

  • 请求转发的时候,URL不会发生变化;307
  • 重定向的时候,URL会发生变化;302

4、 Cookie和Session(重点)

1、Cookie

  1. 从服务器请求中拿到Cookie信息
  2. 服务器相应给客户端cookie

1、cookie会话

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话

有状态会话:访问网站,下次访问有记录的情况

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

客户端 服务端

  1. 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了; cookie
  2. 服务器登记你来过了,下次你来的时候我来匹配你;session

2、保存会话的两种技术

cookie

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

session

  • 服务器技术,利用这个技术,可以保存会话的信息,我们把它保存到Session中

    //Cookie,服务器端从客户端获取呀;
    Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个
    cookie.getName();//获得cookie
    cookie.getValue();//获得cookie中的Value
    Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");//新建一个cookie
    cookie.setMaxAge(24 * 62 * 60); //cookie有效期
    resp.addCookie(cookie);//响应给客户端一个cookie

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

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

删除Cookie:

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

解决cookie乱码

编码解码

Cookie cookie = new Cookie("name", URLEncoder.encode("秦疆", "UTF-8"));
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));

相关源码

package com.Aaron.Servlet;

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

import static java.lang.System.out;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-01 19:35
 **/
//保存 用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //服务器告诉你,你来的时间,把这个这个时间封装,下次你来带来我就知道你来了
        //解决中文乱码
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=UTF-8");

        PrintWriter out = resp.getWriter();
        //Cookie,服务器端从客户端获取呀;
        Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个
        //判断Cookie是否存在
        if (cookies != null) {
            //如果存在怎么办
            out.write("您上一次访问本站的时间是:");
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                //获取cookie的名字
                if (cookie.getName().equals("lastLoginTime")) {
                    //获取cookie中的值
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastLoginTime);
                    out.write(date.toLocaleString());
                }
            }
        } else {
            out.write("这是您第一次访问本站");
        }
        //服务给客户端响应一个cookie;
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
        //cookie有效期为一天
        cookie.setMaxAge(24 * 62 * 60);
        resp.addCookie(cookie);
    }

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



package com.Aaron.Servlet;

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

/**
 * @Author: Alskaboo
 * @Date: 2022-04-01 21:01
 **/
public class CookieDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建和刚才的cookie名字一样
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
        cookie.setMaxAge(0);
        resp.addCookie(cookie);
    }

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



<?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>CookieDemo01</servlet-name>
        <servlet-class>com.Aaron.Servlet.CookieDemo01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieDemo01</servlet-name>
        <url-pattern>/c1</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>CookieDemo02</servlet-name>
        <servlet-class>com.Aaron.Servlet.CookieDemo02</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieDemo02</servlet-name>
        <url-pattern>/c2</url-pattern>
    </servlet-mapping>
</web-app>

2、Session(重点)含销毁时间

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话

什么是session:

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

使用场景:

  • 保存一个登录用户的信息
  • 购物车信息
  • 整个网站中经常使用的信息

相关代码:

//得到Session
HttpSession session = req.getSession();

//给Session存东西
Person person = new Person("秦疆",10);
session.setAttribute("name", person);



//得到Session
HttpSession session = req.getSession();

//给Session存东西
Person name = (Person) session.getAttribute("name");
System.out.println(name);


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

    }

会话关闭web配置文件

    <!--设置Session默认的失效时间-->
    <session-config>
        <!--设置Session失效时间,以分钟为单位 24*60-->
        <session-timeout>1440</session-timeout>
    </session-config>
  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
  • Session对象由服务创建;

5、JSP

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

最大的特点:写JSP就像在写HTML

HTML和JSP最大的区别:

  • HTML只给用户静态的
  • JSP页面中可以嵌入java代码,为用户提供动态数据

思路:JSP怎么运行?

  • 代码层面没有问题

  • 服务器内部工作

    Tomcat中的work目录

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

JSP最终也会被转换成JAVA类

JSP本质上就是一个Servlet

在JSP中:

只要是Java代码就会原封不动的输出;

如果是HTML代码,就会被转换

out.write("<html>\r\n");

这样的格式输出到前端。

任何语言都有自己的语法,JSP作为java技术的一种应用,它拥有一些自己扩充的语法(了解),Java所有语法都支持

JSP表达式

<%--JSP表达式
作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式 %>
--%>
  <%= new java.util.Date()%>

jsp脚本片段

<%--脚本片段--%>
<%
    int sum = 0;
  for (int i = 0; i <= 100; i++) {
    sum += i;
  }
    out.println("<h1>Sum=" + sum + "</h1>");
%>

<%
    for (int i = 0; i < 5; i++) {
%>
<h2>Hello,World! <%=i%>//${i}
</h2>
<%
    }
%>

JSP指令

1.错误页面

<%@ page errorPage= "路径" %>

或者单独创建图片

<img src="路径" alt="500">

或者配置文件

<error-page>
<error-code>404</error-code>
<location> /error/404.jsp</ location></error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>

网站主体:拼接页面

jsp注释

1.隐藏注释

下面介绍一种隐藏注释,注释格式如下:

<%--注释内容--%>

2.HTML中的注释

JSP 文件是由 HTML 标记和嵌入的 Java 程序段组成的,所以在 HTML 中的注释同样可以在 JSP 文件中使用。这种注释虽然在客户端浏览页面时不会看见,但它却存在于源代码中,可通过在客户端查看源代码看到被注释的内容。所以严格来说,这种注释并不安全。注释格式如下:

<!--注释内容-->

3.<% %>脚本片段

其中写的内容会翻译在Servlet的Service方法中,显然我们可以在Service方法中定义局部变量或者调用其他方法,但是不能

在Service中再定义其他的方法,也就是我们可以在<%%>中定义局部变量或者调用方法,但不能定义方法。在jsp页面可以有多个脚本片段,但是多个脚本片段之间要保证结构完整。

4.<%!%>声明

其中写的内容将来会直接翻译在Servlet类中,因为我们可以在类中定义方法和属性以及全局变量,所以我们可以在<%!%>中声

明方法、属性、全局变量。

5.<%=%>称作jsp表达式,用于将已经声明的变量或者表达式输出到网页上面。

  • PageContext 存东西

  • Request 存东西

  • esponse

  • Session 存东西

  • Application 【SerlvetContext】存东西

  • config【serlvetConfig】

  • out

  • page

  • exception

    <% pageContext.setAttribute("name1", "秦疆1号");//保存的数据只在一个页面中有效 request.setAttribute("name2", "秦疆2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据 //跨页面 session.setAttribute("name3", "秦疆3号");//保存的数据只在一次会话中有效,打开到关闭浏览器 application.setAttribute("name4", "秦疆4号");//保存的数据只在服务器有效,从打开到关闭服务器 %>

作用域:

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

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

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

  1. EL表达式:${}
  • 获取数据
  • 执行运算
  • 获取Web开发的常用对象
  1. JSP标签

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

转发携带参数

<%--
http: //localhost:8e80/jsptag.jsp?name=kuangshen&age=12
--%>

<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="kuangshen"></jsp:param>
    <jsp: param name="age" value="12"></jsp:param>
</jsp:forward>

取到参数

<%--取出参数--%>
名字:<%=request.getParameter( name: "name")%>年龄:<%=request.getParameter("age")%>
  1. JSTL表达式

JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和ava代码一样!

JSTL标签库使用步骤:

  • 引入对应的taglib

  • 使用其中的方法

  • 在Tomcat也需要引入jstl的包,否则会报错:JSTL解析错误

    if测试


    <%-- EL表达式获取表单中的数据 ${param.参数名} --%>

    <%--判晰断如果提交的用户名是管理员,则登录成功--%>

    <%--自闭he--%>

实体类

JavaBean有特定的写法:

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法;

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

ORM:对象关系映射

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

6、MVC三层架构

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

用户直接访问控制层,控制器直接操作数据库

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理DBc、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!

Model

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

View展示数据

  • 提供链接发起Servlet请求(a,form,img…)

controller (Servlet)

  • 接收用户的请求: (req:请求参数、Session信息….)

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

  • 控制视图的跳转

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

  • 解决中文乱码

  • 登陆验证

JAVA代码:实现接口、重写方法

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

public class CharacterEncodingFilter implements Filter {
    //初始化:web服务器启动就开始初始化,随时等待更新过滤对象
    public void init(FilterConfig config) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    //销毁:服务器关闭
    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }

    @Override
    //Chain: 链
    /*
    1.过滤器中的所有代码,在过滤特定请求的时候都会执行
    2.必须让过滤器继续同行
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");

        System.out.println("CharacterEncodingFilter执行前");
        chain.doFilter(request, response);//让程序继续走
        System.out.println("CharacterEncodingFilter执行后");
    }
}

xml中配置过滤器代码

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.Aaron.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>ShowServlet</servlet-name>
        <servlet-class>com.Aaron.servlet.ShowServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/show</url-pattern>
    </servlet-mapping>

实现一个监听器的接口;(有N种)

1.编写一个监听器

实现监听器的接口

//监听网站人数
public class onlineListener implements  HttpSessionListener{
@Override
    public void sessionCreated(HttpSessionEvent se) {
        /* Session is created. */
        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
    public void sessionDestroyed(HttpSessionEvent se) {
        /* Session is destroyed. */
        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.手动销毁 getSession().invalidate();
        2.自动销毁
         */

    }
}

2.web.xml中注册监听器

    <listener>
        <listener-class>com.Aaron.OnlineListener.onlineListener</listener-class>
    </listener>

监听器:GUI编程中经常使用;

package com.Aaron;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-05 12:45
 **/
public class TestPanel {
    public static void main(String[] args) {
        Frame frame = new Frame("管理");
        Panel panel = new Panel(null);
        frame.setLayout(null);

        frame.setBounds(500, 300, 500, 700);
        frame.setBackground(new Color(0, 0, 255));

        panel.setBounds(50, 50, 200, 100);
        panel.setBackground(new Color(0, 255, 0));

        frame.add(panel);
        frame.setVisible(true);

        //监听事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
                System.exit(0);
            }
        });
    }
}

用户登录后进入,注销后不能进入主页,过滤器实现

  1. 用户登录之后,向Sesison中放入用户的数据

  2. 进入主页的时候要判断用户是否已经登录;要求:在过滤器中实现!

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;
    
    if(request.getSession().getAttribute(constant.USER_SESSION) == null){
        response.sendRedirect("/error.jsp");
    }
    
    chain.doFilter(req, resp);
    }

7、JDBC

        <!--连接数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>

1.加载驱动

2.连接数据库,代表数据库

3.向数据库发送SQL的对象Statement : CRUD

4.编写SQL(根据业务,不同的SQL)

5.执行SQL

6.关闭连接

package com.Aaron.test;

import java.sql.*;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-05 16:32
 **/
public class TestJDBC {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.向数据库发送SQL的对象Statement
        Statement statement = connection.createStatement();

        //4.编写SQL
        try {
            String sql = "select * from users";

            //5.执行查询操作,返回一个结果集
            ResultSet rs = statement.executeQuery(sql);
            while (rs.next()) {
                System.out.println("id=" + rs.getInt("id"));
                System.out.println("name=" + rs.getString("name"));
                System.out.println("password=" + rs.getString("password"));
                System.out.println("birthday=" + rs.getString("birthday"));
            }
            //6.关闭连接,释放资源*  先开后关
            rs.close();
            statement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

预编译代码

package com.Aaron.test;

import java.sql.*;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-05 17:06
 **/
public class TestJDBC2 {
    public static void main(String[] args) throws Exception {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
        String username = "root";
        String password = "root";

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.连接数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.编写SQL
        try {
            String sql = "insert into users(id,name,password,email,birthday)values (?,?,?,?,?);";

            //4.预编译
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            preparedStatement.setInt(1, 5);
            preparedStatement.setString(2, "小菜");
            preparedStatement.setString(3, "123");
            preparedStatement.setString(4, "2694247423@qq.com");
            preparedStatement.setString(5, "2001-03-17");

            //5.执行SQL

            int i = preparedStatement.executeUpdate();
            if (i > 0) {
                System.out.println("插入成功");
            }

            //6.关闭连接,释放资源*  先开后关
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

要么都成功,要么都失败!

ACID原则:保证数据的安全。

开启事务
事务提交 commit()
事务回滚 ro11back()
关闭事务

转账:
A :1000
B :1000

 A(900)--100-->B(1100)

junit单元测试

依赖

<!--单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

简单使用

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行

package com.Aaron.test;

import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * @Author: Alskaboo
 * @Date: 2022-04-05 17:35
 **/
public class TestJDBC3 {

    @Test
    public void hello() {
        //配置信息
        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
        String username = "root";
        String password = "root";

        Connection connection = null;
        //1.加载驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");

            //2.连接数据库
            connection = DriverManager.getConnection(url, username, password);

            //3.通知数据库开启事务,false开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money - 100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();

            //制造错误
//            int i = 1 / 0;

            String sql1 = "update account set money = money + 100 where name = 'B'";
            connection.prepareStatement(sql1).executeUpdate();

            connection.commit();
            System.out.println("success");

        } catch (Exception e) {
            try {
                //如果异常数据库回滚事务
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}