JavaWeb开发知识总结(HttpServletRequest,HttpServletResponse)

JavaWeb服务器开发知识总结(HttpServletRequest,HttpServletResponse)

1. ServletConfig类

ServletConfig类是Servlet容器进行该Servlet对象初始化时为该类创建的配置对象.该类存储了Servlet类的配置信息,在Servlet对象中可以获得自身的ServletConfig配置对象.

每一个Servlet类初始化时都会创建一个ServletConfig配置对象,该配置对象只属于该Servlet对象.

ServletConfig对象随着Servlet对象创建而被创建,随着Servlet对象的销毁而被销毁.

ServletConfig类是用来获取该Servlet类的配置参数,不能更改配置信息.

1.1 ServletConfig类常用方法:

String getServletName():获取该Servlet类在web.xml中配置在标签中属性值;
String getInitParameter(String name):获取该Servlet类初始化时的指定名称的参数值;
public java.util.Enumeration getInitParameterNames():获取该Servlet类的所有初始值的名称,以枚举类型返回;
ServletContext getServletContext():获取该项目ServletContext对象的引用.

1.2 ServletConfig获取Servlet在web.xml中的配置信息:



<servlet>
  <servlet-name>ServletDemoservlet-name>
  <servlet-class>com.itheima.download.ServletDemoservlet-class>
  
  <init-param>
    
    <param-name>参数名1param-name>
    <param-value>参数值1param-value>
  init-param>
  
  <init-param>
    <param-name>参数名2param-name>
    <param-value>参数值2param-value>
  init-param>
  ...
servlet>

2. ServletContext类(重要)

ServletContext类:服务器启动时为每一个项目工程创建一个单独的ServletContext对象,每个项目只有一个该对象.

ServletContext类有4中作用:获取全局配置参数,获取指定文件的MIME类型,作为域对象存储数据,读取web工程下的文件.

2.1 ServletContext类常用的方法:

String getInitParameter(String name):获取指定名称的全局初始化参数值;
Enumeration getInitParameterNames():获取全局初始化参数值的名称,以枚举类型返回;
void setAttribute(String name, Object object):用ServletContext对象存储绑定到指定名称的对象;
Object getAttribute(String name):获取存储在ServletContext对象中指定名称的对象;
void removeAttribute(String name):移除存储在ServletContext对象中指定名称的对象;
String getMimeType(String file):返回指定文件的MIME类型,如果MIME类型未知,则返回null;
java.io.InputStream getResourceAsStream(String path):以InputStream对象的形式返回位于指定路径上的资源;
String getRealPath(String path):为给定虚拟路径返回包含实际路径的String表现形式;

2.2 ServletContext类获取全局配置参数:

​ 在web.xml配置文件中,通过配置标签(与Servlet标签是平级关系)来配置全局的初始化参数,在程序中通获取ServletContext的对象并通过其获取初始化参数的方法来获取初始化的参数,web.xml文件配置和程序中读取参数案例如下:



<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
    <display-name>项目工程的名称display-name>
    
    <servlet>
      <servlet-name>UserServletservlet-name>
      <servlet-class>com.itheima.servlet.UserServletservlet-class>
    servlet>
    
    <servlet-mapping>
      <servlet-name>UserServletservlet-name>
      <url-pattern>/UserServleturl-pattern>
    servlet-mapping>
    
    <context-param>
      <param-name>参数名1param-name>
      <param-value>参数值1param-value>
    context-param>
    <context-param>
      <param-name>参数名2param-name>
      <param-value>参数值2param-value>
    context-param>
    ...
web-app>
// 在程序的doGet或者doPost方法中获取Servletcontext对象来读取配置信息,以doGet方法示例
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // 获取单个的初始化参数值
  // 获取名称为username的全局初始化参数的值
  String username = this.getServletContext().getInitParameter("username");
  // 获取名称为password的全局初始化参数的值
  String password = this.getServletContext().getInitParameter("password");
  // 输出获取的指定名称和其参数值
  System.out.println(name+"---"+value);

  // 获取所有的初始化参数值
  // 获取所有全局初始化参数的名称,以枚举类型返回
  Enumeration e = this.getServletContext().getInitParameterNames();
  while(e.hasMoreElements()){
    // 根据名称获取指定名称的全局初始化参数的值
    String name = e.nextElement();
    String value = this.getServletContext().getInitParameter(name);
    // 输出获取的指定名称和其参数值
    System.out.println(name+"---"+value);
  }
}

2.3 ServletContext类获取文件的MIME类型:

​ 文件的MIME类型一般应用在文件下载中,客户端请求下载文件时,服务器需要将文件的MIME类型封装到响应的头信息中,然后客户端浏览通过服务器指定的MIME文件类型来下载文件.通过ServletContext的getMimeType方法获取文件的MIME类型.获取文件的MIME类型,见(HttpServletRequest文件下载案例).

2.4 ServletContext类作为域对象存取数据:

​ tomcat服务器启动时会为每一个项目创建一个单独的ServletContext对象(单例模式),该对象能被所有的Servlet对象所共享,并且可以通过其setAttribute方法存储数据,通过getAttribute方法获取指定名称的数据.

ServletContext对象的作用范围: 是整个项目工程,被所有的Servlet对象共享.

ServletContext对象的创建: tomcat服务器启动时为每一个项目创建一个单独的ServletContext对象.

ServletContext对象的销毁: 当项目被从tomcat服务器移除或者服务器关闭的时候,ServletContext对象被销毁.

案例: 通过浏览器访问Servlet,显示当前是第x位访问该Servlet的人

// 创建统计登陆人员的Servlet类,web.xml配置文件中配置访问路径
// 自定义类实现HttpServlet接口
public class UserCountServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    @Override
    // 重写初始化方法,通过ServletContext对象存储统计登陆人员的全局变量
    public void init() throws ServletException {
        // 初始化一个变量count的值为0
        int count = 0;
        // 将这个值存入到ServletContext中
        this.getServletContext().setAttribute("count", count);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // 设置向客户端响应的内容的类型及编码方式,防止中文乱码
      response.setContentType("text/html;charset=UTF-8");
      // 取出ServletContext对象中存储的数据
      int count = (int) this.getServletContext().getAttribute("count");
      // 访问该Servlet就表明是一位用户,将记录访问人数的变量加1
      count++;
      // 将统计的变量再写回到ServletContext对象中
      this.getServletContext().setAttribute("count", count);
      // 向页面显示当前访问者是第几位访问者
      response.getWriter().println("

您是第"+count+"位登录成功的用户!

"
); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }

2.5 ServletContext类读取web项目下的资源文件:

​ web项目工程发布到tomcat服务器后,程序的运行由tomcat进行管理;传统的读取项目下资源的文件的方式存在问题,传统的读取文件使用相对路径,相对的是JVM的路径;web工程中JVM是由tomcat服务器进行管理,程序的运行都是相对tomcat的bin文件夹的路径,则在开发工具(如eclipse)中直接运行服务器并读取项目下的资源是无法找到资源的.针对web工程,可以使用ServletContext对象提供的获取资源路径的方法getResourceAsStreamgetRealPath进行读取资源文件.

2.5.1 传统方式读取资源文件的缺陷:

// 在doGet或者doPost方法中读取项目src目录下名称为db.properties的数据库连接的配置文件
// 获取资源文件的输入流
// 获取src目录下的资源文件时,程序会相对于系统的JVM路径进行定位资源文件,但系统的JVM由tomcat进行管理,此时相对的是tomcat/bin路径,在程序找不到资源文件
// 程序运行出现异常java.io.FileNotFoundException: src\jdbc.properties (系统找不到指定的路径)
InputStream is = new FileInputStream("src/db.properties");
// 创建配置文件对象
Properties properties = new Properties();
// 加载配置文件
properties.load(is);

2.5.2 Web项目中读取资源文件的3种方式

​ web项目发布到tomcat服务器后,项目路径及资源文件的变化,读取web项目下的资源文件都是以项目发布后的目录结构来进行资源文件的定位的.

ServletContext对象的getResourceAsStream方法读取资源文件:

​ 在程序中获取ServletContext对象,通过getResourceAsStream方法获取指定资源文件的字节输入流对象,此处需要注意获得ServletContext对象代表是当前项目的路径,因此要定位的资源文件不能再加上项目名,否则定位的资源文件会出现两个项目名称的路径,定位文件使用相对于发布到tomcat中的当前项目根路径,案例如下:

// 在doGet或者doPost方法中读取项目src目录下名称为db.properties的数据库连接的配置文件,项目发布到tomcat服务器中时,资源文件在WEB-INF/classes/目录下
// 获得ServletContext对象,ServletContext代表的是项目工程的路径,就是代表在工程名下的路径
ServletContext context = this.getServletContext();   
// 获取资源文件的字节输入流对象
InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
// 创建配置文件对象
Properties properties = new Properties();
// 加载配置文件
properties.load(is);
// 获取配置文件中的信息
String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");

ServletContext对象的getRealPath方法读取资源文件:

​ 在程序中获取ServletContext的对象,通过getRealPath方法获取指定资源文件以盘符开始的绝对路径的字符串表示形式,此处需要注意使用的是ServletContext对象,其代表是/项目名路径,方法的参数的路径名必须使用相对于项目路径的相对路径表示,当方法的参数是/时获取的是当前项目的绝对路径.案例如下:

// 在doGet或者doPost方法中读取项目工程src目录下名称为db.properties的数据库连接的配置文件,项目发布到tomcat服务器中时,资源文件在WEB-INF/classes/目录下
// 获得ServletContext对象,ServletContext代表的是项目工程的路径,就是代表在工程名下的路径
ServletContext context = this.getServletContext(); 
// 获取在tomcat服务器中向对于项目在/WEB-INF/classes/目录下的资源文件的绝对路径
String realPath = context.getRealPath("/WEB-INF/classes/db.properties")
// 测试的realPath值是:D:\develop\apache-tomcat-7.0.69\webapps\JavaWeb_day13_Servlet\WEB-INF\classes\db.properties
// 创建文件的字节输入流对象
InputStream is = new FileInputStream(realPath);
// 创建配置文件对象
Properties properties = new Properties();
// 加载配置文件
properties.load(is);
// 获取配置文件中的信息
String driverClass = properties.getProperty("driverClass");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
// 释放IO资源
is.close();

通过类加载器读取资源文件:

​ 通过类加载器获取类加载路径下的资源文件的字节输入流对象,通常先获取src目录下任意一个的类的class字节码文件,通过字节码文件获取类加载器,通过类加载器的getResourceAsStream方法获取指定路径下资源文件的字节输入流对象;定位资源文件的要求是该资源文件必须在类加载路径下或者相对于类加载路径的资源的路径,通常开发工具中放在src目录下的资源文件都会在发布项目时在类加载路径下/WEEB-INF/classes/创建资源的副本.案例如下:

// 在名称为ServletDemo的Servlet类的doGet或者doPost方法中读取项目工程src目录下名称为db.properties的数据库连接的配置文件,项目发布到tomcat服务器中时,资源文件在WEB-INF/classes/目录下
// 通过ServletDemo类的类加载路径下名称为db.properties资源文件的字节输入流对象,WEB-INF/classes/目录下
InputStream is = ServletDemo.class.getClassLoader().getResourceAsStream("db.properties");
// 通过ServletDemo类的类加载路径上一级路径下名称为db.properties资源文件的字节输入流对象,WEB-INF/目录下
// InputStream is = ServletDemo.class.getClassLoader().getResourceAsStream("../db.properties");
...

3. HttpServletRequest类

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头的所有信息都封装在该对象中,通过该对象提供的方法可以获取客户端请求的所有信息.

3.1 HttpServletRequest常用方法:

获取请求中客户机的相关信息:

String getMethod():获取客户端此次请求的方式(常见的GET或者POST方式);
StringBuffer getRequestURL():获取客户端此次请求的URL;URL格式:http://localhost:8080/项目名/请求的访问资源
String getRequestURI():获取客户端此次请求的URI;本质是URL的一部分,URI格式:/项目名/请求的访问资源
String getRemoteAddr():获取客户端此次请求的IP地址;
String getContextPath():获取项目工程名,格式是:/项目名

获取客户端请求中提交的数据(父类中定义的方法):

String getParameter(String name):获取此次请求提交数据中指定名称的值,一般用于获取一个参数对应一个值的数据
String[] getParameterValues(String name):获取此次请求提交数据中指定名称参数的值的数组,一般用于获取一个参数对应多个值的数据(如复选框);
Enumeration getParameterNames():获取此次请求中提交数据中所有参数的名称,以枚举类型返回;
Map getParameterMap():获取此次请求提交数据中所有的参数及对应值的map集合,参数对应的值均存放在对应的数组中.

作为域对象存取数据(父类定义的方法): 存储的数据只能本次请求响应范围内有效(多次转发有效)

void setAttribute(String name, Object o):将绑定到指定名称的对象储存到本次请求中;
void removeAttribute(String name):移除本次请求中存储的指定名称的对象;
Object getAttribute(String name):获取存储到本次请求中的指定名称的对象.
RequestDispatcher getRequestDispatcher(String path):返回一个RequestDispatcher对象,它充当位于给定路径上的资源的包装器,可以使用RequestDispatcher对象将请求转发给资源,或者在响应中包含资源,资源可以是动态的,也可以是静态的.

案例代码:

// 测试获取客户机的信息
public class RequestServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获得请求方式:
        String method = request.getMethod();
        System.out.println("请求方式:"+method);
        // 获得客户机的IP地址:
        String ip = request.getRemoteAddr();
        System.out.println("IP地址:"+ip);
        // 获得用户的请求的路径:
        String url = request.getRequestURL().toString();
        String uri = request.getRequestURI();
        System.out.println("获得请求的URL:"+url);
        System.out.println("获得请求的URI:"+uri);
        // 获得发布的工程名:
        String contextPath = request.getContextPath();
        System.out.println("工程名:"+contextPath);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

3.2 HttpServletRequest作为域对象存储数据:

使用HttpServletRequest对象的setAttribute方法储存数据,使用getAttribute方法读取存储的数据.

HttpServletRequest对象资源转发:

​ HttpServletRequest对象可以将请求该servlet对象的请求进行转发到其他的servlet中,转发是在服务器内部进行转发的,使用的都是其他servlet相对于项目的访问地址,request作为域对象存储的数据可以转发到其他的servlet中,在其他servlet中使用域对象的获取参数的方法即可取出转发过来的数据.

HttpServletRequest对象的作用范围:

HttpServletRequest作用范围: 一次请求的范围(转发多次属于是一次请求).

HttpServletRequest对象创建: 当有客户端向服务器请求该servlet时,服务器就会创建request对象;

HttpServletRequest对象销毁: 当服务器对本次请求做出响应后就销毁该request对象.

3.3 HttpServletRequest接收中文参数乱码及解决(客户端页面编码假定为utf-8):

3.3.1 POST方式提交数据乱码及解决:

​ 客户端POST方式请求提交的以UTF-8格式编码的数据在请求体中,这些数据到达后台的Servlet对象后都被封装到request对象中,request对象中有一个存储请求数据的缓冲区,而缓冲区的默认编码格式ISO-8859-1,此编码格式不支持中文,则从request缓冲区直接读取中文参数会出现乱码,解决乱码思想就是将request缓冲区中的编码格式设置为utf-8格式,再读取中文参数就不会出现乱码.

设置request缓冲区的编码方法: request.setCharacterEncoding("UTF-8"),设置缓冲区编码一定要在读取参数之前.

3.3.2 GET方式提交数据乱码及解决:

​ 客户端GET方式请求提交以UTF-8格式编码的的数据在请求头中,数据到达后台后背封装到request对象中,该对象默认使用ISO-8859-1编码格式进行参数进行编码后存储.解决乱码思路是以ISO-8859-1编码格式从request中取出参数,然后再使用UTF-8格式进行解码即可.

解决乱码的方法: String name = new String(request.getParameter("参数名称").getBytes("ISO-8859-1"),"UTF-8");

4. HttpServletResponse类

tomcat服务器接收到客户端的HTTP请求,会针对每一个请求创建代表对该请求响应的HttpServletResponse对象,Response对象可以向客户机进行输出数据.

4.1 HttpServletResponse常用方法:

设置响应行:

void setStatus(int sc):设置响应头行的状态码,如302,304

设置响应头:

// 下面三种针对是响应头中一个key对应多个value的头信息,添加不会覆盖之前添加的内容
void addDateHeader(String name, long date):用给定名称和日期值添加响应头,参数是毫秒值;
void addHeader(String name, String value):用给定名称和值添加响应头信息;
void addIntHeader(String name, int value):用给定名称和整数值添加响应头信息;
// 下面三种针对是响应头中一个key对应一个value的头信息,后添加的会覆盖之前添加的内容
void setDateHeader(String name, long date):用给定名称和日期值设置响应头,参数是毫秒值;
void setHeader(String name, String value):用给定名称和值设置响应头信息;
void setIntHeader(String name, int value):用给定名称和整数值设置响应头信息;

设置响应体:

ServletOutputStream getOutputStream():获取在响应中编写二进制数据的ServletOutputStream对象,字节流对象;
PrintWriter getWriter():获取可将字符文本发送到客户端的PrintWriter对象,字符流对象;

4.2 HttpServletResponse向客户端输出数据:

​ 使用response对象向客户端输出数据是响应体中的内容,使用response对象的getOutputStream(字节流)或者getWriter(字符流)方法设置响应体中的内容.这两种方法输出数据是互斥的,不能同时使用,只能使用其中的一种,当向客户端输出中文数据时,客户端显示可能出现乱码,两种输出方式输出中文乱码及解决方法有所不同,但思想都是输出时设置编码,同时设置客户端浏览器查看该信息的编码一致即能解决中文乱码问题.

4.2.1 使用字节流向客户端输出数据:

​ 使用字节流向客户端输出中文数据时,如果不设置输出编码,当项目工作空间的编码和客户端打开该数据时的编码相同时,客户端显示中文数据不会乱码,为确保向客户端输出的中文数据不会乱码,则需要设置中文数据转换为字节数组时的编码方式和客户端浏览器查看该中文数据的编码方式相同即可.

设置输出中文数据转换为字节数组时的编码: 设置中的UTF-8的字母只能大写,写出utf-8时不起作用

"中文数据".getBytes("UTF-8");.

设置浏览器查看输出的中文数据的编码: 下面两种方式均可以,设置中的UTF-8的字母只能大写,写出utf-8时不起作用

​ 设置头信息中数据的类型为text/html,字符编码为utf-8,浏览查看该数据时会根据设置的编码解码中文数据:

resposne.setHeader("Content-Type","text/html;charset=UTF-8");

​ 通过response对象setContentType方法设置浏览器查看数据方式:

response.setContentType("text/html;charset=UTF-8");

4.2.2 使用字符流向客户端输出中文数据及乱码解决:

​ 使用字符流对象输出中文时使用默认编码一定会出现中文数据乱码,由于response对象的缓冲区的编码格式是ISO-8859-1,此编码格式不支持中文.

设置response缓冲区的编码: 设置中的UTF-8的字母只能大写,写出utf-8时不起作用

response.setCharacterEncoding("UTF-8");.

设置浏览器查看输出的中文数据的编码: 设置中的UTF-8的字母只能大写,写出utf-8时不起作用

resposne.setHeader("Content-Type","text/html;charset=UTF-8");

设置的简写方式(上述两步的简写方式): 同时设置缓冲区的编码和客户端查看的编码

response.setContentType("text/html;charset=UTF-8");

5. 综合案例

5.1 访问Servlet时定时跳转到其他页面

​ 实现定时跳转输出是服务器向客户端响应,则使用response对象设置响应头信息实现定时跳转.查阅HTTP协议的响应头可知,使用响应头中Refresh定时刷新(可以定时跳转)或设置302重定向(直接跳转)或使用sendRedirect方法(直接跳转)实现跳转页面.

使用Refresh定时刷新跳转页面: 设置Refresh响应头数据格式如下:跳转的路径一般设置为绝对路径

response.setHeader("Refresh","定时时间;url=跳转到指定资源的路径").

使用302状态码和Location属性实现跳转页面: 先设置响应头的状态码为302,然后再设置Location的跳转地址,跳转的路径一般设置为绝对路径

设置302状态码:response.setStatus(302);

设置Location跳转地质:response.setHeader("Location", "跳转的地址");

使用response的sendRedirect方法实现跳转页面: sendRedirect方法默认会设置响应头的302状态码

response.sendRedirect(跳转的资源路径);

案例代码:

// 测试定时跳转页面,使用浏览器访问http:localhost:8080/项目名/UserRefreshServlet访问路径
public class UserRefreshServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // 解决向页面输出中文的乱码问题
      response.setContentType("text/html;charset=UTF-8");
      // 输出提示信息
      response.getWriter().println("

页面将在5秒后跳转!

"
); // 使用定时刷新跳转页面,定时5秒跳转到指定页面 response.setHeader("Refresh", "5;url=/JavaWeb_day13_Servlet/login/login.html"); // 使用302重定向跳转页面 // response.setStatus(302); // response.setHeader("Location", "/JavaWeb_day13_Servlet/login/login.html"); // 上述两个方法可以简化为: void sendRedirect(String location) // 使用sendRedirect方法实现跳转 Response.sendRedirect("/JavaWeb_day13_Servlet/login/login.html"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

5.2 访问Servlet时定时,在中间页面使用js实现读秒控制,时间到后跳转到其他页面

​ 在上面的案例基础上使用中间html页面用js代码实现计时读秒效果,则上述代码只能使用重定向跳转到中间页面,在中间页面中设置Refresh的信息,实现定时跳转.

访问Servlet的代码如下:

// 测试定时跳转页面,使用浏览器访问http:localhost:8080/项目名/UserRefreshServlet访问路径
public class UserRefreshServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // 解决向页面输出中文的乱码问题
      response.setContentType("text/html;charset=UTF-8");
      // 使用302重定向跳转页面,跳转到中间页面
      // response.setStatus(302);
      // response.setHeader("Location", "/JavaWeb_day13_Servlet/login/success.html");

      // 上述两个方法可以简化为: void sendRedirect(String location)
      // 使用sendRedirect方法实现跳转,跳转到中间页面
      Response.sendRedirect("/JavaWeb_day13_Servlet/login/success.html");
    }
    ...
}

中间计时读秒页面代码如下:



<html>
<head>
<meta charset="UTF-8">
 
<meta http-equiv="Refresh" content="5;url=/JavaWeb_day13_Servlet/login/index.html"/>
<title>计时跳转title>
<script type="text/javascript">
    // 页面加载完成后开始计时
    window.onload=function() {
        // 定义定时的时间为5秒
        var time = 5;
        // 设置1秒钟修改span标签中的内容,当计时到了,页面自动跳转
        setInterval(function() {
            document.getElementById("time").innerHTML=--time;
        }, 1000);
    }
script>
head>
<body>
    <h1>
        登陆成功,浏览器将在<span id="time">5span>秒后跳转...
    h1>
body>
html>

5.3 客户端从服务器端下载文件

文件的下载方式:

1. 使用超链接方式实现文件的下载, 文件名,客户端点击超链接实现文件下载,但前提是浏览器不支持此种类型文件的打开,否则浏览器会直接在浏览器打开文件,而不会下载文件.
2. 手动设置完成文件的下载:在服务器端需要使用response对象设置两头一流

设置文件的MIME类型: 通过设置响应头Content-Type的值;response.setHeader("Content-Type",文件MIME类型)

设置文件是以下载的方式打开: 通过设置响应头Content-Disposition的值;response.setHeader("Content-Disposition", "attachment;filename="+文件名称)

获取要下载文件的输入流对象: 读取web项目下的资源文件(见2.5知识).

非中文文件的下载:

// 下载文件时后台的/JavaWeb_day14_request_response/DownloadServlet处理
// 资源文件放在/JavaWeb_day14_request_response/download/目录下
public class DownloadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 接收参数,获取客户端要下载的文件的名称
        String filename = request.getParameter("filename");
        // 设置Content-Type头
        String type = this.getServletContext().getMimeType(filename);
        response.setHeader("Content-Type", type);
        // 设置Content-Disposition头
        response.setHeader("Content-Disposition", "attachment;filename="+filename);  设置下载的文件名
        // 设置文件的InputStream对象
        String realPath = this.getServletContext().getRealPath("/download/"+filename);
        InputStream is = new FileInputStream(realPath);
        // 获得response的输出流对象
        OutputStream os = response.getOutputStream();
        // 读取文件内容写到response的输出流对象中
        int len = 0;
        byte[] b = new byte[1024];
        while((len = is.read(b))!= -1){
            os.write(b, 0, len);
        }
        // 释放资源
        is.close();  // os对象属于response创建,response会自动关闭输出流对象
    }
    ...
}


<html>
<head>
<meta charset="UTF-8">
<title>文件下载title>
head>
<body>
<h1>文件下载列表,超链接下载h1>
<a href="/JavaWeb_day14_request_response/download/WEB09-Servlet.xmind">WEB09-Servlet.xminda><br />
<a href="/JavaWeb_day14_request_response/download/XJad2.2.zip">XJad2.2.zipa><br />
<a href="/JavaWeb_day14_request_response/download/test.propreties">test.propretiesa><br />
<a href="/JavaWeb_day14_request_response/download/笔记.xmind">笔记.xminda><br />
<h1>文件下载列表,编码下载h1>
<a href="/JavaWeb_day14_request_response/DownloadServlet?filename=WEB09-Servlet.xmind">WEB09-Servlet.xminda><br />
<a href="/JavaWeb_day14_request_response/DownloadServlet?filename=XJad2.2.zip">XJad2.2.zipa><br />
<a href="/JavaWeb_day14_request_response/DownloadServlet?filename=test.propreties">test.propretiesa><br />
body>
html>

文件名为中文的文件的下载:

​ 浏览器下载文件时对中文文件名称进行编码,不同的浏览器对中文文件的名称的编码方式不同,则服务器向客户端输出文件名时根据不同的浏览器类型设置不同的编码,IE和Chrome等浏览器使用的URL的编码,Firefox使用的是Base64的编码.

// 下载文件时后台的/JavaWeb_day14_request_response/DownloadServlet处理
// 资源文件放在/JavaWeb_day14_request_response/download/目录下
public class DownloadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 请求传递过来的数据以request的默认编码存入request对象中,则需要以request默认的ISO-8859-1编码取出数据,然后再以utf-8进行解码
        // 获取需要下载的文件的名称
        String filename = new String(request.getParameter("filename").getBytes("ISO-8859-1"),"UTF-8");
        // 获取要下载的文件的MIME类型
        String filetype = this.getServletContext().getMimeType(filename);
        // 设置响应头中文件的类型
        response.setHeader("Content-Type", filetype);
        // 根据浏览器类型的不同设置不同格式的文件名的编码
        // IE等浏览器是以URLEncoder进行编码,Firefox是以base64进行编解码
        // 获取浏览器的类型
        String header = request.getHeader("User-Agent");
        String newFilename = null;
        // 判断是否是Firefox浏览器,是则使用base64进行编码
        if (header.contains("Firefox")) {
            newFilename = base64EncodeFileName(filename);
        // 如果不是Firefox浏览器使用URL编码
        } else {
            newFilename = URLEncoder.encode(filename,"UTF-8");
        }
        // 设置响应头中的Content-Disposition的值,就是文件下载时显示的名称
        response.setHeader("Content-Disposition", "attachment;filename="+newFilename);
        // 获取资源的io流方式1
        // this.getServletContext().getResourceAsStream代表的是当前项目的根目录,/JavaWeb_day14_request_response
        // InputStream is = this.getServletContext().getResourceAsStream("/download/"+filename);
        // 获取资源的io流方式2
        String realPath = this.getServletContext().getRealPath("/download/"+filename);
        // System.out.println(realPath);输出结果如下
        // E:\develop\apache-tomcat-7.0.69\webapps\JavaWeb_day14_request_response\download\WEB09-Servlet.xmind
        InputStream is = new FileInputStream(realPath);

        // 获取资源的io流方式3
        // InputStream is = DownloadServlet.class.getClassLoader().getResourceAsStream("../../download/"+filename);
        ServletOutputStream os = response.getOutputStream();
        // 向客户端输出数据
        int len = 0;
        byte[] arr = new byte[1024];
        while((len = is.read(arr)) != -1) {
            os.write(arr, 0, len);
        }
        // 释放资源
        is.close();
    }

    // Firefox浏览采用的是base64编码,该方法是对字符串进行base64编码,记住下面的使用即可
    public static String base64EncodeFileName(String fileName) {
        BASE64Encoder base64Encoder = new BASE64Encoder();
        try {
            return "=?UTF-8?B?"
                    + new String(base64Encoder.encode(fileName
                            .getBytes("UTF-8"))) + "?=";
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
  ...
}

“`html





文件下载

文件下载列表,超链接下载

WEB09-Servlet.xmind

XJad2.2.zip

test.propreties

笔记.xmind

文件下载列表,编码下载

WEB09-Servlet.xmind

笔记.xmind

XJad2.2.zip

test.propreties



“`

6. 重定向和转发的区别(重点)

资源的重定向:

​ 资源的重定向使用response设置响应头中Refresh定时刷新(可以定时跳转)或设置302重定向(直接跳转)或使用sendRedirect方法(直接跳转)实现跳转页面.

使用Refresh定时刷新跳转页面: 设置Refresh响应头数据格式如下:跳转的路径一般设置为绝对路径

response.setHeader("Refresh","定时时间;url=跳转到指定资源的路径").

使用302状态码和Location属性实现跳转页面: 先设置响应头的状态码为302,然后再设置Location的跳转地址,跳转的路径一般设置为绝对路径

设置302状态码:response.setStatus(302);

设置Location跳转地质:response.setHeader("Location", "跳转的地址");

使用response的sendRedirect方法实现跳转页面: sendRedirect方法默认会设置响应头的302状态码

response.sendRedirect(跳转的资源路径);

资源的转发:

​ 资源的转发是使用request对象将请求进行转发到其他的servlet中,转发是在服务器内部进行转发的,使用的都是其他servlet相对于项目的访问地址,request作为域对象存储的数据可以转发到其他的servlet中,在其他servlet中使用域对象的获取参数的方法即可取出转发过来的数据.

重定向和转发的区别:

  • 重定向时浏览器的地址栏会发生变化,转发时浏览器的的地址栏不变;
  • 重定向时是两次请求两次响应,转发时是一次请求一次响应;
  • 重定向时资源路径需要加工程名,转发时的路径不能加工程名;
  • 重定向时可以跳转到任意网站,转发时只能在服务器内部进行转发.

注意事项:
转发时使用的服务器端路径,转发时不能加上工程名,转发时默认会添加上工程名.

重定向:设置的资源路径需要加上项目名,一般使用绝对路径.

转发格式: request.getRequestDispatcher("/转发的路径").forward(request, response);

你可能感兴趣的:(JavaWeb,java,web,servlet)