Servlet简单介绍

来源:互联网 发布:linux 3306监听命令 编辑:程序博客网 时间:2024/05/22 17:31

Servlet

注意点:

  • cmd中设置servlet相关的编译路径:set classpath=%classpath%;D:\0hsx\
    apache-tomcat-7.0.67\lib\servlet-api.jar
    ,然后在运行相关的servlet的Java程序。

手动编写Servlet过程

  • 建立JavaWeb应用的目录
Hello  ---  应用名称    WEB-INF  ---  目录        classes  ---  目录:对应的Servlet的java文件就放在这里,比如:HelloServlet.java        lib      ---  目录        web.xml  ---  配置文件
  • 在classes目录中建立HelloServlet.java文件,具体代码如下:
package com.hsx;import java.io.*;import javax.servlet.*;public class HelloServlet extends GenericServlet {    public void init() throws ServletException {        System.out.println("init");    }    public void service(ServletRequest req, ServletResponse res) throws ServletException,java.io.IOException {        //向客户端输出数据        String data = "Hello Servlet";        OutputStream out = res.getOutputStream();        out.write(data.getBytes());    }    public void destroy() {        System.out.println("destory");    }}
  • web.xml文件的配置,代码:
<?xml version="1.0" encoding="UTf-8"?><web-app xmlns="http://java.sun.com/xml/ns/javaee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  version="3.0"  metadata-complete="true">    <servlet>      <servlet-name>HelloServlet</servlet-name> <!-- Servlet的名称 -->      <servlet-class>com.hsx.HelloServlet</servlet-class> <!-- Servlet的全名-路径 -->    </servlet>    <servlet-mapping>      <servlet-name>HelloServlet</servlet-name> <!-- Servlet的名称,与<servlet>中的<servlet-name>中的内容要一致 -->      <url-pattern>/helloServlet</url-pattern> <!-- URL:用户访问的映射路径 -->    </servlet-mapping></web-app>
  • 编译HelloServlet.java文件,注意,编译需要用到servlet-api.jar(在Tomcat的lib目录中),在cmd目录中编译时,需要设置classpath的路径,命令set classpath=%classpath%;D:\0hsx\
    apache-tomcat-7.0.67\lib\servlet-api.jar
    ,接着在classes目录下编译该java类,命令:javac -d . HelloServlet.java,这是可以在classes目录中查看其是否编译成功。
  • 启动Tomcat。
  • 在浏览器中输入:http://localhost:8080/hello/helloServlet,页面上回显示”Hello Servlet”。

感觉用intellij Idea开发Servlet不好。

开发servlet的三种方式

  • 实现servlet接口
  • 继承GenericServlet类
  • 继承HttpServlet类 * 一般用这个

修改MyEclipse中的Servlet模板

MyEclipse2014:在MyEclipse的安装目录中找到这个com.genuitec.eclipse.wizards_11.5.0.me201310291746.jar文件,打开其中的templates找到Servlet.java文件(注意:需要关闭MyEclipse,修改是应该养成良好的备份习惯)

Servlet的一些细节

细节1

  • 由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。
  • <servlet>元素用于注册Servlet,它包含两个主要的子元素:
    • <servlet-name> :设置Servlet的注册名
    • <servlet-class> :设置Servlet的完整类名
  • <servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问的路径,它包好两个子元素:
    • <servlet-name> :指定Servlet的注册名
    • <url-pattern> :Servlet对外访问路径
  • 示例:
    <servlet>      <servlet-name>HelloServlet</servlet-name>      <servlet-class>com.hsx.HelloServlet</servlet-class>    </servlet>    <servlet-mapping>      <servlet-name>HelloServlet</servlet-name>      <url-pattern>/hello</url-pattern>    </servlet-mapping>

细节2

  • 同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的值可以相同,即同一个Servlet的注册名。
  • 在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:
    • 一种格式是*.扩展名 (注:*前没有其他内容)
    • 另一种格式是以正斜杠(/)开头并以(/*)结尾

注:*.扩展名的匹配优先级低。

细节3

  • 如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前web应用程序的缺省Servlet,即默认的Servlet。
  • 凡是在web.xml文件中找不到匹配的元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省的Servlet用于处理所有其他的Servlet群殴不处理的访问请求。
  • 在[tomcat的安装目录]\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省的Servlet。
    <servlet>        <servlet-name>default</servlet-name>        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>        <init-param>            <param-name>debug</param-name>            <param-value>0</param-value>        </init-param>        <init-param>            <param-name>listings</param-name>            <param-value>false</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>default</servlet-name>        <url-pattern>/</url-pattern>    </servlet-mapping>

即访问Tomcat服务器中某个静态HTML文件盒图片时,实际上是在访问这个缺省的Servlet。

Servlet的生命周期

  • Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎控制和调度。
  • 针对客户端的多次请求,通常,服务器只会创建一个Servlet实例对象,也就说Servlet实例对象一旦创建,它就会驻留在内存中,为后继的其他请求服务,直至web容器退出,Servlet实例对象才会销毁。
  • 在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用Servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给他调用的Servlet的service()方法,service方法再根据请求方式调用doXXX方法。
  • <load-on-startup>的取值说明这个Servlet的启动顺序。
    <servlet>      <servlet-name>HelloServlet</servlet-name>      <servlet-class>com.hsx.HelloServlet</servlet-class>      <load-on-startop>2</load-on-startup>    </servlet

Servlet线程安全问题

  • 当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
  • 如果Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
  • SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。
  • 对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每一个线程分别调用一个独立的Servlet实例对象。
  • 实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。

解决并发问题

  • 使用Java同步机制对多线程同步:运行效率低。
  • 使用SingleThreadModel接口。
  • 合理决定在Servlet中定义的变量的作用域。

ServletConfig对象

  • 在Servlet的配置文件中,可以使用一个或多个<init-param>标签为Servlet配置一些初始化参数。
  • 当Servlet配置了初始化参数后,web容器在创建Servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用Servlet的init方法时,将ServletConfig对象传递给Servlet,从而,程序员通过ServletConfig对象就可以得到当前Servlet的初始化参数信息。
<init-param>    <param-name>enconding</param-name>    <param-value>utf-8</param-value></init-param><load-on-startup>1</load-on-startup>

注:要配置在的下面。

补充:

  • 只能给某个Servlet配置参数,当然也只能作用于对应的Servlet。
  • 是给所有的Servlet配置参数,当然要配置在所有的Servlet外面,作用于所有的Servlet。
  • 示例:
<!-- web.xml --><context-param>    <param-name>encoding</param-name>    <param-value>UTF-8</param-value></context-param><context-param>    <param-name>welcome</param-name>    <param-value>hhh</param-value></context-param>//结合ServletContext对象ServletConfig servletConfig = this.getServletConfig();ServletContext servletContext = servletConfig.getServletContext();Enumeration<String> e = servletContext.getInitParameterNames();while (e.hasMoreElements()) {    String name = e.nextElement();    Object value = servletContext.getInitParameter(name);    System.out.println(value);}

ServletContext对象

  • Web容器在启动时,它会为每一个Web应用程序都创建一个对应的ServletContext对象,它代表的是当前的Web应用。
  • ServletConfig对象中维护了ServletContext对象的引用,我们在编写程序时,可以通过:
    1. servletConfig.getServletContext方法this.getServletConfig().getServletContext();获得ServletContext对象。
    2. 在继承HttpServlet中,直接ServletContext sc = getServletContext();获得ServletContext对象。
  • 由于一个Web应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象实现通讯。ServletContext对象通常也被称为context域对象。

ServletContext应用

  • 实现Servlet的转发示例:
//ServletContextDemo3中的代码ServletContext sc = getServletContext();RequestDispatcher rd = sc.getRequestDispatcher("/ServletContextDemo4");rd.forward(request, response);//ServletContextDemo4中的代码response.getOutputStream().write("nihao".getBytes());
  • 转发的特点:
    • 请求的地址栏不变。
    • 转发前的Servlet和转发后的Servlet,两者之间共享request和response对象。
    • 转发前的页面是不会有输出的,显示的始终是转发后的页面。示例:
ServletContext sc = getServletContext();RequestDispatcher rd = sc.getRequestDispatcher("/ServletContextDemo4");System.out.println("转发前ServletContextDemo3"); //后台会打印response.getOutputStream().write("Demo3 before".getBytes()); //页面不会显示response.getOutputStream().flush(); //强制刷新缓存 - 这是显示的Dome3的内容,而不会显示Demo4的内容//注:转发前不要刷新response输出流//转发前会清空response中输出流的内容rd.forward(request, response);System.out.println("转发后ServletContextDemo3"); //后台会打印response.getOutputStream().write("Demo3 after".getBytes()); //页面不会显示
  • ServletContext读取资源配置文件,示例:
package com.hsx;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 读取文本中的某个资源文件,下载的方式打开 * @author hsx * */public class ServletContextDemo5 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        //1 http.png的真实路径        String httpPath = "/image/http.png"; //在web开发中"/"就代表当前web应用的根目录,本应用就是servletContext        ServletContext sc = getServletContext();        String realPath = sc.getRealPath(httpPath); //得到绝对路径        System.out.println(realPath);        InputStream in = new FileInputStream(realPath);        OutputStream out = response.getOutputStream();          //通知客户端下载的方式        response.setHeader("Content-Disposition", "attachment;filename=http.png");        byte[] buffer = new byte[1024];        int len = -1;        while ((len = in.read(buffer)) != -1) {            out.write(buffer, 0, len);        }        in.close();        out.close(); //有没有没有什么关系,servlet容器会自动将其关闭    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}

注:getRealPath():获取指定相对路径资源的绝对路径,相对路径在WebRoot目录下必须以”/”开始。

  • 读取WEB-INF目录下的配置文件
String realPath = sc.getRealPath("/WEB-INF/db.properties");
  • 读取类目录下的配置文件
String realPath = sc.getRealPath("/WEB-INF/classes/db.properties");
  • 读取类目录中的某个包中的配置文件
String realPath = sc.getRealPath("/WEB-INF/classes/com/hsx/db.properties");
  • 采用类加载器读取配置文件,ClassLoader只能加载类目录中的资源(类加载不适合加载大的配置文件)
ClassLoader cl = ServletContextDemo6.class.getClassLoader(); //or  this.getClass().getClassLoader();InputStream in = cl.getResourceAsStream("db.properties");Properties properties = new Properties();properties.load(in);System.out.println(properties.getProperty("name"));System.out.println(properties.getProperty("password"));

HttpURLConnection

  • HttpURLConnection类的作用是通过HTTP协议向服务器发送请求,并可以获取服务器发回的数据。
  • HttpURLConnection来自于jdk,它的完整名称为:java.net.HttpURLConnection。
  • HttpURLConnection类没有公开的构造方法,但我们可以通过java.net.URL的openConnection方法获取一个URLConnection的实例,而HttpURLConnection是它的子类。
  • 示例:
URL url = new URL("http://localhost:8080");HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  • 示例:简单获取服务器数据
    • connection.getResponseCode() : 获取响应码
    • connection.getResponseMessage() : 获取响应码描述
    • connection.getHeaderField(“Server”) : 获取响应头
    • connection.getInputStream(): 获取正文输入流
package com.hsx;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;public class HttpURLConnectionTest {    public static void main(String[] args) throws Exception {        URL url = new URL("http://localhost:8080/");        HttpURLConnection connection = (HttpURLConnection) url.openConnection();        // 获取响应码        int code = connection.getResponseCode();        // 获取响应码描述        String status = connection.getResponseMessage();        // 获取一个响应头        String header = connection.getHeaderField("Server");        // 获取响应正文        InputStream in = connection.getInputStream();        System.out.println("响应码" + code + "\t响应码描述" + status + "\t响应头" + header);        byte[] buffer = new byte[1024];        int len = -1;        while ((len = in.read(buffer)) != -1) {            System.out.println(new String(buffer, 0, len));        }        in.close();        connection.disconnect();    }}
  • 示例:向服务器发送消息默认请求到doGet方式
URL url = new URL("http://localhost:8080/servletContext/ServletContextDemo1");HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setDoOutput(true);//向服务器发送消息头connection.setRequestProperty("mheader", "pp");//向服务器发送请求参数OutputStream out = connection.getOutputStream();out.write("username=huang".getBytes());System.out.println(connection.getResponseCode());connection.disconnect();
  • 示例:向服务器发送消息默认请求到doPost方式,只需要在上述代码中加上connection.setRequestMethod("POST"),默认的是doGet方式。

Servlet类图

这里写图片描述

request和response

  • Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象和代表响应的response对象。
  • request和response对象既然代表请求和响应,要获取客户机提交过来的数据,只需要找request对象;要想客户机输出数据,只需要response对象。

HttpServletResponse

  • HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头、发送响应状态码的方法。

response常见应用

向客户端输出中文数据,以字节为单位的四种方式:

package com.hsx;import java.io.IOException;import java.io.OutputStream;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 以字节为单位向客户端发送中文数据 * @author hsx * */public class ServletTest extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        //test1(response);        //test2(response);        //test3(response);        test4(response);    }    /**     * 以UTF-8编码向客户端发送中文数据,并告诉客户端编码方式     * @param response     * @throws IOException     */    private void test4(HttpServletResponse response) throws IOException {        String data = "中华";        response.setContentType("text/html;charset=UTF-8"); //实际上就是设置响应头        OutputStream out = response.getOutputStream();        out.write(data.getBytes("UTF-8"));         // 告诉客户端编码方式        out.close();    }    /**     * 以UTF-8编码向客户端发送中文数据,并通过meta标签模拟请求头     * @param response     * @throws IOException     */    private void test3(HttpServletResponse response) throws IOException {        String data = "中华";        OutputStream out = response.getOutputStream();        out.write("<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>".getBytes());        out.write(data.getBytes("UTF-8"));    }     /**     * 以UTF-8编码向客户端发送中文数据,并告诉客户端编码方式     * @param response     * @throws IOException     */    private void test2(HttpServletResponse response) throws IOException {        String data = "中华";        OutputStream out = response.getOutputStream();        out.write(data.getBytes("UTF-8"));         // 告诉客户端编码方式        response.setHeader("Content-Type", "text/html;charset=UTF-8");        out.close();    }    /**     * 以本地平台默认编码向客户端发送中文数据 - GBK     * @param response     * @throws IOException     */    private void test1(HttpServletResponse response) throws IOException {        String data = "中华";        OutputStream out = response.getOutputStream();        out.write(data.getBytes()); //默认编码GBK         out.close();    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}

总结:程序以什么编码输出,就要告知客户端以什么编码显示。

注:浏览器“查看”编码,再修改编码是不可取的。

注意:以字节流的方式向客户端发送1,一定要把int型的转换成String型

    int i = 1;    OutputStream out = response.getOutputStream();    out.write((i + "").getBytes());    out.close();

向客户端输出中文数据,以字符为单位的两种方式:

package com.hsx;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 以字符为单位向客户端发送中文数据 *  * @author hsx *  */public class ServletTest2 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        //test1(response);        test2(response);    }    /**     * 字符流用这一种方式就可以搞定中文乱码问题response.setContentType("text/html;charset=UTF-8");     * @param response     * @throws IOException     */    private void test2(HttpServletResponse response) throws IOException {         String data = "你好,啊打发";        response.setContentType("text/html;charset=UTF-8");        PrintWriter pw = response.getWriter();        pw.write(data);        pw.close();    }    /**     * 制定向客户端发送的数据的编码是UTF-8,告诉客户端编码方式[即时客户端打开时显示的数据时以UTF-8编码显示的]     * @param response     * @throws IOException     */    private void test1(HttpServletResponse response) throws IOException {        String data = "你好,黄阿斯";        response.setCharacterEncoding("UTF-8"); //制定向客户端发送的数据的编码是UTF-8        PrintWriter pw = response.getWriter(); //默认的编码是ISO-8859-1(ISO-8859-1码表中没有中文)        response.setHeader("Content-Type", "text/html;charset=UTF-8"); //告诉客户端编码方式        pw.write(data);        pw.close();    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}

中文文件下载时的中文显示问题

package com.hsx;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.URLEncoder;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpUtils;public class ServletTest3 extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        //1 得到文件的真实路径        String realPath = getServletContext().getRealPath("/image/http请求过程.jpg");        String name = realPath.substring(realPath.lastIndexOf("\\") + 1); //文件名        System.out.println(name);        //2 构建输入流        InputStream in = new FileInputStream(realPath);        //3 利用response向客户端输出,告知客户端的下载方式        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name, "UTF-8")); //这里需要将文件的中文名进行编码,这里指定的编码是UTF-8        OutputStream out = response.getOutputStream();        byte[] buffer = new byte[1024];        int len = -1;        while((len = in.read()) != -1) {            out.write(buffer, 0, len);        }        in.close();        //out.close();    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}

输出随机图片

  • 输出随机图片(CAPTCHA图像):Completely Automated Public Turing Test to Tell Computer and Humans Apart(全自动区分计算和人类的测试),相关的主要类[JDK查看API]:

    • BufferedImage:内存图像
    • Graphics:画笔
    • ImageIO:输出图像
    • 放在HTML页面上

    注意:浏览器默认会缓存图片。

    • 控制客户端不要缓存
response.addHeader("Pragma", "no-cache");response.setHeader("Cache-Control", "no-cache");response.setHeader("Expires", "0");
package com.hsx;import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.io.IOException;import java.io.PrintWriter;import java.util.Random;import javax.imageio.ImageIO;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 输出随机图像 * @author hsx * */public class ServletTest4 extends HttpServlet {    private static int WIDTH = 120;    private static int HIGHT = 30;    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.addHeader("Pragma", "no-cache");        response.setHeader("Cache-Control", "no-cache");        response.setHeader("Expires", "0");        //1 创建一个内存图像,并设置长和高 :BufferedImage        BufferedImage image = new BufferedImage(WIDTH, HIGHT, BufferedImage.TYPE_INT_RGB);        //2 得到该图像的画笔 :Graphics        Graphics g = image.getGraphics();        //2.1 画边框        g.setColor(Color.BLUE);        g.drawRect(0, 0, WIDTH, HIGHT);        //2.2 画背景色        g.setColor(Color.GRAY);        g.fillRect(1, 1, WIDTH - 2, HIGHT - 2);        //2.3 画干扰线9条        Random random = new Random();        for (int i = 0; i < 9; i++) {            g.setColor(Color.YELLOW);            g.drawLine(random.nextInt(WIDTH), random.nextInt(HIGHT), random.nextInt(WIDTH), random.nextInt(HIGHT));        }        //2.4 画验证树数字4个        int count = 5;        for (int i = 0; i < 4; i++) {            g.setColor(Color.RED);            g.setFont(new Font("宋体", Font.BOLD, 25));            g.drawString(random.nextInt(9) + "", count, 25);            count += 30;        }        //3 输出daoresponse的输出流中 :ImageIO        ImageIO.write(image, "jpeg", response.getOutputStream());    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}
  • js能刷新页面
<body>    <form action="" method="post">        <input type="text" name="username" value=""/><br/><br/>        <input type="password" name="password" value=""/><br/>        <input type="text" name="code" value=""/><img id="codeImg" src="/servletContext/ServletTest4">        <a href="javascript:change()">看不清,换一张</a><br/>        <input type="submit" value="登录"/>    </form>    <script type="text/javascript">        function change() {            var imgObj = document.getElementById("codeImg");            imgObj.src = "/servletContext/ServletTest4?" + new Date().getTime();        }       </script></body>

刷新页面

  • 每隔3秒刷新页面(Servlet控制)
response.setHeader("Refresh", "3"); //每隔3秒中刷新一次
  • 刷新到新的页面(Servlet控制)
response.getOutputStream().write("<meta http-equiv=\"Refresh\" content=\"3;URL=/servletContext/login.html\">".getBytes());
  • 页面跳转到Servlet控制的页面上上去

··

<meta http-equiv="Refresh" content="0;URL=/servletContext/ServletTest5">
  • 模仿注册成功,提示3秒后跳转到主页,或者点击‘这里’,直接跳转到主页
response.setContentType("text/html;charset=GBK");PrintWriter pw = response.getWriter();response.setHeader("Refresh", "3;URL=/servletContext/default.html");pw.println("注册成功!3秒后会自动转向主页。若没有发生跳转,请猛点<a href='/servletContext/default.html'>这里</a>");

控制客户端的缓存

  • 设置客户端缓存一个月
// 设置客户端缓存一个月response.setContentType("text/html;charset=UTF-8"); response.setDateHeader("Expires", System.currentTimeMillis() + 30 * 24 * 60 * 60 * 1000);response.getOutputStream().write("你好".getBytes("UTF-8"));;

通过response现实请求重定向

  • 请求重定向是指:一个Web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向。
  • 地址栏会变,并发送2次请求,增加服务器负担。
  • 实现方式:
    • response.sendRedirect()
    • 实现原理:
    • 302状态码和location头即可实现重定向。
//重定向到login.html页面response.sendRedirect("/servletContext/login.html");

response细节

  • getOutputStream()和getWriter()方法分别用于得到输出二进制数据、输出文本数据的ServletOutputStream、PrintWriter对象。
  • getOutputStream()和getWriter()这两个方法互相排斥,调用了其中的任何有一个方法后,就不能再调用另一个方法。会抛异常。
  • Servlet程序向ServletOutputStream或者PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当做响应消息的正文,然后再与响应状态行和各响应头组合后输出DOA客户端。( Servlet程序向ServletOutputStream或者PrintWriter对象将数据写到了response对象中,容器从response对象中获取响应行、响应头和正文)。
  • Servlet的service()方法结束后,Servlet引擎将检查getWriter()或getOutputStream()方法返回的输出流对象是否已经调用close()方法,如果没有,Servlet引擎将调用close()方法关闭输出流对象。

HttpServletRequest

  • HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获取客户端这些消息。

request常用的方法

  • 获取客户机 + 服务器信息
    • getRequestURL方法返回客户端发出请求时的完整URL。
    • getRequestURI方法返回请求行中的资源名部分。
    • getQueryString方法返回请求行中的参数部分。
    • getRemoteAddr方法返回发出请求的客户机的IP地址。
    • getRemoteHost方法发出请求的客户机的完整主机名。
    • getRemotePort方法返回客户机所使用的网络端口号。
    • getLocalAddr方法返回WEB服务器的IP地址。
    • getLocalName方法返回WEB服务器的主机名。
    • getMethod返回客户机的请求方式。
String url = request.getRequestURL().toString();String uri = request.getRequestURI();String attr = request.getQueryString();String remoteAddr = request.getRemoteAddr();String remoteHost = request.getRemoteHost();int remotePort = request.getRemotePort();String localAddr = request.getLocalAddr();String localName = request.getLocalName();String method = request.getMethod();
  • 获得客户机请求头
    • getHeader(name) 获取某个请求头的值
    • getHeaders(name) 获取某个请求头的值(有多个,全部返回出来)
    • getHeaderNames() 获取请求头的所有的键,而不是值。
String header = request.getHeader("Accept");pw.println(header + "<br/>");pw.print("<br/>");Enumeration<String> headers = request.getHeaders("Accept");while (headers.hasMoreElements()) {    String string = (String) headers.nextElement();    pw.println(string + "<br/>");}pw.print("<br/>");Enumeration<String> hh = request.getHeaderNames();while (hh.hasMoreElements()) {    String key = (String) hh.nextElement();    String value = request.getHeader(key);    pw.println(key + " = " + value + "<br/>");}
  • 获得客户机请求参数(客户提交的数据)
    • getParameter(name) 获取对应的值
    • getParameteValues(name) 获取对应的值[数组]
    • getParameterNames() 获取对应的键
    • getParameterMap()
    • getInputStream()

request处理中文乱码问题

  • 浏览器是什么编码就以什么编码传送数据。
  • 解决:
    • request.setCharacterEncoding(“UTF-8”); //POST有效
    • new String(username.getBytes(“ISO-8859-1”),”UTF-8”); //GET方式
    • 超链接:cn //GET方式
    • 更改Tomcat的配置解决URL编码问题:

request对象实现请求转发

  • request对象实现请求转发:请求转发指一个Web资源收到客户端请求后,通知服务器去调用另外一个Web资源进行处理。
  • request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispathcher对象,调用这个对象的forword方法可以实现请求转发。
  • request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其他Web资源处理。
    • setAttribute()
    • getAttribute()
    • removeAttribute()
    • getAttributeNames()
//得到请求转发器RequestDispatcherRequestDispatcher rd = request.getRequestDispatcher("/servlet/ServletDemo");rd.forward(request, response);

转发与包含

  • forward:浏览器访问Servlet1,Servlet1转发到Servlet2,Servlet2把结果返回给浏览器。
  • include:浏览器访问Servlet1,Servlet1包含了Servlet2,Servlet1把结果返回给浏览器。[这里指的是动态包含]

RequestDispatcher

  • 表示请求分发器,两个方法:

    • forward(): 把请求转发给目标组件
    • include(): 包含目标组件的响应结果
  • 得到RequestDispatcher对象

    • ServletContext对象的getRequestDispather(String path1),path1必须用绝对路径,即以”/”开头,若用相对路径会抛出异常。
    • ServletRequest对象的getRequestDispather(String path2),path2可以使用绝对路径也可以使用相对路径。

路径的写法

  1. 绝对路径:ServletContext都必须用绝对路径。”/”
  2. 相对路径:其他的都可以使用相对路径,也可以使用绝对路径
  3. 在使用绝对路径时,要不要加”/”或者项目名:

    • 是服务器调用的,不用加项目名,用”/”就可以代表了;
    • 是客户端调用的,必须加上项目名。

    • 转发:request.getRequestDispather(String url); – 当使用绝对路径时: “/ServletDemo” — 服务器

    • 重定向:response.sendRedirect(String url); – 当使用绝对路径时: “/servlet/ServletDemo” — 客户端
    • 超链接: – 当使用绝对路径时: “/servlet/ServletDemo” — 服务器
    • 类加载文件的路径 – web应用中只能用相对路径,相对于classes目录的
    • – 当使用绝对路径时: “/servlet/ServletDemo” — 服务器
    • 页面分帧(frame) – 当使用绝对路径时: “/servlet/ServletDemo”
    • ServletContext.getRealpath(url) – 当使用绝对路径时: “/servlet/ServletDemo”
1 0
原创粉丝点击