Skip to main content

javaweb

java web

1.基本概念

1.1 前言

​ web 开发

  • ​ web,网页的开发 www.baidu.com
  • 静态 web
    • html css
    • 提供给所有人看的数据始终不会发生变化!
  • 动态 web
    • 淘宝推荐,几乎所有的网站都是动态的
    • 提供给所有人的数据会发生变化,每个人不同时间,不同地点看到的信息各不相同
    • 技术栈:Servlet/jsp,ASP,PHP,

在 java 中动态的 web 资源开发技术统称为:javaweb;

1.2 web 应用程序

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

  • a.html.bhtml....等等多个 web 资源,此资源可以被外界访问,可以为外界服务;
  • 你们可以访问到的任何一个页面或者是资源,都存在与这个世界的某一个角落的计算机上
  • URL:通过这个来作为连接访问
  • 这个统一的 web 资源会被放在同一个文件夹下,web 应用程序-->tomcat:服务器
  • 一个 web 应用由多部分组成(静态 web,动态 web)
    • html,css,js
    • jsp,servlet
    • java
    • jar 包
    • 配置文件(Properties)

web 程序的应用程序编写完毕后,提供给外界访问,需要一个服务器来统一管理

1.3 静态 web

  • .htm.html 这些网页后缀,如果服务器存在这些东西,我们可以直接进行读取

请求与响应

  • 静态 web 存在缺点
    • web 页面无法动态更新,所有的用户都看到的是同一个页面
      • 轮播图,点击特效:伪动态
      • javaScript【实际开发中,用的最多】
      • VBscript【微软开发】
    • 它无法实现和数据库交互(数据无法持久化,用户无法交互)

1.4 页面动态展示

页面会动态的展示:web 的页面展示的效果因人而异,

动态web的结构

  • 缺点:加入服务器的动态 web 资源出现了错误,我们需要重新编写我们的后台程序,重新发布。
    • 以前的网站,停机维护就是如此

优点:

  • Web 页面可以动态更新,所有用户看到的都不是同一个页面
  • 可以和数据库交互(数据持久化,注册,信息可以得到保存)

2.web 服务器

2.1 服务端技术

ASP:

  • 微软:国内最早流星的是 ASP
  • 在 html 中嵌入 VB 的脚本,ASP+HTML
  • 在 ASP 开发中,基本一个页面,大量互相嵌套的业务逻辑代码,造成维护成本过高

PHP:

  • PHP 将开发速度很快,功能强大,跨平台,代码简单(70%,wp)
  • 无法承载大访问量的情况(局限性)

JSP/Servlet

B/S 浏览与服务器

C/S 客户端与服务器

  • sun 公司主推的 B/S 架构
  • 基于 java 语言的(所有大公司,或者一些开源的组件,都是用 java 写的)
  • 可以承载三高的问题带来的影响
  • 语法想 ASP-->JSP 加强市场强度

2.2web 服务器

作用:接收用户的请求给予相应的响应,是一种被动操做,用来处理用户请求给用户返回响应信息

lls

微软:ASP,,windows 中自带的

tomcat:

Tomcat 是 Apache 软件基金会(Apache Software Foundation)的 Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了 Sun 的参与和支持,最新的 Servlet 和 JSP 规范总是能在 Tomcat 中得到体现,Tomcat 5 支持最新的 Servlet 2.4 和 JSP 2.0 规范。因为 Tomcat 技术先进、性能稳定,而且免费,因而深受 Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的 Web 应用服务器。

Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试 JSP 程序的首选。对于一个 java 初学 web 来说,

诀窍是,当配置正确时,Apache 为 HTML 页面服务,而 Tomcat 实际上运行 JSP 页面和 Servlet。另外,Tomcat 和IIS等 Web 服务器一样,具有处理 HTML 页面的功能,另外它还是一个 Servlet 和 JSP 容器,独立的 Servlet 容器是 Tomcat 的默认模式。不过,Tomcat 处理静态HTML的能力不如 Apache 服务器。目前 Tomcat 最新版本为 10**。**

工作 3-5 年可以尝试手写 tomcat 服务器

下载 tomcat:

  1. 安装 and 解压
  2. 了解配置文件以及目录结构
  3. 这个东西的作用

3,tomcat

3.1 安装 tomcat

tomcat官网01

下载 windows 64 安装包

解读 tomcat 的文件目录

image-20210323154638539

3.2 启动,关闭 tomcat

tomcat启动与关闭

访问测试 url:

http://localhost:8080/

3.3 配置

核心文件:

image-20210323155113249

可能遇到的问题:

​ 1.java 环境变量没有配置

​ 2.闪退问题,需要配置兼容性

​ 3.乱码问题要去配置文件设置

可以配置启动的端口号

  • tomcat 的默认端口号为:8080
  • mysql:3306
  • http:80
  • https:443
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

可以配置主机名称

  • 默认的主机名为 localhost=>127.0.0.1
  • 默认网站应用存放位置为:webapps
      <Host name="localhost"  appBase="webapps"
unpackWARs="true" autoDeploy="true">

高难度面试题

请你谈谈网站是如何进行访问的!

  1. 输入一个域名:回车

  2. 检查本机的 C:\Windows\System32\drivers\etc\hosts 配置文件下有没有这个域名的映射

    1. 有:直接返回对应的 ip 地址,这个地址中有我们访问的 web 程序,可以直接访问

      127.0.0.1 www.qingjiang.com
    2. 没有:上 dns 服务器上找,找到的话就返回,没有的话返回你的网页走丢了

高分面试网站访问

3.tomcat 文档本地地址 http://localhost:8080/examples/

3.4 发布 web 网站

  • 先写网站放到 tomcat/webapps/,服务器中指定的 web 应用文件夹下,就可以访问了

网站该有的结构

--webapps:tomcat服务器的web目录
-root
-项目名: 网站的目录名
-web-inf
-web.xml
-classes:java
-lib:web应用所依赖的jar包
-index.html
-static
css
style
js
img

HTTP 协议:面试

Maven:构建工具

  • Maven 安装包

Servlet

  • helloword
  • Servlet
  • 原理

4.http

4.1 什么是 http

Http 超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当。

  • 文本:html,字符串等等
  • 超文本:图片,音乐,视频,定位,地图
  • 端口号:80

Https:安全的

  • 端口 443

4.2 两个时代

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

4.3http 请求

  • 客户端---》发送请求(Requset)---》服务器

百度:

Request URL: https://www.baidu.com/ //请求地址
Request Method: GET get方法/post方法
Status Code: 200 OK 状态码:200
Remote Address: 163.177.151.110:443 地址加端口
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9 语言
Cache-Control: max-age=0
Connection: keep-alive

1.请求行

  • 请求行中的请求方式:get/post
  • 请求方式: Get/post, HEAD,DELETE,put tract
    • get:请求能够携带的参数比较小,大小被限制,会在浏览器的 url 地址栏显示数据内容,不安全,但高效。
    • post:请求能够携带的参数没有限制,没有大小限制,不会在浏览器的 URL 地址栏显示数据内容,安全但不高效

2.消息头

Accept 告诉浏览器,它所支持的数据类型
Accept-Encoding 支持那种编码格式 gbk,utf-8,gb2312,iso8859-1(java默认编码)
Accept-Language 语言
Cache-Control 缓存控制
Connection 告诉浏览器请求完成是断开还是保持连接
HOST:主机

4.4HTTP 响应

  • 服务器---》响应---》客户端

百度:

Cache-Control: private 		缓存控制
Connection: keep-alive 连接:保持连接
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 类型

1.响应体

Accept 告诉浏览器,它所支持的数据类型
Accept-Encoding 支持那种编码格式 gbk,utf-8,gb2312,iso8859-1(java默认编码)
Accept-Language 语言
Cache-Control 缓存控制
Connection 告诉浏览器请求完成是断开还是保持连接
HOST:主机
Refresh:告诉客户端,多久刷新一次
Location:让网页重新定位

2.响应状态码(重点)

200:请求响应成功

3xx:请求重定向

  • 重定向:你重新到我给你的新位置去

4xx:找不到资源:404

  • 资源不存在:

5xx:服务器代码错误 500 502:网关错误

常见面试题:

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

5.Maven

我为什么要学习这个基数

  1. 在 javaweb 开发中,需要使用大量的 jar 包,我们需要去手动去导入 jar 包

  2. 如何能够让一个东西自动帮我们导入和配置这些 jar 包

    由此,Maven 诞生了!

5.1Maven 项目架构管理工具

我们目前用它来方便导入 jar 包

Maven 核心思想:约定大于配置

  • 有约束,不要去违反

Maven 会规定好你该如何去编写 java 代码,目录结构必须要按照这个规范来

5.2 下载安装 Maven

官网网址:https://maven.apache.org/download.cgi

下载完成后解压即可:

建议:电脑上的所有环境都放在一个文件夹下方便管理

5.3 配置环境变量

在系统环境变量之中

配置如下:

  • M2_HOME maven 目录下的 bin 目录
  • MAVEN_HOME maven 的目录
  • 在系统的 path 中配置 MAVEN_HOME 目录 %MAVEN_HOME%\bin

5.4 阿里云镜像

  • 镜像:mirrors
    • 作用:加速下载
  • 建议使用阿里云
2      <mirror>
3 <id>nexus-aliyun</id>
4 <mirrorOf>*</mirrorOf>
5 <name>Nexus aliyun</name>
6 <url>http://maven.aliyun.com/nexus/content/groups/public</url>
7 </mirror>

5.5 本地仓库 repository

本地仓库,远程仓库

建立一个本地仓库:

  <localRepository>D:\apache-maven-3.6.3\maven-repo</localRepository>

5.6 在 idea 使用 maven

  1. 启动 idea

  2. 创建一个 maven 项目

    maven仓库

  3. 等待项目初始化完毕

maven环境搭建成功

4.观察 maven 仓库多了什么东西

5.idea 中 maven 设置

​ 注意:IDEA 创建成功后看一眼 maven 的配置,

注意事项查看maven设置

image-20210329142738908

6.到这,maven 在 IDEA 的配置和使用就 ok 了

5.7 创建一个普通的 maven 项目

5.7

干净的MAVEN

maven资源测试目录

maven项目文件解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZfdyIk91-1648909270901)(C:\Users\doomwstcher\AppData\Roaming\Typora\typora-user-images\image-20210329144558685.png)]

5.9 在 idea 配置 tomcat

配置tomcat

解决警告问题

必须配置,为什么会有问题,我们访问一个网站,需要指定一个文件夹的名字;

image-20210329145158985

image-20210329145423702

image-20210329145827852

5.10pom 文件

pom.xml 是 Maven 的核心配置文件

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--创建项目的时候生成的配置gav-->
<groupId>com.hyc</groupId>
<artifactId>javaweb01-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<name>javaweb01-maven Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- 项目依赖文件-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

<!--项目构建文件-->
<build>
<finalName>javaweb01-maven</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

image-20210329152132457

maven 由于约定大于配置,会出现我们之后遇到写的配置文件无法被导出或者生效的问题,

解决方案:

<!-- 配置resouce来防止我们导出失败的问题-->
<build>

<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>

</build>

6.Servlet

6.1 什么是 Servlet

  • sun 公司开发动态 web 的一门技术

  • sun 公司在 api 中提供了一个借口叫 Servlet,你想开发 Servlet 程序。只需要两个小步骤

    • 编写一个类,实现 Servlet 接口
    • 把开发好的 java 类部署到 web 服务器中

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

6.2 HelloServlet

Servlet 接口有两个默认的实现类:httpServlet,GenericServlet

  1. 构建一个普通的 maven 项目,删掉里面的 src 目录,以后我们的学习就在这里面建立 moudel;这个空的工程就是 maven 的主工程

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

    1. 父项目中会有:

          <modules>
      <module>Servlet-01</module>
      </modules>

      子项目中会有:

        <parent>
    <artifactId>javaweb-maven-02</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    </parent>
  3. Maven 环境优化

    1. 修改 web.xml 为最新的
    2. 将 Maven 的结构搭建完整
  4. 编写一个 Servlet 程序

    1. 编写一个普通类

    2. 继承接口实现类

      package com.hyc.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.print("Hello,servlet");


      }

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

  5. 编写 Servlet 的映射

    为什么需要映射呢,我们写的是 java 程序,通过浏览器访问,而浏览器需要连接 web 服务器,所以我们需要在 web 服务中出册我们写的 Servlet,还需要给他一个浏览器访问的 url

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <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_3_1.xsd"
    version="3.1"
    metadata-complete="true">

    <display-name>Welcome to Tomcat</display-name>
    <description>
    Welcome to Tomcat
    </description>

    <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.hyc.servlet.helloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    </web-app>

  6. 配置 tomcat

    配置项目发布路径

  7. 启动测试

6.3servlet 原理

Servlet 是由 web 服务器调用,web 服务器在收到浏览器请求之后会:

image-20210407102137906

6.4Mapping

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

      <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.hyc.servlet.helloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
  2. 一个 sevlet 可以指定多个映射路径

      <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.hyc.servlet.helloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
  3. 一个 sevlet 可以指定默认映射路径(尽量不要去写)

      <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/*</url-pattern>
    </servlet-mapping>
  4. 一个 sevlet 可以指定前缀或者是后缀映射路径

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

6.5 优先级问题

指定了固有映射路径的优先级最高,如果找不到怎么办那么就会进行默认的

<!--404-->
<servlet>
<servlet-name>err</servlet-name>
<servlet-class>com.hyc.servlet.errServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>err</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

6.6ServletContext

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

1.共享数据

在一个 servlet 的数据可以从另一个 servlet 拿到

  • 共享数据

    我在这个 servlet 中保存的数据,可以在另外一个 servlet 中拿到

    package com.hyc.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 {

    resp.setContentType("text/html");
    resp.setCharacterEncoding("utf-8");
    ServletContext context = this.getServletContext();
    String name =(String)context.getAttribute("username");
    resp.getWriter().print(name);


    }
    }

    package com.hyc.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 {
    System.out.println("HELLO");
    ServletContext Context = getServletContext();
    String username = "胡宇辰";
    Context.setAttribute("username",username);
    }
    }

    <?xml version="1.0" encoding="ISO-8859-1"?>

    <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_3_1.xsd"
    version="3.1"
    metadata-complete="true">

    <display-name>Welcome to Tomcat</display-name>
    <description>
    Welcome to Tomcat
    </description>
    <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.hyc.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hi</url-pattern>
    </servlet-mapping>

    <servlet>
    <servlet-name>get</servlet-name>
    <servlet-class>com.hyc.servlet.getServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>get</servlet-name>
    <url-pattern>/get</url-pattern>
    </servlet-mapping>
    </web-app>

    测试结果

2.获取初始化参数

设置初始化参数
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost/3306/mybaties</param-value>
</context-param>

读取参数
        resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext context = this.getServletContext();
String name =(String)context.getAttribute("username");
String url =(String)context.getInitParameter("url");

resp.getWriter().print( url );

3.请求转发

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/get").forward(req,resp);


}

image-20210409083815354

4.读取资源文件

properties

  • 在 java 目录下新建 properties 文件
  • 在 resouesce 目录下新建 properties 文件

发现都会打包到同一个路径下:classes,我们俗称这个路径为 classpath

思路:需要一个文件流

        resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext context = this.getServletContext();
InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String user = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().print(user+" "+pwd);
username=root
password = 123456

访问测试即 ok

6.6 HttpServletRequest

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

image-20210413085651840

image-20210413085723383

1.获取前端传递参数,并且请求转发

image-20210413085943348

  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("pwd");
String[] hobbys = req.getParameterValues("hobby");
System.out.println("====================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
System.out.println("====================");
req.getRequestDispatcher("/success.jsp").forward(req,resp);

}

请求转发和重定向的区别

6.7HttpServletResponse

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

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

1.简单分类

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

    ServletOutputStream getOutputStream() throws IOException;

PrintWriter getWriter() throws IOException;

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

    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);

void addIntHeader(String var1, int var2);

响应状态码

    int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
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;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

2,常见应用

  1. 向浏览器输出消息

  2. 下载文件,上传文件

    1. 要获取下载文件的路径
    2. 下载的文件名是什么?
    3. 设置让浏览器支持下载我需要的文件
    4. 获取下载文件的输入流
    5. 创建缓冲区
    6. 获取 outinputstream 对象
    7. 将 fileoutinputstream 写入 buffer 缓冲区
    8. 使用 outinputstream 将缓冲区中的数据输出到客户端
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载文件的路径
String realPath ="D:\\javaweb-maven-02\\response\\target\\classes\\梦.jpg";
//2. 下载的文件名是什么?
System.out.println("下载文件路径"+realPath);
String Filename =realPath.substring(realPath.lastIndexOf("//")+1);
// 3. 设置让浏览器支持下载我需要的文件
resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(Filename,"UTF-8"));
//4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
//5. 创建缓冲区
int len = 0;
byte[] buffter = new byte[1024];
//6. 获取outinputstream对象
ServletOutputStream out = resp.getOutputStream();
//7. 将fileoutinputstream写入buffer缓冲区, 使用outinputstream将缓冲区中的数据输出到客户端
while ((len = in.read(buffter))>0){
out.write(buffter,0,len);
}
//关闭
in.close();
out.close();
}

3.验证码功能

验证码怎么来的

  • 前端实现
  • 后端实现,需要用到 java 的图片类来实现

4.实现重定向

image-20210413102934024

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

常见场景:

  • 用户登录
void sendRedirect(String var1) throws IOException;
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.setHeader("location","/r/img");
// resp.setStatus(resp.SC_MOVED_TEMPORARILY);
resp.sendRedirect("/r/img");
}

面试题:请你聊聊重定向和转发的区别?

相同点

  • 页面都会实现跳转

不同点

  • 请求转发的时候,url 不会产生变化
  • 重定向时候,url 地址栏会产生变化

image-20210413104110899

7.cookie,session

7.1 会话

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

**有状态会话:**一个同学来过教室,下次再来教师,我们会知道这个同学之前来过教师,称之为有状态会话

如何证明你是学生?

对象: 你 学校

  1. 发票 学校给你的发票
  2. 学校登记 学校标记你来过了

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

客户端 服务器

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

7.2 保存会话的两种技术

cookie

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

session

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

常见场景:网站登录之后你下次不用在登录了,第二次访问直接就上去了

7.3Cookie

  1. 从请求中拿到 cookie 信息,
  2. 服务器响应给客户端 cookie
Cookie[] cookies = req.getCookies();//返回数组说明cookie存在多个
cookie.getName()//获取cookie的名字
cookie.getValue()//获得cookie中的value
new Cookie()//设置cookie的有效期
cookie.setMaxAge(24*60*60);//设置有效期
resp.addCookie(cookie)//响应给客户端一个cookie

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

一个网站的 cookie 是否存在上线,细节问题

  • 一个 cookie 只能保存一个信息
  • 一个 web 站点可以给浏览器多个 cookie,最多存放 20 个 cookie
  • Cookie 的大小有限制
  • 300 个 cookie 浏览器上限

删除 cookie

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

编码解码:

URLDecoder.decode(cookie.getValue(),"utf-8")//解码
URLEncoder.encode("请将","utf-8")//编码

7.4session(重点)

什么是 session:

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

image-20210416083210571

<!--  设置session默认的失效时间-->
<session-config>
<!--15分钟后session自动失效-->
<session-timeout>15</session-timeout>
</session-config>

session 和 cookie 的区别:

  • Cookie 是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session 把用户的数据写到用户独占的 session 中,服务器端保存(保存重要的消息,减少服务器资源的浪费)
  • session 对象由服务器创建

使用场景:

  • 保存一个用户登陆的信息
  • 购物车信息;
  • 在整个网站中经常会使用的数据
//创建session
package com.hyc.servlet;

import com.hyc.pojo.persion;

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

public class sessionDemo 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");
HttpSession session = req.getSession();
session.setAttribute("name",new persion("hyc",12)) ;
String id = session.getId();
if (session.isNew()) {
resp.getWriter().write("session创建成功:"+ id);
}else {
resp.getWriter().write("session已经在服务器存在了:"+id);
}
//session的创建的时做了什么事情
Cookie cookie = new Cookie("JSESSIONID",id);
}

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

//拿到session
package com.hyc.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import com.hyc.pojo.persion;

public class sessionDemo02 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");
HttpSession session = req.getSession();
persion name = (persion) session.getAttribute("name");
System.out.println(name.toString());
}

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

//删除和注销session
package com.hyc.servlet;

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

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

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

image-20210416094024554

8.JSP

8.1 什么是 jsp

java Server pages:java 服务器端页面,也和 servlet 一样,用于开发动态 web

最大的特点:

  • 写 jsp 就像是写 html

  • 区别:

    • HTML 只给用户提供静态的数据

    • jsp 页面中可以嵌入 java 代码,为用户提供动态数据

  • jsp 九个内置对象

    • request:封装客户端的请求,其中包含来自 GET 或 POST 请求的参数;
  • response:封装服务器对客户端的响应;

    • pageContext:通过该对象可以获取其他对象;
  • session:封装用户会话的对象;

    • application:封装服务器运行环境的对象;
  • out:输出服务器响应的输出流对象;

    • config:Web 应用的配置对象;
  • page:JSP 页面本身(相当于 Java 程序中的 this);

    • exception:封装页面抛出异常的对象。

8.2jsp 原理

思路:jsp 到底如何执行

  • 代码层面没有任何问题

  • 服务器内部工作

    tomcat 中有一个 work 目录

    idea 中使用 tomcat 的话会在 idea 的 tomcat 生成一个 work 目录

    C:\Users\doomwstcher\AppData\Local\JetBrains\IntelliJIdea2020.2\tomcat\Unnamed_javaweb-session-cookie\work\Catalina\localhost\javaweb_session_cookie_war\org\apache\jsp

    发现页面转变成了 java 程序

image-20210416101719160

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

jsp 最终也会被转换成为一个 jsp 类

jsp 本质是一个 servlet

//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//jsp的service
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
  1. 判断请求

  2. 内置一些对象

    final javax.servlet.jsp.PageContext pageContext;//页面上下文
    javax.servlet.http.HttpSession session = null;//session
    final javax.servlet.ServletContext application;//applicationcontext
    final javax.servlet.ServletConfig config;//配置
    javax.servlet.jsp.JspWriter out = null;//out
    final java.lang.Object page = this;//当前
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;
    HttpServletRequest//请求
    HttpServletResponse//响应
  3. 输出页面前增加的代码

      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-20210416104914995

在 jsp 页面中:

只要是 java 代码就会原封不动的输出,

如果是 html 代码就会被转换为 out.write("\r\n");这样的格式输出到前端

8.3JSP 基础语法

任何语言都有自己的语法,java 中有。。,jsp 作为 java 技术的一种应用,他拥有一些自己的扩充的语法(了解,知道即可),java 的所有语法他都支持!

JSP 表达式

<%--  JSP表达式
作用:用来将程序的输出结果,输出到客户端
<%=变量或者表达式%>
--%>

JSP 脚本片段

<%
int sun=0;
for (int i = 0; i <5 ; i++) {
sun+=i;
}
out.print("<h1>sun="+sun+"</h1>");
%>

脚本片段的再实现

<%-- 在代码中嵌入html元素--%>
<%
for (int i = 0; i <5 ; i++) {
%>

<h1>狂神<%= i%></h1>

<%
}
%>

jsp 声明

<%!
static {
System.out.println("loading Servlet!");
}
private int var = 0;
public void hu(){
System.out.println("进入了方法hu");
}
%>

JSP 声明:会变一到 JSP 生成 java 的类中!其他的,就会被生成到 _jspService 方法中,在 jsp 中嵌入 java 代码即可!

<%%>片段
<=%%>表达式
<%!%>定义全局方法
<%--注释--%>

JSP 的注释,不会在客户端显示,html 就会!

8.4JSP 指令

<%@%>
<%@include file=""%>包含文件

JSP 标签

<%@ include file="common/HEADER.jsp"%>
<h1>我是主题页面</h1>
<%@ include file="common/footer.jsp"%>
<%--jsp标签--%>
<jsp:include page="common/HEADER.jsp"/>
<h1>我是第二个</h1>
<jsp:include page="common/footer.jsp"/>
<%--@ include会将两个页面合二为一--%>
<%@ include file="common/HEADER.jsp"%>
<h1>我是主题页面</h1>
<%@ include file="common/footer.jsp"%>

<%--jsp标签
jsp:include;拼接页面,本质是三个页面
--%>
<jsp:include page="common/HEADER.jsp"/>
<h1>我是第二个</h1>
<jsp:include page="common/footer.jsp"/>

8.5 九大内置对象

  • PageContext 存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application 【ServletContext】存东西
  • config 【ServletConfig】
  • page 几乎不用
  • execption 和 java 异常一样
  pageContext.setAttribute("name1","h1");//保存的数据只在一个页面中有效
request.setAttribute("name2","h2");//保存的数据在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","h3");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","h4");//保存数据只在服务器中有效,从打开服务器到关闭服务器
%>

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

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

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

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

        <!-- 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 表达式:${}

  • 获取数据
  • 执行运算
  • 获取 web 开发的常用对象
  • 调用 java 方法

JSP 标签

<%--<jsp:include>--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="kuangshen"/>
<jsp:param name="age" value="18"/>
</jsp:forward>

JSTL 标签

JSTL 标签库的使用就是为了弥补 HTML 标签的不足;

它自定义了许多的标签,可以供我们使用,标签的功能和 java 代码的一样

核心标签(要求掌握部分即可)

image-20210419084229290

JSTL 标签使用步骤:

  • 引入对应的 taglib
  • 使用其中的方法
  • 在 tomcat 中也需要引入 jstl 的包否则会报错,jstl 解析错误

c:if

<h4>
if测试
</h4>
<hr>
<form action="coreif.jsp" method="get">
<%-- el表达式获取表单中的数据
${parom.参数}
--%>
<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="${param.username}"></c:out>

c:choose

<c:set var="score" value="91"/>
<c:choose>
<c:when test="${score>90}">你的成绩还行</c:when>
<c:when test="${score>80}">你的成绩不行</c:when>
<c:when test="${score>60}">你退学吧</c:when>
</c:choose>

c:foreach

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

格式化标签

SQL 标签

XML 标签

9.0、javaBean

实体类

javaBean 有特定的写法:

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

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

ORM:对象关系映射

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

people 表

idnameageaddress
1laozi13深圳
2laozi214深圳
3laozi314深圳
class Perple{
private int id;
private String name;
private int age;
private String address;

}
class a{
new Perple(1,"laozi1",3,"深圳");
new Perple(2,"laozi2",14,"深圳");
new Perple(3,"laozi3",14,"深圳");
}
  • 过滤器
  • 文件上传
  • 邮件发送
  • 复习 jdbc:如何使用 jdbc,增删改查,事务

10.三层架构

什么是 mvc: model view Controller 模型 视图,控制器

10.1 早些年的架构

image-20210419111655115

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

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

10.2、MVC 三层架构

image-20210419112711540

model

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

view

  • 展示数据
  • 提供链接发起 Servlet 请求(a,form.img..)

Controller(Serlet)

  • 接收用户请求:(req:请求参数,session 信息.....)
  • 交给业务层处理对应代码
  • 控制视图的跳转
登陆-->接受用户的登录请求--->处理用户请求(获取用户登陆的参数,username,password)---->交给业务层处理登陆业务,判断用户名密码是否正确:事务--->DAO查询用户名和密码是否正确--->数据库

11、Filter

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

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

image-20210419114926394

1.导包

image-20210419122500441

不要搞错包

2 实现 Filter 接口

package com.hyc.filter;

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

public class ChatcterEncodingFilter implements Filter {
//初始化:web服务器启动的就以及初始化了,随时等待过去对象出现
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("ChatcterEncodingFilter已经初始化");
}
// 在过滤中的所有代码,在过滤特定请求的时候都会执行
// 必须要让过滤器找到同行
// chain.doFilter(request,response);
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("执行前");
chain.doFilter(request,response);//让请求继续往前走,如果不写的程序到这里停止
System.out.println("执行后");
}
//销毁
public void destroy() {
System.out.println("ChatcterEncodingFilter销毁");
}
}

3 在 web.xml 中配置 Filter


<filter>
<filter-name> ChatcterEncodingFilter</filter-name>
<filter-class>com.hyc.filter.ChatcterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ChatcterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>

12.监听器

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

  1. 编写一个监听器

    package com.hyc.listner;

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

    public class OnlineListner implements HttpSessionListener {
    //创建session监听,看你的一举一动
    //一旦创建session就会触发一个事件
    public void sessionCreated(HttpSessionEvent se) {
    System.out.println(se.getSession().getId());
    ServletContext ctx = se.getSession().getServletContext();
    Integer oc =(Integer) ctx.getAttribute("OnlineCount");
    if (oc==null){
    oc = new Integer(1);
    }else {
    int count = oc.intValue();
    oc = new Integer(count+1);
    }
    ctx.setAttribute("OnlineCount",oc);
    }

    public void sessionDestroyed(HttpSessionEvent se) {
    ServletContext ctx = se.getSession().getServletContext();
    Integer oc =(Integer) ctx.getAttribute("OnlineCount");
    if (oc==null){
    oc = new Integer(0);
    }else {
    int count = oc.intValue();
    oc = new Integer(count-1);
    }
    ctx.setAttribute("OnlineCount",oc);
    }
    /*
    * 销毁session
    * 手动销毁
    * 自动销毁
    * */
    }
  2. 在 web.xml 中注册监听器


<!-- 注册监听器-->
<listener>
<listener-class>com.hyc.listner.OnlineListner</listener-class>
</listener>

3,看情况准备

13、过滤器和监听器的常见应用

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

package com.hyc.listner;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class Testpanel {
public static void main(String[] args) {
Frame frame = new Frame("中秋快乐");//一个窗体
Panel pa1 = new Panel(null);//面板
frame.setLayout(null);
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(0,0,255));
pa1.setBounds(50,50,300,300);
pa1.setBackground(new Color(255,0,0));
frame.add(pa1);
frame.setVisible(true);
//监听事件:关闭时间
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("关闭");
System.exit(0);
}
}
);

用户登陆之后才能进入首页,用户注销之后就不能进入主页了!

登记权限问题:什么权限进入什么页面

  1. 用户登陆后,向 session 中放入用户的数据

  2. 进入主页的时候判断用户是否已经登陆

    HttpServletRequest request1 = (HttpServletRequest) request;
    HttpServletResponse response1 = (HttpServletResponse) response;
    Object user_session = request1.getSession().getAttribute(Coestext.USER_SESSION);
    if (user_session==null){
    response1.sendRedirect("/jf/error.jsp");
    }

    chain.doFilter(request,response);

14、jdbc(复习)

什么是 JDBC: java 连接数据库

image-20210421175232428

新建数据库

添加数据库依赖

<dependencies>
<dependency>
<!-- mysql的驱动-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>

idea 连接数据库

image-20210421175417673

jdbc 固定六部曲,(固定步骤)

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送 sql 的接口,做增删改查(CRUD)
  4. 编写 sql(根据业务,编写不同 sql)
  5. 执行 SQL
  6. 关闭连接
    String url = "jdbc:mysql://localhost:3306/peojdbc?userUnicode=true&charcterEncoding=utf-8";
String username = "root";
String password = "root";
//1加载驱动
Class.forName("java.sql.Driver");
//2连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
Statement statement = connection.createStatement();
//3编写sql
String sql = "select *\n" + "from users ;";
//4返回结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id"+rs.getInt("id"));
System.out.println("name"+rs.getString("name"));

}
//5先开后关
statement.close();
connection.close();

PreparedStatement 安全接口的复习

package com.hyc.test;

import java.sql.*;

public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://localhost:3306/peojdbc?userUnicode=true&charcterEncoding=utf-8";
String username = "root";
String password = "root";
//1加载驱动
Class.forName("java.sql.Driver");
//2连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "insert into users (id, name, password, email, birthday) values (?,?,?,?,?);";

PreparedStatement pst = connection.prepareStatement(sql);
//3编写sql
String sql1 = "select *\n" + "from users ;";
pst.setInt(1,4);
pst.setString(2,"hjj");
pst.setString(3,"123456");
pst.setString(4,"一二三@qq.com");
pst.setDate(5,new Date(new java.util.Date().getTime()));
//4返回结果集
int i = pst.executeUpdate();
if (i>=0){
System.out.println("添加成功");
}
ResultSet rs = pst.executeQuery(sql1);
while (rs.next()){
System.out.println("id"+rs.getInt("id"));
System.out.println("name"+rs.getString("name"));

}
//5先开后关
pst.close();
connection.close();
}
}

事务

要么都成功,要么都失败

ACID 原则:保证数据安全

开始事务
事务提交 comit()
事务回滚 rollback()
关闭事务

经典例子
a:1000
b:1000
a(900)---100---b(1100)

junit 单元测试

依赖

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>

测试成功是这样的

package com.hyc.test;

import org.junit.jupiter.api.Test;

public class testjunit {
@Test()
public void test(){
System.out.println("hello");
}

}

image-20210421221459752

测试失败是这样的

image-20210421221543371

接下来用 junit 来测试数据库中的事务

package com.hyc.test;

import org.junit.jupiter.api.Test;

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

public class testjunit {
@Test()
public void test() {
String url = "jdbc:mysql://localhost:3306/peojdbc?userUnicode=true&charcterEncoding=utf-8";
String username = "root";
String password = "root";
Connection connection = null;
//1加载驱动
try {
Class.forName("java.sql.Driver");

//2连接数据库,代表数据库
connection = DriverManager.getConnection(url, username, password);
//3.通知数据库开启事务
connection.setAutoCommit(false);
String sql = "update accout\n" +
"set moeny = moeny-100\n" +
"where name =\"a\";";
connection.prepareStatement(sql).executeUpdate();
// int i = 1/0;
String sql2 = "update accout\n" +
"set moeny = moeny+100\n" +
"where name =\"b\";";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();//以上sql全执行成功了就提交事务
System.out.println("success");
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}

}

smbms 项目

image-20210422082658489

数据库:

image-20210422082723749

项目如何搭建:

考虑使用不使用 maven?依赖?jar 包

项目搭建准备工作

  1. 搭建 maven 项目

  2. 配置 tomcat

  3. 测试项目是否能够跑起来

  4. 导入项目会遇到的依赖 jar 包

    1. jsp.Servlet.mysql,jsp
  5. 创建项目结构

    1. image-20210422090102390
  6. 编写实体类

    1. orm: 表映射
  7. 编写基础公共类

    1. 数据库配置文件

      driver=com.mysql.jdbc.Driver
      url =jdbc:mysql://localhost:3306?useUnicode=true&charcterEncoding=utf-8
      username = root
      password = root
    2. 编写数据库公共类

      package com.hyc.dao;

      import java.io.InputStream;
      import java.sql.*;
      import java.util.Properties;

      //操作数据库的公共类
      public class BaseDao {
      private static String driver;
      private static String url;
      private static String username;
      private static String password;

      //静态代码块,类加载的时候就初始化了
      static {
      Properties properties = new Properties();

      InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.Properties");
      try {
      properties.load(is);
      }catch (Exception e){
      e.printStackTrace();
      }

      driver = properties.getProperty("driver");
      url = properties.getProperty("url");
      password = properties.getProperty(" password");
      username = properties.getProperty("username");
      }

      public static Connection getconnection(){
      Connection conn = null;
      try {
      Class.forName(driver);
      conn = DriverManager.getConnection(url,username,password);
      } catch (Exception e) {
      e.printStackTrace();
      }
      return conn;
      }
      //查询公共类
      //预编译的sql我们直接执行就好了
      public static ResultSet execute(Connection conn,String sql,Object[] params,PreparedStatement pst,ResultSet rs){
      try {
      pst = conn.prepareStatement(sql);
      for (int i = 0; i < params.length ; i++) {
      //pst.setObject占位符是从1开始的,但是我们的数组是从0开始的
      pst.setObject(i+1,params[i]);
      }
      rs = pst.executeQuery();

      } catch (SQLException throwables) {
      throwables.printStackTrace();
      }
      return rs;
      }

      //增删改公共方法
      public static int execute(Connection conn,String sql,Object[] params,PreparedStatement pst){
      int UpdateRows = 0;
      try {
      pst = conn.prepareStatement(sql);
      for (int i = 0; i < params.length ; i++) {
      //pst.setObject占位符是从1开始的,但是我们的数组是从0开始的
      pst.setObject(i+1,params[i]);
      }

      UpdateRows = pst.executeUpdate();
      } catch (SQLException throwables) {
      throwables.printStackTrace();
      }
      return UpdateRows;
      }

      public static boolean closeResoure(Connection conn,PreparedStatement pst ,ResultSet rs)
      {
      boolean flag = true;
      if (conn!=null){
      try {
      conn.close();
      //GC回收
      conn=null;
      } catch (SQLException throwables) {
      throwables.printStackTrace();
      flag = false;
      }
      }
      if (pst!=null){
      try {
      pst.close();
      //GC回收
      pst=null;
      } catch (SQLException throwables) {
      throwables.printStackTrace();
      flag = false;
      }
      }
      if (rs!=null){
      try {
      rs.close();
      //GC回收
      rs=null;
      } catch (SQLException throwables) {
      throwables.printStackTrace();
      flag = false;
      }
      }
      return flag;
      }
      }

    3. 编写过滤器

  8. 导入静态资源

登陆功能实现

image-20210422100402188

  1. 编写前端也眯娜

  2. 设置欢迎页面

      <welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
    </welcome-file-lit>
  3. 编写 dao 层得到用户登陆的接口

       public user getLoginUser(Connection conn, String usercode);
  4. 编写 dao 得到用户登陆的接口实现

    package com.hyc.dao.user;
    import java.sql.*;
    import com.hyc.dao.BaseDao;
    import com.hyc.pojo.user;

    import java.sql.Connection;

    public class UserDaoImpl implements UserDao {


    @Override
    public user getLoginUser(Connection conn, String usercode) {
    PreparedStatement pst = null;
    ResultSet rs = null;
    user user = null;
    if (conn != null) {
    String sql = "select * from smbms_user where userCode=?";
    Object[] params = {usercode};
    try {
    rs = BaseDao.execute(conn,sql,params,pst,rs);
    if (rs.next()){
    user = new user();
    user.setId(rs.getInt("id"));
    user.setUserCode(rs.getString("userCode"));
    user.setUserName(rs.getString("userName"));
    user.setUserPassword(rs.getString("userPassword"));
    user.setGender(rs.getInt("gender"));
    user.setBirthday(rs.getDate("birthday"));
    user.setPhone(rs.getString("phone"));
    user.setAddress(rs.getString("address"));
    user.setUserRole(rs.getInt("userRole"));
    user.setCreatedBy(rs.getInt("createdBy"));
    user.setCreationDate(rs.getTimestamp("creationDate"));
    user.setModifyBy(rs.getInt("modifyBy"));
    user.setModifyDate(rs.getTimestamp("modifyDate"));
    }
    BaseDao.closeResoure(null,pst,rs);

    }catch (Exception e){

    }

    }

    return user;
    }
    }

  5. 编写业务层

    public interface UserService {
    public user login(String userCode,String password);
    }
  6. 业务层实现类

       public user login(String userCode, String password) {
    Connection conn = null;
    user user = null;
    try{
    conn = BaseDao.getconnection();
    user = userDao.getLoginUser(conn,userCode);
    }catch (Exception e){
    e.printStackTrace();
    }finally {
    BaseDao.closeResoure(conn,null,null);
    }

    return user;
    }
  7. servlet 编写

    package com.hyc.servlet.user;

    import com.hyc.pojo.user;
    import com.hyc.service.user.UserService;
    import com.hyc.service.user.UserServiceImpl;
    import com.hyc.util.Constaets;

    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 LoginSerlvet extends HttpServlet {
    //Servlet:控制层调用业务层代码
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("进入servlet");
    //获取用户名和密码
    String uc = req.getParameter("userCode");
    String upwd = req.getParameter("userPassword");
    UserServiceImpl userService = new UserServiceImpl();
    user user = userService.login(uc,upwd);
    if (user!=null){
    System.out.println("查有此人");
    req.getSession().setAttribute(Constaets.USER_SEESION,user);
    //跳转到内部主页
    resp.sendRedirect("/smbms/jsp/frame.jsp");
    }else {
    //查无此人转发会登陆页面
    req.setAttribute("error","用户名或者密码不正确");
    req.getRequestDispatcher("login.jsp").forward(req,resp);

    }
    }

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

  8. 注册 servlet

    <!--  servlet-->
    <servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.hyc.servlet.user.LoginSerlvet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login</url-pattern>
    </servlet-mapping>

    9.优化登陆选项,拦截登陆优化

    编写过滤器

    package com.hyc.filter;

    import com.hyc.pojo.user;
    import com.hyc.util.Constaets;

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

    public class SysFilter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest servletRequest1 = (HttpServletRequest) servletRequest;
    HttpServletResponse servletResponse1 = (HttpServletResponse) servletResponse;
    user user = (user)servletRequest1.getSession().getAttribute(Constaets.USER_SEESION);
    if (user == null) {
    servletResponse1.sendRedirect("/smbms/error.jsp");
    }else {
    filterChain.doFilter(servletRequest,servletResponse);
    }

    }

    @Override
    public void destroy() {

    }
    }

    测试,登陆,注销,权限都要 ok

密码修改

  1. 导入素材

  2. 写项目,从底层往上面写

    image-20210422160752254

  3. 编写 userdao

        //修改密码
    @Override
    public int updateuser(Connection conn, int id, String password) {
    String sql = "update smbms_user\n" +
    "set userPassword=?\n" +
    "where id=?;";
    int execute = 0;
    if (conn!=null){
    PreparedStatement pst = null;
    Object parms[] = {password,id};
    execute =BaseDao.execute(conn, sql, parms, pst);
    BaseDao.closeResoure(null,pst,null);
    }

    return execute;
    }

  4. 在服务层接口新增修改密码方法

     public  boolean updateuser( int id, String password);
  5. 编写 service 层别忘记注册

        public boolean updateuser(int id, int password) {
    boolean flag = false;
    Connection conn = null;
    try {
    conn= BaseDao.getconnection();
    //修改密码
    if(userDao.updateuser(conn,password,id)>0){
    System.out.println("修改成功");
    flag = true;
    }
    }catch (Exception e){

    }

    return flag;
    }
    package com.hyc.servlet.user;

    import com.hyc.pojo.user;
    import com.hyc.service.user.UserService;
    import com.hyc.service.user.UserServiceImpl;
    import com.hyc.util.Constaets;
    import com.mysql.jdbc.StringUtils;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    //实现Servlet复用
    public class UserServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //从session里面那到用户的id
    Object o = req.getSession().getAttribute(Constaets.USER_SEESION);
    String newpassword = req.getParameter("newpassword");
    boolean flag = false;
    if (o != null&&newpassword!=null) {
    UserServiceImpl userService = new UserServiceImpl();
    flag = userService.updateuser(((user)o).getId(),newpassword);
    if (flag){
    req.setAttribute("massage","修改密码成功,请退出使用新密码登陆");
    req.getSession().removeAttribute(Constaets.USER_SEESION);
    System.out.println( req.getSession().getAttribute(Constaets.USER_SEESION));
    resp.sendRedirect("/smbms/login.jsp");
    }else {
    req.setAttribute("massage","密码修改失败");

    }
    }else {
    req.setAttribute("massage","新密码有问题");
    req.getRequestDispatcher("smbms/jsp/pwdmodify.jsp").forward(req,resp);
    }

    }
    }

  6. 实现复用需要提取方法

       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getParameter("method");
    if (method.equals("savepwd")&&method!=null){
    this.updatepwd(req,resp);
    }
    }
  7. 测试功能

优化密码注册密码修改使用 ajax

  1. 阿里巴巴的 fastjson;
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>

2.后台代码修改

//验证旧密码,session中有用户的密码
public void pwdmodify(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{
Object o = req.getSession().getAttribute(Constaets.USER_SEESION);
String oldpassword = req.getParameter("oldpassword");
//万能的map:结果集
HashMap<String, String>resultMap = new HashMap<String, String>();

if (o==null){//session失效了,过期了
resultMap.put("result","sessionerror");
}else if(oldpassword!=null){
resultMap.put("result","error");
}else {
String userPassword = ((user)o).getUserPassword();
if (oldpassword.equals(userPassword)){
resultMap.put("result","true");
}else {
resultMap.put("result","false");
}
}
try{
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
//JSONArray 阿里巴巴的json工具类,转换格式
writer.write(JSONArray.toJSONString(resultMap));
writer.close();
}catch (Exception e){
System.out.println(e.getMessage());
}
}

实现底层用户管理分页

image-20210426105328702

  1. 导入分页的工具类
  2. 用户列表页面导入
  3. 引入页面

1.获取用户数量

  1. userdao

        public  int getUserCount(Connection conn ,String username,int userrole);

  2. userDaoimpl

        //根据用户名或者角色名查询用户总数[核心sql]项目内最难得sql
    @Override
    public int getUserCount(Connection conn, String username, int userrole) {

    PreparedStatement pst = null;
    ResultSet rs = null;
    int count = 0;

    if (conn!=null){
    StringBuffer sql = new StringBuffer();
    sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id");
    ArrayList<Object> list = new ArrayList<>();//存放参数
    if (!StringUtils.isNullOrEmpty(username)){
    sql.append(" and u.userName like ?");
    list.add("%"+username+"%");//list默认下标0
    }
    if (userrole>0){
    sql.append(" and u.userRole like ?");
    list.add(userrole);//list默认下标0
    }
    //怎么把list转换为数组
    Object[] params = list.toArray();
    System.out.println("userdaoimpl"+sql.toString());//输出最后完整的sql语句;
    rs = BaseDao.execute(conn,sql.toString(),params,pst,rs);
    try {
    if (rs.next()){
    count = rs.getInt("count");//从结果集获取数量
    }
    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }finally {
    BaseDao.closeResoure(conn,pst,rs);
    }
    }
    return count;
    }
  3. UserService

        public  int getUserCount(String username,int userRole);

  4. UserServiceimpl

        @Override
    public int getUserCount(String username, int userRole) {
    Connection conn = null;
    int count = 0;

    conn = BaseDao.getconnection();
    count = userDao.getUserCount(conn,username,userRole);
    BaseDao.closeResoure(conn,null,null);
    return count;
    }
  5. 第二条线,分页查询用户

    Userdao 确认 sql:

        select u.*,r.roleName as userRoleName from smbms_user u ,smbms_role r where u.userRole = r.id and u.userName like ? and u.userRole = ?  order by u.createdBy DESC limit ?,?;
      //查询条件获取用户list
    public List<user> getUserList(Connection conn,String userName,int userRole,int CurrentPagNo,int pageSize);
  6. 编写分页查询用户实现类

        public List<user> getUserList(Connection conn, String userName, int userRole, int CurrentPagNo, int pageSize) {

    PreparedStatement pst = null;
    ResultSet rs = null;
    List<user> userList = new ArrayList<>();
    List<Object> List = new ArrayList<>();
    if (conn!=null){
    StringBuffer sql = new StringBuffer();
    sql.append("SELECT u.*,r.roleName AS userRoleName FROM smbms_user u ,smbms_role r WHERE u.userRole = r.id");
    if (!StringUtils.isNullOrEmpty(userName)){
    sql.append(" and u.userName like ?");
    List.add("%"+userName+"%");
    }
    if (userRole>0){
    sql.append(" and u.userRole = ?");
    List.add(userRole);
    }
    sql.append(" order by u.createdBy DESC limit ?,?");
    CurrentPagNo = (CurrentPagNo-1)*pageSize;
    List.add(CurrentPagNo);
    List.add(pageSize);
    Object[] params = List.toArray();
    System.out.println("sql-->"+sql.toString());
    rs = BaseDao.execute(conn,sql.toString(),params,pst,rs);
    try {
    if (rs.next()){
    user _user = new user();
    _user.setId(rs.getInt("id"));
    _user.setId(rs.getInt("id"));
    _user.setUserCode(rs.getString("userCode"));
    _user.setUserName(rs.getString("userName"));
    _user.setGender(rs.getInt("gender"));
    _user.setBirthday(rs.getDate("birthday"));
    _user.setPhone(rs.getString("phone"));
    _user.setUserRole(rs.getInt("userRole"));
    _user.setUserRoleName(rs.getString("userRoleName"));
    userList.add(_user);
    }
    } catch (SQLException throwables) {
    throwables.printStackTrace();
    }
    return userList;
    }
  7. 编写服务层

       public List<user> getUserList(String queryUserName,int queryUserRole,int currentPagNo,int PageSize);

  8.     @Override
    public List<user> getUserList( String queryUserName,int queryUserRole, int currentPagNo, int PageSize) {
    Connection conn = null;
    List<user> userList = null;
    conn = BaseDao.getconnection();
    userList = userDao.getUserList(conn,queryUserName,queryUserRole,currentPagNo,PageSize);


    return userList;
    }

2 .显示用户 serlvet

  1. 获取用户的前端数据(查询)
  2. 判断请求是否需要执行,看参数的值来判断
  3. 为了实现分页,需要计算出当前页面和总页面的参数
  4. 用户列表展示
  5. 返回前端

15.文件上传原理

文件上传原理就是操作 io 流

一共就那麽几个步骤

1.判断文件是不是文件表单

2.创建缓冲区以防文件过大

处理上传文件,一般需要通过流来获取,我们可以使用 req 的流,原生态的文件上传流获取,十分麻烦 但是我们都建议使用 apache 的文件上传组件来实现,common-fileupload,他需要以来与 commons-io 组件 通过这个工厂设置一个缓冲区,当上传文件大于缓冲区的时候,将他放到临时文件中

3.处理上传文件把前端请求解析成一个 fileitems 集合对象

可以使用 UUID(唯一识别通用的通用码),保证文件名唯一 随意生成一个唯一的识别通用码

网络传输中的东西,都需要序列化 pojo 实体类 如果想要通过网络在多个电脑上运行,传输===>需要把对象都序列化 没有方法的接口叫做标记接口 jvm--> Java 栈, 本地方法栈 :native--> c++ jni = java Native Interface

4.确认存放文件存放路径

5 文件传输和返回前端成功与否的信息

idea 插件

image-20210505160517558