Java-JavaWeb—(3)Web核心-Part1

1.JavaEE 

1.1简介

JavaEE是Java的企业版,由SUN公司领导、各个厂家共同制定并得到官方认可的工业标准。

JavaEE规范是很多Java开发技术的总称,一共包括13个技术规范,包括:JDBC、JNDI、EJB、RMI、IDL/CORB、JSP、Servlet、XML、JMS、JTA、JTS、JavaMail、JAF。

1.2Web简述

Wbe在计算机领域中代表的是网格,像我们之前所用的WWW,简称为万维网。网路技术的出现都是为了让我们在网络的世界中获取资源,这些资源的存放之处,我们称之为网站

资源分为静态资源和动态资源

静态资源:网站中提供给人们展示的资源是一成不变的,也就是说不同人或者在不同时间,看到的内容都是一样的。例如:我们看到的新闻,网站的使用手册,网站功能说明文档等等。

动态资源:网站中提供给人们展示的资源是由程序产生的,在不同的时间或者用不同的人员由于身份的不同,所看到的内容是不一样的。例如:我们在12306上购买火车票,火车票的余票数由于时间的变化,会逐渐的减少,直到最后没有余票。

1.3系统结构

基础结构划分:C/S结构,B/S结构两类。

技术选型划分:Model1模型,Model2模型,MVC模型和三层架构+MVC模型。

部署方式划分:一体化架构,垂直拆分架构,分布式架构,流动计算架构,微服务架构。

1.3.1C/S结构

它指的是客户端——服务器的方式。其中C代表着Client,S代表着服务器。

1.3.2B/S结构

它指的是浏览器——服务器的方式。其中B代表着Browser,S代表着服务器。

1.3.3两种结构的区别

第一:硬件环境不同,C/S通常是建立在专用的网络或小范围的网络环境上(即局域网),且必须要安装客户端。而B/S是建立在广域网上的,适应范围强,通常有操作系统和浏览器就行。

第二:C/S结构比B/S结构更安全,因为用户群相对固定,对信息的保护更强。

第三:B/S结构维护升级比较简单,而C/S结构维护升级相对困难。

2.Tomcat

2.1Tomcat服务器

服务器的概念非常的广泛,它可以指代一台特殊的计算机(相比普通计算机运行更快、负载更高、价格更贵),也可以指代用于部署网站的应用。我们这里说的服务器,其实是web服务器,或者应用服务器。它本质就是一个软件,一个应用。作用就是发布我们的应用(工程),让用户可以通过浏览器访问我们的应用。

服务器名称说明
weblogic实现了javaEE规范,重量级服务器,又称为javaEE容器
websphereAS实现了javaEE规范,重量级服务器。
JBOSSAS实现了JavaEE规范,重量级服务器。免费的。
Tomcat实现了jsp/servlet规范,是一个轻量级服务器,开源免费。

官网地址:http://tomcat.apache.org

解压目录结构:

        bin:tomcat的二进制文件目录

        conf:tomcat的配置文件目录

        lib:tomcat运行时所需的jar包目录

        logs:tomcat的日志目录

        temp:tomcat的临时文件目录

        webapps:tomcat的默认应用发布目录

        work:tomcat的工作目录

2.2Tomcat的配置

2.2.1环境变量配置

系统变量新建CATALINA_HOME,路径为Tomcat的目录

系统变量Path添加以下路径

%CATALINA_HOME%\lib

%CATALINA_HOME%\lib\servlet-api.jar

%CATALINA_HOME%\lib\jsp-api.jar

2.2.2user配置

添加用户,进入tomcat的目录的conf,选择“tomcat-users.xml”文件,打开文件后在最后 一行代码的前面添加如下代码:

<role rolename="manager-gui"/> 

<role rolename="admin-gui"/>  

<user username="admin" password="admin" roles="admin-gui"/>

<user username="tomcat" password="admin" roles="manager-gui"/>

2.2.3改字符集

在conf的目录中,logging.properties的下面部分,的最后一行改为gbk


2.3基本使用

2.3.1启动和停止

Tomcat的bin目录中startup.bat(windows)和startup.sh(linux)用于启动

shutdown.bat(windows)和shutdown.sh(linux)用于关闭

启动之后,可以在浏览器中输入网址:http://localhost:8080

访问到Tomcat官网

2.3.2遇到问题

1.如果一闪而过,应该配置JAVA_HOME环境变量

2.出现Address already in user:JVM_Bind,端口被占用

3.在cong目录下,server.xml的下面部分,将prot改为80

 2.4IDEA集成Tomcat

打开IDEA,菜单栏Run,选择Edit Configuration,添加Tomcat Server,选择Local,然后添加Tomcat目录,选择默认打开浏览器,完成配置

在Tomcat目录的wedapps目录下下添加文件夹hello,添加文件hello.html

然后在浏览器中输入:http://localhost:8080/hello/hello.html

2.5Tomcat发布应用

在IDEA中,创建模板 ,选择Java Enterprise,然后确认JDK版本和JavaEE版本,下面Addition中,添加Web Application,然后直接创建就可以了。

运行Tomcat

连接成功,并且会弹出index.jsp的网站

2.6Linux安装Tomcat

1.上传压缩包到路径/home路径:put d:/apache-tomcat-9.0.29.tar.gz

2.解压压缩包:tar -zxvf apache-tomcat-9.0.29.tar.gz

3.进入bin目录下:cd apache-tomcat-9.0.29.tar.gz/bin

4.启动tomcat服务:./startup.sh

5.使用浏览器测试:http://192.168.175.175:8080/

3.Tomcat发布项目

3.1JavaWeb简述

JavaWeb应用是一个全新的应用种类。这类应用程序指供浏览器访问的程序,通常也简称为Web应用。

Web应用开发好后,若想供外界访问,需要把web应用所在目录交给Web服务器管理(Tomcat就是Web服务器之一),这个过程称之为虚似目录的映射。

3.2JavaWeb应用目录结构

WEB-INF--------如果有web.xml或者.class文件时,该目录必须存在,且严格区分大小写。
           --------该目录下的资源,客户端是无法直接访问的。
           --------目录中内容如下:
        classes目录----------------web应用的class文件(加载顺序:我们的class,lib目录中的jar包,tomcat的lib目录中的jar包。优先级依次降低)
        lib目录--------------------web应用所需的jar包(tomcat的lib目录下jar为所有应用共享)
        web.xml-------------------web应用的主配置文件

 3.3JavaWeb应用创建

创建模块JavaEnterprise,然后选择下面的Web Application

3.3.1JavaWeb应用的部署

 Application context:设置默认路径

 下面services可以操作打开Tomcat服务器

 显示此处表示连接成功,然后会默认打开index.jsp页面

 

 3.3.2war包部署

1.在项目的web路径下打war包:jar -cvf myweb.war .

2.将打好的war包剪切到tomcat的webapps路径下

3.启动tomcat服务,自动解压war包

4.通过浏览器验证结果

 3.4Tomcat配置文件

配置默认端口:

Tomcat服务器主配置文件中配置着访问端口,它在配置文件中写的值是:8080。但是它不是Tomcat的默认端口。我们此处说的默认端口是,当使用默认值的时候,端口号可以省略。Tomcat的默认端口是80

server.xml文件

<Connector port="80" protocol="HTTP/1.1"

connectionTimeout="20000" redirectPort="8443" />        

3.5配置虚拟目录

虚拟目录的配置,支持两种方式。第一种是通过在主配置文件中添加标签实现。第二种是通过写一个独立配置文件实现。

方法一:在server.xml的<Host>元素中加一个<Context path="" docBase=""/>

        path:访问资源URI。URI名称可以随便起,但是必须在前面加上一个。

        docBase:资源所在的磁盘物理地址

方法二:写一个独立的xml文件。文件内写一个<Context/>元素

        把该文件放到Tomcat目录 的conf\Catalina\localhost\目录下

        需要注意的是,在使用了独立的配置文件之后,访问资源URI就变成了<b><font color='red'>/+文件的名称</font></b>。而Contextpath属性就失效了。

3.6配置虚拟主机

1.编辑server.xml配置文件,找到<Engine>标签

2.加入以下内容

<Engine name="Catalina" defaultHost="localhost">

        <Host name="www.webdemo.com" appBase="webapps"

                unpackWARs="true" autoDeploy="true">

                <Context path="" docBase="webdemo"/>

        </Host>

<Engine>

name属性:访问虚拟主机的名称

appBase属性:项目存放的路径

unpackWARs属性:是狗自动解压war包

autoDeploy属性:是否自动发布

3.修改hosts文件

c://windows/system32/drivers/etc/hosts

127.0.0.1 www.webdemo.com

4.HTTP协议

4.1协议简介

HTTP的全称是:Hyper Text Transfer Protocol,意为 超文本传输协议。它指的是服务器和客户端之间交互必须遵循的一问一答的规则。形容这个规则:问答机制、握手机制。它规范了请求和响应内容的类型和格式。

HTTP协议是由W3C组织管理和维护的。

4.2HTTP协议组成

4.2.1请求部分

1.组成部分

请求行:永远位于请求的第一行

请求头:从第二行开始,到第一个空行结束

请求空行:就是换行

请求体:POST方式才有请求体

2.方式

GET和POST

 3.请求行

        请求行:GET /myapp/2.html HTTP/1.1

内容说明
GET请求的方式。(还有POST)
/myapp/2.html请求的资源。
HTTP/1.1使用的协议,及协议的版本。

4.请求头

内容说明
Accept告知服务器,客户浏览器所支持的MIME类型。
Accept-Encoding告知服务器,客户浏览器所支持的压缩编码格式。最常用的就是gzip压缩。
Accept-Language告知服务器,客户浏览器所支持的语言。一般都是zh_CN或en_US等。
Referer告知服务器,当前请求的来源。<br/>只有当前请求有来源的时候,才有这个消息头。从地址栏输入的没有来源。<br/>作用:1 投放广告 2 防盗链
Content-Type告知服务器,请求正文的MIME类型。
Content-Length告知服务器,请求正文的长度。
User-Agent浏览器相关信息
Connection: Keep-Alive连接的状态:保持连接
If-Modified-Since告知服务器,客户浏览器缓存文件的最后修改时间。
Cookie(****)会话管理相关,非常的重要。

 5.请求行

        普通换行,用于区分请求头和请求体

6.请求体

        只有POST提交方式才有请求体,用于显示提交参数

4.2.2响应部分

1.响应行

        响应行:HTTP/1.1 200 OK

内容说明
HTTP/1.1使用协议的版本。
200响应状态码
OK状态码描述

        常用状态码介绍:

状态码说明
200一切都OK>
302/307请求重定向(客户端行为,两次请求,地址栏发生改变)
304请求资源未发生变化,使用缓存
404请求资源未找到
500服务器错误

 2.响应消息头

消息头说明
Location请求重定向的地址,常与302,307配合使用。
Server服务器相关信息。
Content-Type告知客户浏览器,响应正文的MIME类型。
Content-Length告知客户浏览器,响应正文的长度。
Content-Encoding告知客户浏览器,响应正文使用的压缩编码格式。常用的gzip压缩。
Content-Language告知客户浏览器,响应正文的语言。zh_CN或en_US等等。
Content-Disposition告知客户浏览器,以下载的方式打开响应正文。
Refresh定时刷新
Last-Modified服务器资源的最后修改时间。
Set-Cookie(***)会话管理相关,非常的重要
Expires:-1服务器资源到客户浏览器后的缓存时间
Catch-Control: no-catch不要缓存,//针对http协议1.1版本
Pragma:no-catch不要缓存,//针对http协议1.0版本

3.响应行

        普通换行,用于区分请求头和请求体

4.响应体

        将资源文件发送给客户端浏览器进行解析

5.静态资源

按照上面创建javaweb项目的方法创建模块,将需要设置静态的文件保存在web目录下

在web.xml中配置默认主页,将下面的代码添加到web-app标签内的末端

<!--修改默认主页-->
    <welcome-file-list>
        <welcome-file>/news/news.html</welcome-file>
    </welcome-file-list>

 再将Application context设置为根目录

5.动态资源

5.1servlet介绍

Servlet翻译成中文是服务端脚本,它是SUN公司推出的一套规范,称为Servlet规范。Servlet规范是JavaEE规范中的一部分。我们可以通过查阅JavaEE规范的API来了解Servlet的基本概念。是运行在Java服务器端的程序,用于接收和响应来自客户端基于HTTP协议的请求。

要想实现Servlet的功能,可以通过实现javax.servlet.Servlet接口或者继承它的实现类。

核心方法:service(),任何客户端的请求都会经过该方法。

5.2实现动态资源

先要导入javax包

找到Tomcat的lib目录的servlet-api.jar。导入项目中

在项目的src文件中创建servlet包,并且创建StudentServlet类,该类实现Servlet接口,并且重写方法

 在service方法中添加语句,因为该方法必须调用

 在web.xml文件中添加如下代码

<?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_3_1.xsd"
         version="3.1">
<!--修改默认主页-->
    <welcome-file-list>
        <welcome-file>/html/frame.html</welcome-file>
    </welcome-file-list>

<!--servlet声明-->
    <servlet>
        <servlet-name>studentServlet</servlet-name>
        <servlet-class>servlet.StudentServlet</servlet-class>
    </servlet>

<!--servlet映射-->
    <servlet-mapping>
        <servlet-name>studentServlet</servlet-name>
        <url-pattern>/studentServlet</url-pattern>
    </servlet-mapping>
</web-app>

 然后进行测试

在网址后加:studentServlet

 

 每次访问该页面,就会调用service方法,在控制台上输出

 5.3执行流程

输入studentServlet网址后,会自动匹配servlet-mapping的url-pattern,再去找到servlet-name,然后找到servlet的servlet-name,再找到servlet-class的实现类,最后会自动的执行service方法

6.Servlet

6.1Servlet介绍

Servlet是一个运行在web服务端的java小程序。它可以用于接收和响应客户端的请求。要想实现Servlet功能,可以实现Servlet接口,继承GenericServlet或者HttpServlet。每次请求都会执行service方法。Servlet还支持配置

6.2Servlet入门 

1.创建JavaWeb项目,然后在src目录下创建servlet类

2.该类继承GenericServlet并且重写service方法

3.在web.xml配置Servlet

4.打开目录无任何显示,由于未编辑对客户端的响应界面,但是控制台会输出service方法的内容

 6.3Servlet执行过程

通过浏览器发送请求,请求首先到达Tomcat服务器,由服务器解析请求URL,然后在部署的应用列表中找到我们的应用。接下来,在我们的应用中找应用里的web.xml配置文件,在web.xml中找到FirstServlet的配置,找到后执行service方法,最后由FirstServlet响应客户浏览器。

 6.4Servlet关系视图

Servlet,实现的方式都是选择继承GenericServlet,在Servlet的API介绍中,它提出了我们除了继承GenericServlet外还可以继承HttpServlet,通过查阅servlet的类视图,我们看到GenericServlet还有一个子类HttpServlet。同时,在service方法中还有参数ServletRequest和ServletResponse

6.5Servlet实现方式

1.实现Servlet接口,接口中的方法必须全部实现。​ 使用此种方式,表示接口中的所有方法在需求方面都有重写的必要。此种方式支持最大程度的自定义。

2.继承GenericServlet,service方法必须重写,其他方可根据需求,选择性重写。使用此种方式,表示只在接收和响应客户端请求这方面有重写的需求,而其他方法可根据实际需求选择性重写,使我们的开发Servlet变得简单。但是,此种方式是和HTTP协议无关的。

 3.继承HttpServlet,它是javax.servlet.http包下的一个抽象类,是GenericServlet的子类。如果我们选择继承HttpServlet时,只需要重写doGet和doPost方法,不要覆盖service方法。 使用此种方式,表示我们的请求和响应需要和HTTP协议相关。

 通过访问网站,控制台输入内容

6.6Servlet生命周期

对象的生命周期,就是对象从生到死的过程,即:出生——活着——死亡。用更偏向 于开发的官方说法就是对象创建到销毁的过程。

出生:请求第一次到达Servlet时,对象就创建出来,并且初始化成功。只出生一次,就放到内存中。

活着:服务器提供服务的整个过程中,该对象一直存在,每次只是执行service方法。

死亡:当服务停止时,或者服务器宕机时,对象消亡。

public class ServletDemo03 extends HttpServlet {


    //对象出生
    @Override
    public void init() throws ServletException {
        System.out.println("对象创建并初始化...");

    }
    //对象服务
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("接收到了客户端的请求...");
    }

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

    //对象销毁

    @Override
    public void destroy() {
        System.out.println("对象销毁...");
    }
}

 

在不断的刷新过程中,会持续在控制台上输出请求语句,即doGet方法的调用

在关闭Tomcat后,对象死亡,自动调用destory方法

 

通过分析Servlet的生命周期我们发现,它的实例化和初始化只会在请求第一次到达Servlet时执行,而销毁只会在Tomcat服务器停止时执行,由此我们得出一个结论,Servlet对象只会创建一次,销毁一次。所以,Servlet对象只有一个实例。如果一个对象实例在应用中是唯一的存在,那么我们就说它是单实例的,即运用了单例模式。

6.7Servlet线程安全

/*
    Servlet线程安全
 */
public class ServletDemo04 extends HttpServlet{
    //1.定义用户名成员变量
    //private String username = null;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = null;
        //synchronized (this) {
            //2.获取用户名
            username = req.getParameter("username");

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //3.获取输出流对象
            PrintWriter pw = resp.getWriter();

            //4.响应给客户端浏览器
            pw.print("welcome:" + username);

            //5.关流
            pw.close();
        //}
    }

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

启动两个浏览器,输入不同的参数,访问之后发现输出的结果都是一样,所以出现线程安全问题

 在Servlet中定义了类成员之后,多个浏览器都会共享类成员的数据。其实每一个浏览器端发送请求,就代表是一个线程,那么多个浏览器就是多个线程,所以测试的结果说明了多个线程会共享Servlet类成员中的数据,其中任何一个线程修改了数据,都会影响其他线程。因此,我们可以认为Servlet它不是线程安全的。

 解决这个问题也非常简单,就是在Servlet中定义类成员要慎重。如果类成员是共用的,并且只会在初始化时赋值,其余时间都是获取的话,那么是没问题。如果类成员并非共用,或者每次使用都有可能对其赋值,那么就要考虑线程安全问题了,把它定义到doGet或者doPost方法里面去就可以了。

1.将成员变量定义到doGet方法中

2.对可能出现共享数据的代码块进行synchronized(this)封锁进程

6.8Servlet映射方式

1.具体名称的方式。访问的资源路径必须和映射配置完全相同

2./开头+通配符的方式。只要符合目录结构即可,不用考虑结尾是什么。

3.通配符+固定格式结尾的方式。只要符合固定结尾格式即可,不用考虑前面的路径。

6.8.1映射方式

1.

    <servlet>
        <servlet-name>servletDemo05</servlet-name>
        <servlet-class>servlet.ServletDemo05</servlet-class>
    </servlet>
    <!--    -->
    <servlet-mapping>
        <servlet-name>servletDemo05</servlet-name>
        <url-pattern>/servletDemo05</url-pattern>
    </servlet-mapping>

  

2.

    <servlet>
        <servlet-name>servletDemo05</servlet-name>
        <servlet-class>servlet.ServletDemo05</servlet-class>
    </servlet>
    <!--    -->
    <servlet-mapping>
        <servlet-name>servletDemo05</servlet-name>
        <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>

3.

 3.

    <servlet>
        <servlet-name>servletDemo05</servlet-name>
        <servlet-class>servlet.ServletDemo05</servlet-class>
    </servlet>
    <!--    -->
    <servlet-mapping>
        <servlet-name>servletDemo05</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

 6.8.2多路径映射

给一个Servlet配置多个访问映射,从而可以根据不同请求URL实现不同的功能。

public class ServletDemo06 extends HttpServlet {
    //对象服务
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.定义一个商品金额
        int money=1000;

        //2.获取访问的资源路径
        String path = req.getRequestURI();

        path = path.substring(path.lastIndexOf("/"));

        //3.条件判断
        if("/vip".equals(path)){
            System.out.println("商品原价为:"+money+"。优惠后价格为:"+(0.9*money));
        }
        else if("/vvip".equals(path)){
            System.out.println("商品原价为:"+money+"。优惠后价格为:"+(0.5*money));
        }
        else{
            System.out.println("商品原价为:"+money+"。");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
        <servlet>
            <servlet-name>servletDemo06</servlet-name>
            <servlet-class>servlet.ServletDemo06</servlet-class>
        </servlet>
        <!--    -->
        <servlet-mapping>
            <servlet-name>servletDemo06</servlet-name>
            <url-pattern>/svip/*</url-pattern>
        </servlet-mapping>

 6.8.3Servlet创建时机

1.请求第一次访问是创建Servlet,它的优势就是减少了对服务器内存的浪费,因为那些一直没有被访问过的Servlet对象都没有创建,因此也提高了服务器的启动时间。而它的弊端就是,如果有一些要在应用加载时就做的初始化操作,它都没法完成,从而要考虑其他技术实现。

2.应用加载时创建Servlet,它的优势是在服务器启动时,就把需要的对象都创建完成了,从而在使用的时候减少了创建对象的时间,提高了首次执行的效率。它的弊端也同样明显,因为在应用加载时就创建了Servlet对象,因此,导致内存中充斥着大量用不上的Servlet对象,造成了内存的浪费。

servlet的load-on-startup标签下,如果正整数代表服务器加载时创建,值越小,优先级越高。负整数或不写代表第一次访问时创建

<!--配置ServletDemo3-->
<servlet>
    <servlet-name>servletDemo3</servlet-name>
    <servlet-class>com.itheima.web.servlet.ServletDemo3</servlet-class>
    <!--配置Servlet的创建顺序,当配置此标签时,Servlet就会改为应用加载时创建
        配置项的取值只能是正整数(包括0),数值越小,表明创建的优先级越高
    -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>servletDemo3</servlet-name>
    <url-pattern>/servletDemo3</url-pattern>
</servlet-mapping>

 6.8.4默认Servlet

默认Servlet是由服务器提供的一个Servlet,它配置在Tomcat的conf目录下的web.xml中。

 它的映射路径是<url-pattern>/<url-pattern>,我们在发送请求时,首先会在我们应用中的web.xml中查找映射配置,找到就执行,这块没有问题。但是当找不到对应的Servlet路径时,就去找默认的Servlet,由默认Servlet处理。所以,一切都是Servlet。

7.ServletConfig

7.1基本概念

它是Servlet的配置参数对象,在Servlet规范中,允许为每个Servlet都提供一些初始化配置。所以,每个Servlet都一个自己的ServletConfig。它的作用是在Servlet初始化期间,把一些配置信息传递给Servlet。

由于它是在初始化阶段读取了web.xml中为Servlet准备的初始化配置,并把配置信息传递给Servlet,所以生命周期与Servlet相同。这里需要注意的是,如果Servlet配置了<load-on-startup>1</load-on-startup>,那么ServletConfig也会在应用加载时创建。

7.2ServletConfig使用

配置方式:

在<servlet>标签中,通过<init-param>标签来配置。有两个子标签。

<param-name>:代表初始化参数的key

<param-value>:代表初始化参数的value

7.2.1配置ServletConfig

<?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_3_1.xsd"
         version="3.1">
<!--配置servlet-->
    <servlet>
        <servlet-name>servletConfigDemo</servlet-name>
        <servlet-class>servlet.ServletConfigDemo</servlet-class>
        <!-- 配置servletconfig -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>desc</param-name>
            <param-value>This is ServletConfig</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletConfigDemo</servlet-name>
        <url-pattern>/servletConfigDemo</url-pattern>
    </servlet-mapping>
</web-app>

7.2.2ServletConfig方法

package servlet;

import javax.servlet.ServletConfig;
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;
import java.util.Enumeration;

/*
   ServletConfig
    */
public class ServletConfigDemo extends HttpServlet {
    //1.声明ServletConfig
    private ServletConfig config;

    //2.通过init方法对config赋值
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config=config;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //3.常用方法
        //根据key获取value
        config.getInitParameter("encoding");

        //获取所有的key
        Enumeration<String> keys = config.getInitParameterNames();
        while(keys.hasMoreElements()){
            //获取每一个key
            String key = keys.nextElement();
            //根据key获取value
            String value = config.getInitParameter(key);

            System.out.println(key+"   "+value);
        }
        //获取Servlet名称
        String servletName = config.getServletName();
        System.out.println(servletName);

        //获取servletContext对象
        ServletContext servletContext = config.getServletContext();
        System.out.println(servletContext);
    }

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

8.ServletContext

8.1基本概念

ServletContext对象,它是应用上下文对象。每一个应用有且只有一个ServletContext对象。它可以实现让应用中所有Servlet间的数据共享。

生命周期:应用一加载则创建,应用被停止则销毁

作用:可以配置和获得应用的全局初始化参数,可以实现Servlet之间的数据共享

域对象的概念,它指的是对象有作用域,即有作用范围。作用,域对象可以实现数据共享。不同作用范围的域对象,共享数据的能力不一样。

8.2ServletContext使用

配置方式:

在<web-app>标签中,通过<context-param>标签来配置。有两个子标签。

<param-name>:代表全局初始化参数的key

<param-value>:代表全局初始化参数的value

8.2.1配置ServletContext

<?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_3_1.xsd"
         version="3.1">
<!--配置servlet-->
    <servlet>
        <servlet-name>servletConfigDemo</servlet-name>
        <servlet-class>servlet.ServletConfigDemo</servlet-class>
        <!-- 配置servletconfig -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>desc</param-name>
            <param-value>This is ServletConfig</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletContexDemo</servlet-name>
        <url-pattern>/servletContexDemo</url-pattern>
    </servlet-mapping>

    <!--配置Servlet-->
    <servlet>
        <servlet-name>servletContexDemo</servlet-name>
        <servlet-class>servlet.ServletContextDemo</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletConfigDemo</servlet-name>
        <url-pattern>/servletConfigDemo</url-pattern>
    </servlet-mapping>
    <!--配置ServletContext-->
    <context-param>
        <param-name>globalEncoding</param-name>
        <param-value>UTF-8</param-value>
    </context-param>
    <context-param>
        <param-name>globalDesc</param-name>
        <param-value>This is ServletContext</param-value>
    </context-param>
</web-app>

8.2.2常用方法

package 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 ServletContextDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取ServletContext对象
        ServletContext servletContext = getServletContext();

        //2.获取全局配置参数
        String globalDesc = servletContext.getInitParameter("globalDesc");
        System.out.println(globalDesc);

        //获取应用的虚拟目录
        String contextPath = servletContext.getContextPath();
        System.out.println(contextPath);

        //根据虚拟目录获取绝对路径
        String realPath = servletContext.getRealPath("/");
        System.out.println(realPath);
    }

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


    }
}

8.3数据共享

9. 注解开发Servlet

9.1自动注解

创建JavaWeb项目,并且选择JavaEE8,在删除web.xml

package servlet;

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;


@WebServlet("/servletDemo01")
public class ServletDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet01执行了");
    }

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

 自动注解解析

/**
 * WebServlet注解
 * @since Servlet 3.0 (Section 8.1.1)
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {

    /**
     * 指定Servlet的名称。
     * 相当于xml配置中<servlet>标签下的<servlet-name>
     */
    String name() default "";

    /**
     * 用于映射Servlet访问的url映射
     * 相当于xml配置时的<url-pattern>
     */
    String[] value() default {};

    /**
     * 相当于xml配置时的<url-pattern>
     */
    String[] urlPatterns() default {};

    /**
     * 用于配置Servlet的启动时机
     * 相当于xml配置的<load-on-startup>
     */
    int loadOnStartup() default -1;

    /**
     * 用于配置Servlet的初始化参数
     * 相当于xml配置的<init-param>
     */
    WebInitParam[] initParams() default {};

    /**
     * 用于配置Servlet是否支持异步
     * 相当于xml配置的<async-supported>
     */
    boolean asyncSupported() default false;

    /**
     * 用于指定Servlet的小图标
     */
    String smallIcon() default "";

    /**
     * 用于指定Servlet的大图标
     */
    String largeIcon() default "";

    /**
     * 用于指定Servlet的描述信息
     */
    String description() default "";

    /**
     * 用于指定Servlet的显示名称
     */
    String displayName() default "";
}

9.2手动注解

在使用Servlet3.1版本的规范时,脱离了web.xml进行注解开发,它除了支持使用注解的配置方式外,还支持纯手动创建Servlet容器的方式。要想使用的话,必须遵循它的编写规范。它是从Servlet3.0规范才开始引入的,加入了一个新的接口:

package javax.servlet;

import java.util.Set;

/**
 * 初始化Servlet容器必须实现此接口
 * 它是Servlet3.0规范提供的标准接口
 * @since Servlet 3.0
 */
public interface ServletContainerInitializer {
     /**
     * 启动容器时做一些初始化操作,例如注册Servlet,Filter,Listener等等。
 	 * @since Servlet 3.0
     */
    void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException;
}

创建JavaWeb项目,并且选择JavaEE8,在删除web.xml

package servlet;

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 ServletDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet02执行了");
    }

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

在脱离web.xml时,要求在src目录下包含一个META-INF目录,位置和及字母都不能改变,且严格区分大小写。在目录中创建一个名称为javax.servlet.ServletContainerInitializer的文件,里面写实现了ServletContainerInitializer接口的全限定类名。

在该文件下输入:servlet.MyRegister

package servlet;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import java.util.Set;

/*
    注册配置Servlet的功能类
 */

public class MyRegister implements ServletContainerInitializer {
    @Override
    public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
        //完成Servlet的创建h和配置
        //1.创建ServletDemo02对象
        ServletDemo02 servletDemo02 = new ServletDemo02();
        //2.在ServletContext对象中添加Servlet,并得到Servlet的动态配置
        ServletRegistration.Dynamic registration = servletContext.addServlet("servletDemo02", servletDemo02);
        //3.配置Servlet
        registration.addMapping("/servletDemo02");//访问资源的路径
        registration.setLoadOnStartup(1); //Servlet加载时机
    }
}

10.应用-学生信息系统

本质就是通过html发送一个请求,把表单中填写的数据带到服务器端。因为每个使用者在表单填写的内容不一样,所有最终存起来的也就不一样了。

添加学生信息界面:addStudent.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>保存学生信息</title>
</head>
<body>
    <form action="/stu/studentServlet" method="get" autocomplete="off">
        学生姓名:<input type="text" name="StudentName"><br/>
        学生年龄:<input type="number" name="StudentAge"><br/>
        学生成绩:<input type="number" name="StudentScore"><br/>
        <button type="submit">保存</button>
    </form>
</body>
</html>

添加StudentServlet类:StudentServlet.class

package servlet;

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

public class StudentServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取表单数据
        String studentName = req.getParameter("StudentName");
        String studentAge = req.getParameter("StudentAge");
        String studentScore = req.getParameter("StudentScore");

        //采用字符输出流
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("Phase02_04_07Test\\stu.txt",true));
        bufferedWriter.write(studentName+","+studentAge+","+studentScore);
        bufferedWriter.newLine();
        bufferedWriter.close();

        //响应客户端浏览器
        PrintWriter printWriter = resp.getWriter();
        printWriter.println("Save Success!");
        printWriter.close();
    }

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

修改servlet配置:webxml

<?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">
<!--    修改默认主页-->
    <welcome-file-list>
        <welcome-file>/addStudent.html</welcome-file>
    </welcome-file-list>
<!--    配置Servlet-->
    <servlet>
        <servlet-name>studentServlet</servlet-name>
        <servlet-class>servlet.StudentServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>studentServlet</servlet-name>
        <url-pattern>/studentServlet</url-pattern>
    </servlet-mapping>

</web-app>

 11.请求请求

 11.1概述

请求,顾明思议,就是使用者希望从服务器端索取一些资源,向服务器发出询问。

请求对象,就是在JavaEE工程中,用于发送请求的对象。我们常用的对象就是ServletRequest和HttpServletRequest,它们的区别就是是否和HTTP协议有关。

11.2方法

11.2.1 获取各种路径

package servlet;

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.util.function.DoubleToIntFunction;

@WebServlet("/servlerDemo01")
public class ServletDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取虚拟目录:getContextPath()
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        //2.获取Servlet映射路径getServletPath():
        String servletPath = req.getServletPath();
        System.out.println(servletPath);
        //3.获取访问者getRemoteUser():
        String remoteAddr = req.getRemoteAddr();
        System.out.println(remoteAddr);
        //4.请求消息的数据getQueryString():
        String queryString = req.getQueryString();
        System.out.println(queryString);
        //5.获取统一资源标识符getRequestURI():
        String requestURI = req.getRequestURI();
        System.out.println(requestURI);
        //6.获取统一资源定位符getRequestURL():
        StringBuffer requestURL = req.getRequestURL();
        System.out.println(requestURL);

    }

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

 

11.2.2 获取请求头

package servlet;

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.util.Enumeration;

@WebServlet("/servletDemo02")
public class ServletDemo02 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.根据请求头获取一个值
        String connection = req.getHeader("connection");
        System.out.println(connection);
        System.out.println("------------------");
        //2.根据请求头名称获取多个值
        Enumeration<String> values = req.getHeaders("accept-encoding");
        while (values.hasMoreElements()){
            String value = values.nextElement();
            System.out.println(value);
        }
        System.out.println("------------------");
        //3.获取所有的请求头的名称
        Enumeration<String> headerNames = req.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            System.out.println(name+"..."+values);
        }

    }

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

 11.2.3获取请求参数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="/request/servletDemo03" method="get" autocomplete="off">
        姓名:<input type="text" name="username"> <br>
        密码:<input type="password" name="password"> <br>
        爱好:<input type="checkbox" name="hobby" value="study">学习
              <input type="checkbox" name="hobby" value="game">游戏 <br>
        <button type="submit">注册</button>
    </form>
</body>
</html>
package servlet;

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.util.Enumeration;
import java.util.Map;

@WebServlet("/servletDemo03")
public class ServletDemo03 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.根据名称获取数据
        String username = req.getParameter("username");
        System.out.println(username);
        String password = req.getParameter("password");
        System.out.println(password);
        System.out.println("_______________________");
        //2.根据名称获取所有数据
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
        System.out.println("________________________");

        //3.获取所有名称
        Enumeration<String> parameterNames = req.getParameterNames();
        while(parameterNames.hasMoreElements()){
            String s = parameterNames.nextElement();
            System.out.println(s);
        }
        System.out.println("________________________");

        //4.获取所有参数的键值对
        Map<String, String[]> parameterMap = req.getParameterMap();
        for (String key : parameterMap.keySet()) {
            String[] values = parameterMap.get(key);
            System.out.print(key+":");
            for (String value : values) {
                System.out.print(value+",");
            }
            System.out.println("");
        }

    }

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

 

 

 11.2.4获取请求参数并封装对象

1.手动封装

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="/request/servletDemo04" method="get" autocomplete="off">
        姓名:<input type="text" name="username"> <br>
        密码:<input type="password" name="password"> <br>
        爱好:<input type="checkbox" name="hobby" value="study">学习
              <input type="checkbox" name="hobby" value="game">游戏 <br>
        <button type="submit">注册</button>
    </form>
</body>
</html>

package servlet;

import bean.Student;

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.util.Enumeration;
import java.util.Map;
/*
封装对象:手动封装
 */
@WebServlet("/servletDemo04")
public class ServletDemo04 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取所有数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobby");
        //2.封装学生对象
        Student stu = new Student(username,password,hobbies);

        //3.输出对象
        System.out.println(stu);

    }

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

 

 2.反射封装

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="/request/servletDemo05" method="get" autocomplete="off">
        姓名:<input type="text" name="username"> <br>
        密码:<input type="password" name="password"> <br>
        爱好:<input type="checkbox" name="hobby" value="study">学习
              <input type="checkbox" name="hobby" value="game">游戏 <br>
        <button type="submit">注册</button>
    </form>
</body>
</html>
package servlet;

import bean.Student;

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.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Map;

/*
封装对象:反射封装
 */
@WebServlet("/servletDemo05")
public class ServletDemo05 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取所有数据
        Map<String, String[]> map = req.getParameterMap();

        //2.封装学生对象
        Student stu = new Student();

        for (String key : map.keySet()) {
            String[] value = map.get(key);
            try {
                //获取Student对象的属性描述器
                PropertyDescriptor pd = new PropertyDescriptor(key,stu.getClass());
                //获取set方法
                Method writeMethod = pd.getWriteMethod();
                //执行方法
                if(value.length>1){
                    writeMethod.invoke(stu,(Object)value);
                }
                else{
                    writeMethod.invoke(stu,value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //3.输出对象
        System.out.println(stu);
    }

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

 3.工具类封装

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="/request/servletDemo06" method="get" autocomplete="off">
        姓名:<input type="text" name="username"> <br>
        密码:<input type="password" name="password"> <br>
        爱好:<input type="checkbox" name="hobby" value="study">学习
              <input type="checkbox" name="hobby" value="game">游戏 <br>
        <button type="submit">注册</button>
    </form>
</body>
</html>
package servlet;

import bean.Student;
import org.apache.commons.beanutils.BeanUtils;

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.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Map;

/*
封装对象:工具类封装
 */
@WebServlet("/servletDemo06")
public class ServletDemo06 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取所有数据
        Map<String, String[]> map = req.getParameterMap();

        //2.封装学生对象
        Student stu = new Student();

        try {
            BeanUtils.populate(stu,map);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //3.输出对象
        System.out.println(stu);
    }

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

 11.2.5流对象获取请求信息

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="/request/servletDemo07" method="post" autocomplete="off">
        姓名:<input type="text" name="username"> <br>
        密码:<input type="password" name="password"> <br>
        爱好:<input type="checkbox" name="hobby" value="study">学习
              <input type="checkbox" name="hobby" value="game">游戏 <br>
        <button type="submit">注册</button>
    </form>
</body>
</html>
package servlet;

import bean.Student;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

/*
通过流对象获取数据
 */
@WebServlet("/servletDemo07")
public class ServletDemo07 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //字符流
//        BufferedReader br = req.getReader();
//        String line;
//        while((line=br.readLine())!=null){
//            System.out.println(line);
//        }
//    }

        //字节流
        ServletInputStream is = req.getInputStream();
        byte[] arr = new byte[1024];
        int len;
        while ((len = is.read(arr)) != -1) {
            System.out.println(new String(arr, 0, len));
        }
        // is.close();
    }


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

 11.2.6中文乱码问题的解决

1.GET方式

GET方式请求的正文是在地址栏中,在Tomcat8.5版本及以后,Tomcat服务器已经帮我们解决了,所以不会有乱码问题了。

而如果我们使用的不是Tomcat服务器,或者Tomcat的版本是8.5以前,那么GET方式仍然会有乱码问题,解决方式如下:

/**
 * 在Servlet的doGet方法中添加如下代码
 */
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
   

        /*
         * GET方式:正文在地址栏
         * username=%D5%C5%C8%FD
         * %D5%C5%C8%FD是已经被编过一次码了
         *
         * 解决办法:
         * 	 使用正确的码表对已经编过码的数据进行解码。
         * 		就是把取出的内容转成一个字节数组,但是要使用正确的码表。(ISO-8859-1)
         * 	 再使用正确的码表进行编码
         * 		把字节数组再转成一个字符串,需要使用正确的码表,是看浏览器当时用的是什么码表
         */
        String username = request.getParameter("username");
        byte[] by = username.getBytes("ISO-8859-1");
        username = new String(by,"GBK");

        //输出到浏览器:注意响应的乱码问题已经解决了
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write(username);
}

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

2.POST方式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
    <form action="/request/servletDemo08" method="post" autocomplete="off">
        姓名:<input type="text" name="username"> <br>
        密码:<input type="password" name="password"> <br>
        爱好:<input type="checkbox" name="hobby" value="study">学习
              <input type="checkbox" name="hobby" value="game">游戏 <br>
        <button type="submit">注册</button>
    </form>
</body>
</html>
package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
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.util.Enumeration;

/*
中文乱码
 */
@WebServlet("/servletDemo08")
public class ServletDemo08 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");

        String username = req.getParameter("username");
        System.out.println(username);
    }


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

 11.3请求转发

请求域:可以在一次请求范围内进行共享数据

一般用于请求转发的多个资源中共享数据

 请求对象操作共享数据方法:

        void setAttribute(String name,Object value):向请求域对象中存储数据

        Object getAttribute(String name):通过名称获取请求域对象中的数据

        void removeAttribute(String name) :通过名称移除请求域对象中的数据

请求转发:客户端的一次请求到达后,发现需要借助其他Servlet来实现功能。

特点:浏览器地址栏不变。与对象中的数据不丢失。负责转发的Servlet转发前后的响应正文回丢失。由转发的目的地来响应客户端。

package servlet;

import javax.servlet.RequestDispatcher;
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.util.Enumeration;

/*
请求转发
 */
@WebServlet("/servletDemo09")
public class ServletDemo09 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置共享数据
        req.setAttribute("encoding","gdk");

        //获取请求调度对象
        RequestDispatcher rd = req.getRequestDispatcher("/servletDemo10");
        //实现转发功能
        rd.forward(req,resp);
    }


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

import javax.servlet.RequestDispatcher;
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.util.Enumeration;

/*
请求转发
 */
@WebServlet("/servletDemo10")
public class ServletDemo10 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取共享数据
        Object encoding = req.getAttribute("encoding");
        System.out.println(encoding);
        System.out.println("servletDemo10已执行....");
    }


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

11.4请求包含

请求包含:可以合并其他Servlet中的功能一起响应给客户端

特点:浏览器地址不变,域对象中的数据不丢失,被包含的Servlet响应头会丢失。负责转发的Servlet转发前后的响应正文不会丢失由转发的目的地来响应客户端。

package servlet;

import javax.servlet.RequestDispatcher;
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.util.Enumeration;

/*
请求包含
 */
@WebServlet("/servletDemo11")
public class ServletDemo11 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("ServletDemo11执行了....");

        RequestDispatcher rd = req.getRequestDispatcher("/servletDemo12");

        rd.include(req,resp);
    }


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

import javax.servlet.RequestDispatcher;
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.util.Enumeration;

/*
请求包含
 */
@WebServlet("/servletDemo12")
public class ServletDemo12 extends HttpServlet {

    private Enumeration<String> values;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("ServletDemo12执行了....");
    }


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

12.响应对象

12.1概述

响应,它表示了服务器端收到请求,同时也已经处理完成,把处理的结果告知用户。简单来说,指的就是服务器把请求的处理结果告知客户端。在B/S架构中,响应就是把结果带回浏览器。

响应对象,顾名思义就是用于在JavaWeb工程中实现上述功能的对象。

12.2状态码

200:成功

302:重定向

304:请求资源未变化,使用缓存

400:请求时错误,常见于请求参数错误

404:请求资源未找到

405:请求方式不支持

500:服务器错误

状态码说明
1xx消息
2xx成功
3xx重定向
4xx客户端错误
5xx服务器错误

12.3方法

12.3.1字节流响应消息

ServletOutputStream getOutputStream():获取响应字节输出流对象

void setContenType("text/html;charset=UTF-8"):设置响应内容类型,解决中文乱码问题

package servlet;

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

/*
字节流响应消息
 */
@WebServlet("/servletDeom01")
public class ServletDeom01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取字节流输出对象
        ServletOutputStream os = resp.getOutputStream();

        //2.定义一个消息
        String str = "你好!";

        //3.通过字节流对象输出
        os.write(str.getBytes());
    }

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

 浏览器的编码格式为GBK,而IDEA的编码格式为UTF-8,通过str.Butes(),自动的将字符串转化为系统的字符集格式。

package servlet;

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

/*
字节流响应消息
 */
@WebServlet("/servletDeom01")
public class ServletDeom01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取字节流输出对象
        ServletOutputStream os = resp.getOutputStream();

        //2.定义一个消息
        String str = "你好!";

        //3.通过字节流对象输出
        os.write(str.getBytes("UTF-8"));
    }

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

 通过转化到UTF-8的格式,而浏览器的格式还是GBK,导致出现中文乱码

package servlet;

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

/*
字节流响应消息
 */
@WebServlet("/servletDemo01")
public class ServletDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");

        //1.获取字节流输出对象
        ServletOutputStream os = resp.getOutputStream();

        //2.定义一个消息
        String str = "你好!";

        //3.通过字节流对象输出
        os.write(str.getBytes("UTF-8"));
    }

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

设置浏览器的消息内容未UTF-8的编码格式显示

 12.3.2字符流响应消息

PrintWriter getWriter():获取响应字符输出流对象

void setContenTyp("text/html;charset=UTF-8"):设置响应内容类型,解决中文乱码问题

package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
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;

/*
字符流响应消息
 */
@WebServlet("/servletDemo02")
public class ServletDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");

        //1.获取字符流输出对象
        PrintWriter pw = resp.getWriter();

        //2.定义一个消息
        String str = "你好!";

        //3.通过字节流对象输出
        pw.write(str);
    }

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

 12.3.3响应图片

package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

/*
响应图片
 */
@WebServlet("/servletDemo03")
public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;ServletDemo01charset=UTF-8");

        //1.创建字节输入流对象,关联图片路径
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("/img/qq.png"));

        //2.通过响应对象获取字节输出流对象
        ServletOutputStream os = resp.getOutputStream();


        //3.循环读写
        byte[] arr = new byte[1024];
        int len;
        while((len=bis.read(arr))!=-1){
            os.write(arr,0,len);
        }

        //4/释放资源
        bis.close();
    }

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

需要更改图片的获取路径 ,web项目不能直接访问该路径下的文件,需要访问该文件的绝对路径!!

package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

/*
响应图片
 */
@WebServlet("/servletDemo03")
public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通过文件的绝对路径获取绝对路径
        String realPath = getServletContext().getRealPath("/img/qq.png");

        //1.创建字节输入流对象,关联图片路径
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath));

        //2.通过响应对象获取字节输出流对象
        ServletOutputStream os = resp.getOutputStream();


        //3.循环读写
        byte[] arr = new byte[1024];
        int len;
        while((len=bis.read(arr))!=-1){
            os.write(arr,0,len);
        }

        //4/释放资源
        bis.close();
    }

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

12.3.4设置缓存 

缓存:对于不经常变化的数据,我们可以设置合理缓存时间,以避免浏览器频繁请求服务器。以此来提高效率!

void setDateHeader(String name,long time):设置消息头添加缓存

package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

/*
设置缓存
 */
@WebServlet("/servletDemo04")
public class ServletDemo04 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通过文件的绝对路径获取绝对路径
        String  news="这是一条很火爆的新闻";

        //设置缓存 1小时的缓存时间
        resp.setDateHeader("Expires",System.currentTimeMillis()+1*60*60*1000);

        //设置编码格式
        resp.setContentType("text/html;charset=UTF-8");

        //输出数据
        resp.getWriter().write(news);

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

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

 刷新页面属于重新请求服务器,而直接查找地址是直接访问缓存

12.3.5定时刷新

void setHeader(String name,String value):设置消息头定时刷新

login001.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <form action="#" method="get" autocomplete="off">
        姓名:<input type="text" name="username"> <br>
        密码:<input type="password" name="username"> <br>
        <button type="submit">登录</button>
    </form>
</body>
</html>
package servlet;

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

/*
定时刷新
 */
@WebServlet("/servletDemo05")
public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String str = "您的用户名或密码错误,三秒后自动跳转到登陆页面....";

        //设置编码格式
        resp.setContentType("text/html;charset=UTF-8");
        //写数据
        resp.getWriter().write(str);

        //定时刷新
        resp.setHeader("Refresh","3;URL=/response/login001.html");
    }

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

 12.3.6请求重定向

请求重定向:客户端的一次请求到达后,发现需要借助其他Servlet来实现功能

特点:浏览器地址栏会发生变化,两次请求,请求域对象中不能共享数据,可以重定向到其他服务器

重定向实现原理:设置响应状态码302【resp.setStatus(302);】

设置响应的资源路径(资源去哪里)【resp.setHeader("localtion","/response/responseDemo07");】

重定向方法:void sendRedirect(String name):设置重定向

package servlet;

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;

/*
请求重定向
 */
@WebServlet("/servletDemo06")
public class ServletDemo06 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("ServeltDemo06执行了...");

        //设置请求域共享数据
        req.setAttribute("username","zhangsan");

        //设置重定向
        resp.sendRedirect(req.getContextPath()+"/servletDemo07");
    }

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

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;

/*
请求重定向
 */
@WebServlet("/servletDemo07")
public class ServletDemo07 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("ServeltDemo07执行了...");

        //获取共享数据
        Object username = req.getAttribute("username");

        System.out.println(username);
    }

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

由于是两次请求,请求域中不能共享数据! 

需要共享数据则使用请求转发,如果不需要则使用重写

12.3.7文件下载

package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

/*
请求重定向
 */
@WebServlet("/servletDemo08")
public class ServletDemo08 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.创建字节输入流对象,关联读取的文件
        String realPath = getServletContext().getRealPath("/img/qq.png");
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath));

        //2.设置响应头支持的类型
        /*
        Content-Type:消息头   支持的类型
        application/octet-stream:消息头参数  应用的类型为字节流
         */
        resp.setHeader("Content-Type","application/octet-stream");

        //3.设置响应头以下载方式打开附件
        /*
        Content-Disposition:消息头名称  处理的形式
        attachment;filename=qq.png:消息头参数 附件形式进行处理  指定下载文件的名称
         */
        resp.setHeader("Content-Disposition","attachment;filename=qq.png");

        //4.获取字节输出流对象
        ServletOutputStream os = resp.getOutputStream();

        //5.循环读写
        byte[] arr=new byte[1024];
        int len;
        while((len=bis.read(arr))!=-1){
            os.write(arr,0,len);
        }

        //6.释放资源
        bis.close();


    }

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

 12.3.8多个文件下载

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
</head>
<body>
    <h1>请点击以下链接下载对应的资源</h1>
    <a href="/demo/ServletDemo09?filename=day48__Redis.pdf">下载day48__Redis.pdf</a><br/>
    <a href="/demo/ServletDemo09?filename=JSP.zip">下载JSP原型.zip</a><br/>
    <a href="/demo/ServletDemo09?filename=redis.bmp">下载redis解压失败.bmp</a><br/>
</body>
</html>
package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

/*
请求重定向
 */
@WebServlet("/ServletDemo09")
public class ServletDemo09 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String fileName = req.getParameter("filename");
        /*   fileName = new String(fileName.getBytes("iso-8859-1"), "utf-8");*/
        //1.创建字节输入流,关联读取的文件
        //获取文件的绝对路径
        String realPath = getServletContext().getRealPath("/download/"+fileName);
        //创建字节输出流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath));

        //2.设置响应头支持的类型  应用支持的类型为字节流
        /*
            Content-Type 消息头名称   支持的类型
            application/octet-stream   消息头参数  应用类型为字节流
         */
        resp.setHeader("Content-Type","application/octet-stream");

        //3.设置响应头以下载方式打开  以附件形式处理内容
        /*
            Content-Disposition  消息头名称  处理的形式
            attachment;filename=  消息头参数  附件形式进行处理
         */
        resp.setHeader("Content-Disposition","attachment;filename="+fileName);

        //4.获取字节输出流对象
        ServletOutputStream sos = resp.getOutputStream();

        //5.循环读写文件
        byte[] arr = new byte[1024];
        int len;
        while((len = bis.read(arr)) != -1) {
            sos.write(arr,0,len);
        }

        //6.释放资源
        bis.close();
        sos.close();
    }

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

---------------------------------------------------------------------------------------------------------------------------------

内容有部分存在书籍、课堂、网络记录,如有雷同纯属巧合

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值