JavaWeb (SSM框架)

基础概念

web开发:

  • web:页面的意思,例如:www.baidu.com

  • 静态web:

    • html,css
    • 提供给所有人看的数据始终不会发生变化的
  • 动态web:

    • 淘宝,以及几乎所有的网站
    • 提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同
    • 技术栈:Servlet/JSP,ASP,PHP

在Java中,动态web资源开发的技术统称为JavaWeb

web应用程序

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

  • a.html、b.html 等多个web资源,这些web资源可以被外届访问,对外界提供服务;

  • 你们很访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。

  • URL:统一资源定位标志,就是指网络地址。

  • 这个统一的web资源会被放在同一个文件夹下,web应用程序 -->Tomcat:服务器

  • 一个web应用由多部分组成(静态web,动态web)

    • html,css,js
    • jsp,servlet
    • Java程序
    • jar包
    • 配置文件(Properties)

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

静态web

*.htm、*.html、这些都是网页的后缀,
如果服务器上一直存在这些东西,我们就可以直接进行读取。
通络;

在这里插入图片描述
静态web存在的缺点:

  • web页面无法动态更新,所有用户看到都是同一个页面

    • 轮播图、点击特效:伪动态
    • JavaScript [实际开发中,它用的最多]
    • VBScript
  • 它无法和数据库交互(数据无法持久化,用户无法交互)

动态web

页面会动态展示:“web的页面展示的效果因人而异”;
在这里插入图片描述
缺点:

  • 加入服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布;

    • 停机维护

优点:

  • web页面可以动态更新,所有用户看到都不是同一个页面
  • 它可以与数据库交互(数据持久化:注册,商品信息,用户信息…)
    在这里插入图片描述

Tomcat启动和配置

文件夹作用:

  • bin:启动、关闭的脚本文件
  • conf:配置文件
  • lib:依赖的jar包
  • logs:日志文件
  • webapps:存放网站的

可以配置启动的端口号

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

可以配置主机名称

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

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

  • 1、输入一个域名;回车

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

    • 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
    • 没有:去DNS服务器找,找到的话就返回,找不到就返回找不到

在这里插入图片描述

发布一个web网站

不会就先模仿:将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了

网站应该有的结构:

  • webapps:Tomcat服务器的web目录

    • ROOT

    • zyaStudy:网站的目录名

      • WEB-INF

        • classes:Java程序
        • lib:web应用所依赖的jar包
        • web.xml:网站配置文件
      • index.html 默认的首页

      • static

        • css

          • style.css
        • js

        • img


HTTP

http:

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

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

https:

  • Hyper Text Transfer Protocol over SecureSocket Layer,是以安全为目标的 HTTP 通道
  • 端口号:443

两个时代:

http1.0 :

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

http2.0

  • HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源

Http请求:

客户端 — 发请求(Request)— 服务端

百度:

Request URL: https://www.baidu.com/		请求地址
Request Method: GET					get方法/post方法
Status Code: 200 OK						状态码:200
Remote Address: 36.152.44.95:443		远程地址
引用站点策略: strict-origin-when-cross-origin

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive

1、请求行

  • 请求行中的请求方式:GET

  • 请求方式:Get、Post、HEAD、DELETE、PUT、TRACT、…

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

2、消息头

Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式  GBK、UTF-8、GB2312、ISO8859-1
Accept-Language: 告诉浏览器,它的语言环境 
Cache-Control: 缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
HOST: 主机

Http响应

服务端 — 响应(Respones)— 客户端

百度:

Bdpagetype: 2
Bdqid: 0xa2d77d3d0000d469
Cache-Control: private		// 缓存控制
Connection: keep-alive		// 连接:保持活着
Content-Encoding: gzip		// 编码
Content-Type: text/html;charset=utf-8		// 类型
Date: Wed, 18 Aug 2021 13:33:25 GMT
Expires: Wed, 18 Aug 2021 13:33:24 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=320; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=34436_34370_34376_33848_34449_34092_34111_26350_34426_34289; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1629293605019960986611733985055083648105
Transfer-Encoding: chunked
X-Frame-Options: sameorigin
X-Ua-Compatible: IE=Edge,chrome=1

响应体

Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式  GBK、UTF-8、GB2312、ISO8859-1
Accept-Language: 告诉浏览器,它的语言环境 
Cache-Control: 缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
HOST: 主机
Refrush: 告诉客户端,多久刷新一次
Location: 让网页重新定位

响应状态码

200:请求响应成功 200
3xx:请求重定向

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

4xx:找不到资源 404

  • 资源不存在;

5xx:服务器代码错误

  • 500
  • 502:网关错误

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

第一种https://blog.csdn.net/qq_44912064/article/details/114846888

  1. 域名解析
  2. 发起TCP的三次握手
  3. 建立起TCP连接后发起http请求
  4. 服务器响应http请求,浏览器得到html代码
  5. 浏览器解析html代码,并请求html代码中的资源(css JavaScript 图片)
  6. 浏览器对页面进行渲染呈现

第二种
https://zhuanlan.zhihu.com/p/95904514

  1. 用户在浏览器输入 URL
  2. 浏览器尝试读取 URL 的缓存
  3. 无缓存则开始查 URL 域名的 ip,也就是 DNS 查找
  4. 开始建立 TCP 链接,经过三次握手成功建立连接
  5. 客户端开始发送数据
  6. 服务端将用户所需的资源返回给客户端
  7. 若返回的是 HTML 文档的话,浏览器开始解析 HTML 文档
  8. 构建 DOM 树、构建 CSSOM 树
  9. 将解析步骤中创建的 CSSOM 树和 DOM 树合成为 Render 树,然后用于计算每个可见元素的布局,最后将其绘制到屏幕上

Maven

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

2、Maven能够自动帮我们导入和配置这个jar包

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

  • 有约束,不要去违反。

Maven会规定好你该如何去编写我们的Java代码,必须要按照这个规范来;

配置环境变量

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

在这里插入图片描述
在终端输入:mvn -version
得到这个结果:说明环境配置成功

阿里云镜像:

  • 镜像:mirrors

    • 作用:加速我们的下载
  • 国内建议使用阿里云的镜像

本地仓库

在本地的仓库,远程仓库:

建立一个仓库:


Servlet

Servlet就是sun公司开发动态web的一门技术

Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:

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

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

HelloServlet

Servlet接口Sun公司有两个默认的实现类:HttpServlet、

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

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

  • 父项目中会有:

    <modules>
       <module>servlet-01</module>
    </modules>
    
  • 子项目会有:

    <parent>
        <artifactId>javaweb-02-servlet</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    
  • 父项目中的Java子项目可以直接使用:

    son extends father
    

3、Maven环境优化:

  1. 修改web.xml为最新的
  2. 将maven的结构搭建完整

4、编写一个Servlet程序:

  1. 编写一个普通类
  2. 实现Servlet接口,这里我们直接继承HttpServlet
package com.zhang.servlet;

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.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    
    
    // 由于get或者post只是请求实现的不同的方式,可以互相调用,业务逻辑都一样
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        //        ServletOutputStream outputStream = resp.getOutputStream();
        PrintWriter writer = resp.getWriter();  // 响应流
        //        super.doGet(req, resp);
        writer.print("hello servlet");
    }

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

5、编写Servlet的映射:

为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要再web服务器中注册我们写的Servelt,还需要给他一个浏览器能够访问的路径;

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

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

6、配置Tomcat

在这里插入图片描述


Servlet原理

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

在这里插入图片描述

Mapping:请求映射的路径

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

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

2、一个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>
<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello4</url-pattern>
</servlet-mapping>

3、一个Servlet可以指定通用映射路径:

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

4、默认请求路径:

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

5、指定一些后缀或者前缀等等…(可以自定义后缀实现请求路径,注意点:*前面不能加项目映射的路径)

<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.zhangyiang</url-pattern>
</servlet-mapping>

6、以下是一些错误情况

<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*.zhangyiang</url-pattern>
</servlet-mapping>
// * 前面不能加项目映射的路径
<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*.zhangyiang</url-pattern>
</servlet-mapping>

7、优先级问题:

  • 指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
<!--注册Servlet-->
<servlet>
        <servlet-name>error</servlet-name>
        <servlet-class>com.zhang.servlet.ErrorServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<!--localhost:8080/s1/hello-->
<servlet-mapping>
        <servlet-name>error</servlet-name>
        <url-pattern>/*</url-pattern>
</servlet-mapping>

ServletContext

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

  • 共享数据

    我在这个Servlet中保存的数据,可以在另外一个Servlet中拿到;(也可以通过 IO流 的形式进行数据传输,但比较麻烦)

    • 是一个域对象(服务器在内存上创建的存储空间,用于在不同动态资源 servlet 之间传递与共享数据)
    • 可以读取全局配置参数
    • 可以搜索当前工程目录下面的资源文件
    • 可以获取当前工程名字
package com.zhang.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");
        // this.getInitParameter();     // 初始化参数
        // this.getServletConfig();     // Servlet配置
        // this.getServletContext();    // Servlet上下文(联系上下文)

        ServletContext servletContext = this.getServletContext();
        String username = "杯子";
        servletContext.setAttribute("username", username);  // 将一个数据保存在ServletContext中,名字为 username,值为 username

    }

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

package com.zhang.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 {
    
    
        // 将HelloServlet类中的数据,读取到本类中
        ServletContext context = this.getServletContext();
        // 程序把它设定为Object类型,然后我们可以强转为 String类型
        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 {
    
    
    }
}

<!--注册Servlet-->
<servlet>
    <servlet-name>getc</servlet-name>
    <servlet-class>com.zhang.servlet.GetServlet</servlet-class>
</servlet>
<!--映射Servlet-->
<servlet-mapping>
    <servlet-name>getc</servlet-name>
    <url-pattern>/getc</url-pattern>
</servlet-mapping>

获取初始化参数

<!--配置一些web应用初始化参数-->
<context-param>
   <param-name>url</param-name>
   <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    ServletContext context = this.getServletContext();
    String url = context.getInitParameter("url");
    resp.getWriter().print(url);
}

请求转发(RequestDispatcher)

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

请求转发原理:路径不会发生改变
在这里插入图片描述
重定向原理:路径会发生改变
在这里插入图片描述


读取资源文件

<!--在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>

Properties类:

  • 在Java目录下新建properties
  • 在resources目录下新建properties

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

思路:需要一个文件流

package com.zhang.servlet;

import javax.servlet.RequestDispatcher;
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 ServletDemo04 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/zhang/servlet/aa.properties");
        Properties properties = new Properties();
        properties.load(is);
        String user = properties.getProperty("username");
        String pwd = properties.getProperty("password");
        resp.getWriter().print(user + ":" + pwd);
    }

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


HttpServletResponse

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

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

1、简单分类:

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

public ServletOutputStream getOutputStream() throws IOException;

public PrintWriter getWriter() throws IOException;

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

public void setCharacterEncoding(String charset);

public void setContentLength(int len);

public void setContentLengthLong(long len);

public void setContentType(String type);
public void setDateHeader(String name, long date);

public void addDateHeader(String name, long date);

public void setHeader(String name, String value);

public void addHeader(String name, String value);

public void setIntHeader(String name, int value);

public void addIntHeader(String name, int value);

响应的状态码:

public static final int SC_CONTINUE = 100;

public static final int SC_SWITCHING_PROTOCOLS = 101;

public static final int SC_OK = 200;

public static final int SC_CREATED = 201;

public static final int SC_ACCEPTED = 202;

public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;

public static final int SC_NO_CONTENT = 204;

public static final int SC_RESET_CONTENT = 205;

public static final int SC_PARTIAL_CONTENT = 206;

public static final int SC_MULTIPLE_CHOICES = 300;

public static final int SC_MOVED_PERMANENTLY = 301;

public static final int SC_MOVED_TEMPORARILY = 302;

public static final int SC_FOUND = 302;

public static final int SC_SEE_OTHER = 303;

public static final int SC_NOT_MODIFIED = 304;

public static final int SC_USE_PROXY = 305;

public static final int SC_TEMPORARY_REDIRECT = 307;

public static final int SC_BAD_REQUEST = 400;

public static final int SC_UNAUTHORIZED = 401;

public static final int SC_PAYMENT_REQUIRED = 402;

public static final int SC_FORBIDDEN = 403;

public static final int SC_NOT_FOUND = 404;

public static final int SC_METHOD_NOT_ALLOWED = 405;

public static final int SC_NOT_ACCEPTABLE = 406;

public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;

public static final int SC_REQUEST_TIMEOUT = 408;

public static final int SC_CONFLICT = 409;

public static final int SC_GONE = 410;

public static final int SC_LENGTH_REQUIRED = 411;

public static final int SC_PRECONDITION_FAILED = 412;

public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;

public static final int SC_REQUEST_URI_TOO_LONG = 414;

public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;

public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;

public static final int SC_EXPECTATION_FAILED = 417;

public static final int SC_INTERNAL_SERVER_ERROR = 500;

public static final int SC_NOT_IMPLEMENTED = 501;

public static final int SC_BAD_GATEWAY = 502;

public static final int SC_SERVICE_UNAVAILABLE = 503;

public static final int SC_GATEWAY_TIMEOUT = 504;

public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

2、常见应用:

  1. 向浏览器输出消息

  2. 下载文件

    1. 要获取下载文件的路径
    2. 下载的文件名是啥?
    3. 设置想办法让浏览器能够支持下载我们需要的东西
    4. 获取下载文件的输入流
    5. 创建缓冲流
    6. 获取 OutputStream对象
    7. 将 FileOutputStream流写入到 buffer缓冲区
    8. 使用 OutputStream将缓冲区中的数据输出到客户端
package com.zhang.servlet;

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.FileInputStream;
import java.io.IOException;

public class FileServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        System.out.println("1111");
        //        // 1、获取下载文件的路径
//        String realPath = this.getServletContext().getRealPath("/jt.png");
        String realPath = "E:\\idea project\\com.zya\\response1\\src\\main\\resources\\jt.png";
        System.out.println("下载文件的路径: " + realPath);
        // 2、下载的文件名是啥
        String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
        // 3、设置想办法让浏览器能够支持下载我们需要的东西
        resp.setHeader("Content-Disposition", "attachment;filename="+fileName);
        // 4、获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
        // 5、创建缓冲区
        int len = 0;
        byte[] bytes = new byte[1024];
        // 6、获取OutputStream对象
        ServletOutputStream out = resp.getOutputStream();
        // 7、将FileOutputStream流写入到buffer缓冲区,使用OuputStream将缓冲区中的数据输出到客户端
        while ((len = in.read(bytes))!=-1){
    
    
            out.write(bytes, 0, len);
        }
        // 8、关闭数据流
        out.close();
        in.close();
    }

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

验证码功能:

前端实现:用JavaScript

后端实现:可以用到 Java 的图片类,生成一个图片

package com.zhang.servlet;

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;

public class ImageServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 如何让浏览器3秒自动刷新一次
        resp.setHeader("refresh", "3");

        // 在内存中创建一个图片
        BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        // 得到图片
        Graphics2D g = (Graphics2D) bufferedImage.getGraphics();   //笔
        // 设置图片的背景颜色
        g.setColor(Color.WHITE);
        g.fillRect(0,0,80,20);
        // 给图片写数据
        g.setColor(Color.BLUE);
        g.setFont(new Font(null, Font.BOLD,20));
        g.drawString(makeNum(), 0 ,20);

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

        // 把图片写给浏览器
        boolean write = ImageIO.write(bufferedImage, "png",resp.getOutputStream());
    }

    // 生成随机数
    public String makeNum(){
    
    
        Random random = new Random();
        String num = random.nextInt(9999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0;i < 4 - num.length();i++){
    
    
            sb.append("0");
        }
        String s = sb.toString() + num;
        return num;
    }

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

实现重定向

在这里插入图片描述

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

常用场景:

  • 用户登录
    void sendRedirect(String var1) throws IOException;
    
package com.zhang.servlet;

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 RedirectServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        /*
        	原理:
            resp.setHeader("Location", "/img");
            resp.setStatus(302);
         */
        resp.sendRedirect("/ImageServlet"); // 重定向
    }

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

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

相同点:

  • 页面都会实现跳转

不同点:

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

如果出现中文乱码,就加上这句编码转换:
<%@ page contentType=“text/html; charset=UTF-8” %>

<html>
<body>
<h2>Hello World!</h2>

<%--这里提交的路径,需要寻找项目的路径--%>
<%--${pageContext.request.contextPath}代表当前的项目--%>
<%@ page contentType="text/html; charset=UTF-8" %>
<form action="${pageContext.request.contextPath}/login" method="get">
    用户名: <input type="text" name="username"><br>
    密码: <input type="password" name="password"><br>
    <input type="submit">
</form>

</body>
</html>

package com.zhang.servlet;

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 RequestTest extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username + ":" + password);

        // 重定向时候一定要注意路径问题,否则404
        resp.sendRedirect("/success.jsp");
    }

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

HttpServletRequest

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

1、获取前端传递的参数:

  • req.getParameter(String s)
  • req.getParameterMap()
  • req.getParameterNames()
  • req.getParameterValues(String s)

猜你喜欢

转载自blog.csdn.net/xuexiwd/article/details/119737133
今日推荐