Tomcat+Servlet

目录

  • 1. Tomcat
    • 1.1 BS和CS再说明
    • 1.2 简单的Web服务程序
    • 1.3 Tomcat的安装,配置与启动
    • 1.4 Tomcat启动的故障和排除
    • 1.5 Tomcat目录说明
    • 1.6 catalina启动tomcat
    • 1.7 停止tomcat
    • 1.8 Tomcat部署Web应用
    • 1.9 浏览器请求资源UML分析
    • 2.0 修改Tomcat端口
  • 2. IDEA
    • 2.1 IDEA开发部署JavaWeb工程
    • 2.2 注意事项
      • 2.2.1 热加载说明
      • 2.2.2 端口修改
      • 2.2.3 out目录
      • 2.2.4 JavaWeb工程目录结构
  • 3. Servlet
    • 3.1 Servlet快速入门
    • 3.2 浏览器请求Servlet UML分析
    • 3.3 Servlet生命周期
    • 3.4 GET请求和POST请求
  • 4. HttpServlet
    • 4.1 IDEA配置Servlet
    • 4.2 Servlet注意事项
  • 5. Servlet注解
    • 5.1 注解详解
    • 5.2 initParams
    • 5.3 4种注解url匹配方式
    • 5.4 注解注意事项
  • 6. HTTP协议
    • 6.1 http请求&GET请求
    • 6.2 http请求&POST请求
    • 6.3 GET请求&POST区别与选择
    • 6.4 http响应
    • 6.5 状态码200和404
    • 6.6 状态码500
    • 6.7 状态码302
    • 6.8 状态码304
    • 6.9 MIME类型
  • 7. 动态WEB开发核心-Servlet
    • 7.1 ServletConfig
    • 7.2 ServletContext
      • 7.2.1 网站计数器
    • 7.3 HttpServletRequest
      • 7.3.1 细节1
      • 7.3.2 细节2
      • 7.3.3 细节3
    • 7.4 Dispathcer
      • 7.4.1 请求转发应用实例
      • 7.4.2 请求转发细节和注意事项
      • 7.4.3 习题
    • 7.5 HttpServletResponse
      • 7.5.1 请求重定向
      • 7.5.2请求重定向注意事项
      • 7.5.3 动态获取到application context
      • 7.5.4 练习题

1. Tomcat

Tomcat+Servlet_第1张图片

1.1 BS和CS再说明

Tomcat+Servlet_第2张图片

  1. 兼容性: 因为浏览器的种类太多, 会发现你写的程序, 在某个浏览器会出现问题,其它浏览器上正常;
  2. 安全性, 通常情况下, BS安全性不如CS好控制;
  3. 易用性, BS好于CS, 浏览器电脑有
  4. 扩展性, BS相对统一, 只需要写Server

1.2 简单的Web服务程序

http://localhost.9999 表示 浏览器向localhost(127.0.0.1 表示本机)的9999端口发出请求

Tomcat+Servlet_第3张图片

public class MyTomcat {
    public static void main(String[] args) throws IOException {
        //1.服务器在9999端口监听
        ServerSocket serverSocket = new ServerSocket(9999);
        //永远都不可能关闭, 一直监听
        while (!serverSocket.isClosed()) {
            System.out.println("web服务 在9999端口监听");
            //2.等待客户端/浏览器地址栏的连接
            Socket socket = serverSocket.accept();
            //3.通过socket得到输出流
            OutputStream outputStream = socket.getOutputStream();
            BufferedReader bufferedReader =
                    new BufferedReader(new FileReader("src/hello.html"));
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                // 返回给浏览器/客户端
                outputStream.write(line.getBytes());
            }
            //4.关闭流
            outputStream.close();
            socket.close();
        }
        serverSocket.close();
    }
}

1.3 Tomcat的安装,配置与启动

  1. zip压缩包解压到本地目录
  2. bin目录下双击startup.bat(或者在命令行窗口中输入startup.bat)启动Tomcat, 浏览器地址栏输入http://localhost:8080(默认8080端口)

开发中,可以使用netstat -anb(使用管理员权限)看一下哪些端口在监听
Tomcat+Servlet_第4张图片
Tomcat+Servlet_第5张图片

  1. 配置环境变量, 系统环境变量下新建CATALINA_HOME, 值为Tomcat目录,定位到bin的上级目录即可, 在Path下新增%CATALINA_HOME%\bin

1.4 Tomcat启动的故障和排除

双击startup.bat文件,出现一个小黑窗口就没有了,原因是没有配置JAVA_HOME环境变量,

  1. JAVA_HOME必须大写
  2. JAVA_HOME中必须有下划线
  3. JAVA_HOME配置的路径指定到jdk的安装目录即可,不必指定到bin目录下
  4. Tomcat是Java程序,会根据JAVA_HOME使用指定jdk, 所以一定要配置JAVA_HOME
  5. 如果其它服务程序占用了8080端口, Tomcat同样启动不了, 或者修改Tomcat服务的默认端口

1.5 Tomcat目录说明

Tomcat+Servlet_第6张图片

conf目录

  1. server.xml 用于配置tomcat的基本设置(启动端口, 关闭端口, 主机名)
    Tomcat+Servlet_第7张图片
  2. web.xml 用于指定tomcat运行时配置(比如servlet等…)

logs目录

  1. tomcat启动一次会产生五个日志文件Tomcat+Servlet_第8张图片

webapps目录

  1. 存放web应用, 也就是网站
    在webapps下新建test目录
    在test目录下新建html文件, 文件中用img标签引用backgroundImage.webp
    地址栏访问: http://localhost:8080/test/hello.html即可Tomcat+Servlet_第9张图片
    Tomcat+Servlet_第10张图片

1.6 catalina启动tomcat

  1. 在bin目录下打开cmd
    Tomcat+Servlet_第11张图片
  2. 输入 catalina run
    Tomcat+Servlet_第12张图片

1.7 停止tomcat

  1. 点击Tomcat服务器窗口右上角的×号关闭,相当于意外终止, 这个关闭指令不会产生日志
    Tomcat+Servlet_第13张图片
  2. 运行Tomcat的bin目录下的shutdown.bat, 就可以停止Tomcat服务器(推荐)
    Tomcat+Servlet_第14张图片

1.8 Tomcat部署Web应用

JavaWeb程序应用工程目录结构

Tomcat+Servlet_第15张图片

部署方式一

  1. 将web工程的目录拷贝到Tomcat的webapps目录下
  2. 浏览器输入http://ip[域名]:port/子目录…/web资源

部署方式二: 通过配置文件来部署

  1. 在Tomcat的conf目录/Catalina/localhost/下配置文件
    Tomcat+Servlet_第16张图片
    test.xml文件名最好和path="/test"保持一致
    Tomcat+Servlet_第17张图片
    访问http://ip[域名]:port/test/hello.html就相当于
    访问D:\zzw目录下的hello.html
    作用: 可以把一个Web应用,映射到指定的目录,用来解决磁盘空间分配的问题

ROOT工程的访问

  1. 在浏览器地址栏输入 :http://ip[域名]:port, 不加Web工程名/应用名时,访问的是ROOT工程
  2. 在浏览器地址栏输入 :http://ip[域名]:port/工程名/, 不加资源名时, 默认访问index.jsp; 比如:http://localhost:8080/test

1.9 浏览器请求资源UML分析

Tomcat+Servlet_第18张图片

修改hosts文件, 先复制一份到别处,修改之后再覆盖

2.0 修改Tomcat端口

Tomcat目录下的conf目录, 修改server.xml配置文件
Tomcat+Servlet_第19张图片

  1. 默认端口8080, 端口号范围1~65535
  2. 修改端口号建议大于1024, 最好在10000以上
  3. 修改后,重启tomcat生效

http://localhost, 默认是访问80端口, 即http://localhost:80

2. IDEA

2.1 IDEA开发部署JavaWeb工程

文档JavaWeb学习资料\资料\Tomcat\IDEA2020.2中开发JavaWeb工程.docx

Tomcat+Servlet_第20张图片
Tomcat+Servlet_第21张图片
Tomcat+Servlet_第22张图片
Tomcat+Servlet_第23张图片
Tomcat+Servlet_第24张图片

2.2 注意事项

2.2.1 热加载说明

Tomcat+Servlet_第25张图片

  1. on ‘Update’ action: 表示当我们更新操作时, Tomcat会自动更新类和资源(当 jsp / html文件修改时,可以立即生效, 但是如果修改的是java文件, 需要redeploy重新部署才会生效)
  2. on frame deactivation: 表示IDEA失去焦点时(比如最小化), 也会导致 jsp / html 发生更新, 但是如果修改的是java文件, 需要redeploy重新部署才会生效

2.2.2 端口修改

Tomcat+Servlet_第26张图片
3. 这里修改端口只会影响到当前项目的tomcat端口,而不会去修改server.xml
4. 当Tomcat启动时, 会生成out目录, 该目录就是原项目资源的映射, 我们浏览器访问的资源就是out目录中的web资源

2.2.3 out目录

  1. 当我们从外部拷贝资源到项目(图片, 文件, js, css等),如果出现404不能访问错误, 解决方式 rebuild project -> 重启Tomcat

2.2.4 JavaWeb工程目录结构

Tomcat+Servlet_第27张图片

3. Servlet

3.1 Servlet快速入门

Tomcat+Servlet_第28张图片

  1. 新建JavaWeb工程
  2. 项目上右键Add Framework Support导入Web框架
  3. 配置Tomcat
  4. 在WEB-INF目录下新建lib文件夹, 导入servlet-api.jar包
  5. 在com.zzw.servlet包下新建HelloServlet.java文件
package com.zzw.servlet;

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

/**
 * @author 赵志伟
 * @version 1.0
 * 1.开发一个Servlet需要实现Servlet接口
 * 2.实现Servlet接口的五个方法
 */
@SuppressWarnings({"all"})
public class HelloServlet implements Servlet {

    private int count;

    /**
     * 1.初始化 servlet
     * 2.当创建HelloServlet实例时, 会调用init方法
     * 3.该方法只会被调用一次
     *
     * @param servletConfig
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init() 被调用");
    }

    /**
     * 返回ServletConfig 也就是返回Servlet的配置
     *
     * @return
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 1.service方法处理浏览器的请求(包括get和post)
     * 2.当浏览器每次请求Servlet时,就会调用一次service方法
     * 3.当tomcat调用该方法时,会把http请求的数据封装成实现了ServletRequest接口的request对象
     * 4.通过servletRequest对象,可以得到用户提交的数据
     * 5.servletResponse对象可以用于返回数据给tomcat->浏览器
     *
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest,
                        ServletResponse servletResponse) throws ServletException, IOException {
        //如果count的值,在不停的累计, 说明HelloServlet是单例的
        System.out.println("hi HelloServlet~, count=" + count++);
    }

    /**
     * 返回servlet的信息,使用较少
     * @return
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 1.该方法是在servlet销毁时,被调用
     * 2.只会调用一次
     */
    @Override
    public void destroy() {

    }
}

web.xml注释时发现前面有空格
Tomcat+Servlet_第29张图片
解决方案 Settings->Editor->Code Style->XML, 取消勾选
Tomcat+Servlet_第30张图片
IDEA配置快捷键: settings->Keymap
重启(Alt+R)选择重新部署,速度快, 不要选Restart server, 这样会把JDK都重启, 速度很慢
Tomcat+Servlet_第31张图片

  1. 在web.xml文件中配置由Tomat访问HelloServlet的路径

<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">
    
    
    <servlet>
        <servlet-name>HelloServletservlet-name>
        <servlet-class>com.zzw.servlet.HelloServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>HelloServletservlet-name>
        <url-pattern>/helloServleturl-pattern>
    servlet-mapping>
web-app>

3.2 浏览器请求Servlet UML分析

Tomcat+Servlet_第32张图片

3.3 Servlet生命周期

  • Servlet加载阶段

Servlet容器(比如:
Tomcat) 加载Servlet, 加载完成后, Servlet容器会创建一个Servlet实例并调用init()方法(创建的实例放入HashMap), init()方法只会调用一次, Servlet容器在下面的几种情况下会装载Servlet:

  1. 第一种情况: 在web.xml添加1后, Servlet容器(Tomcat)在启动时或是在重新部署时会装载servlet, 即调用init()方法(1代表装载的顺序)
  2. 第二种情况: 在web.xml中放弃添加1, 在Servlet容器启动后, 浏览器首次向Servlet发送请求
    Tomcat+Servlet_第33张图片
  3. 第三种情况: Servlet重新装载时(比如tomcat 进行redeploy, 这个动作会销毁所有的Servlet, 再重新创建Servlet), 重新装载包括两种情况: 第一种情况是web.xml有1, 这时会调用init方法, 第二种情况是web.xml没有1, 这时在浏览器请求时调用init(), service()方法
  • 处理浏览器请求阶段(service方法)
  1. 每收到一个http请求, 服务器就会产生一个新的线程处理
  2. 创建一个用于封装HTTP请求消息的ServletRequest对象和一个代表HTTP响应消息的ServletResponse对象
  3. 然后调用Servlet的service()方法并将请求和响应对象, 并将请求和响应对象作为参数传递进去
  • 终止阶段destroy方法
    当web应用被终止, 或者Servlet容器终止运行, 或者Servlet类重新装载时, 会调用destroy方法

3.4 GET请求和POST请求

shortcuts: ctrl+alt+b 查看子接口或子类

@Override
    public void service(ServletRequest servletRequest,
                        ServletResponse servletResponse) throws ServletException, IOException {
        //如果count的值,在不停的累计, 说明HelloServlet是单例的
        System.out.println("hi HelloServlet~, count=" + count++);
        //System.out.println("当前线程id=" + Thread.currentThread().getId());
        //1.从ServletRequest 没有得到 获取请求方式 的方法
        //2.ServletRequest的子接口有无相关方法 shortcuts: ctrl+alt+b可以看到子接口和实现类
        //3.servletRequest 转成HttpServletRequest引用
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String method = httpServletRequest.getMethod();
        if ("GET".equals(method)) {
            deGet();
        } else if ("POST".equals(method)) {
            doPost();
        }
    }

    /*
    用于响应get请求
     */
    public void deGet() {
        System.out.println("deGet() Method");
    }
    /*
    响应post请求
     */
    public void doPost() {
        System.out.println("doPost() Method ");
    }

4. HttpServlet

Tomcat+Servlet_第34张图片

public class HiServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hiServlet doGet()");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hiServlet doPost()");
    }
}

web.xml配置


    <servlet>
        <servlet-name>HiServletservlet-name>
        <servlet-class>com.zzw.servlet.HiServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>HiServletservlet-name>
        <url-pattern>/hiServleturl-pattern>
    servlet-mapping>

4.1 IDEA配置Servlet

在WEB-INF目录下的lib文件夹下导入servlet-api.jar包并且Add As Library后右键才有新建Servlet的选项

Tomcat+Servlet_第35张图片
Tomcat+Servlet_第36张图片
会自动生成Servlet类和web.xml配置

public class OkServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //可以写自己的业务处理代码
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //可以写自己的业务处理代码
    }

web.xml自动生成以下半截代码, 这里需要手动配置url-pattern
Tomcat+Servlet_第37张图片

4.2 Servlet注意事项

  1. Servlet是一个供其它Java程序(Servlet)引擎调用的Java类, 不能独立运行
  2. 针对浏览器的多次Servlet请求, 通常情况下, 服务器只会创建一个Servlet实例对象, 也就是说Servlet实例对象一旦创建, 它就会驻留在内存中,存在于Tomcat维护的HashMap中, 为后续的其他请求而服务, 直至web容器退出/或者redeploy该web应用, servlet实例对象才会销毁, 从HashMap中移除
  3. 在Servlet的整个生命周期中,init方法只被调用一次, 而对每次请求都导致Servlet引擎调用一次servlet的service方法
  4. 对于每次访问请求, Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象, 然后将这两个对象作为参数传递给它调用的Servlet的service()方法, service方法再根据请求方式分别调用doGet()方法和doPost()方法
  5. 如果在元素中配置了一个元素, 那么web应用程序在启动时, 就会装载并创建Servlet的实例对象, 以及调用Servlet实例对象的init()方法

5. Servlet注解

省去了在web.xml配置的麻烦

方法外不能使用.var

/**
 * 显示方法之间的分割线 Editor->General->Appearance->Show method separators
 * 1.@WebServlet是一个注解
 * 2.@WebServlet的源码
 * 3.urlPatterns 对应web.xml中的 
 *   {"/ok1", "/ok2"} 可以给OkServlet配置多个 urlPattern
 *   相当于这个@WebServlet(urlPatterns={"/ok1", "/ok2"}) 代替了web.xml的配置
 * 4.浏览器可以这样访问OkServlet: http://localhost:8080/servlet/ok1 或者 http://localhost:8080/servlet/ok2
 */
@WebServlet(urlPatterns = {"/ok1", "/ok2"})
public class OkServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("annotation doGet method");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("annotation doPost method");
    }
}

@WebServlet注解源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented => 在javadoc工具生成记录
public @interface WebServlet {
    String name() default "";

    String[] value() default {};

    String[] urlPatterns() default {};

    int loadOnStartup() default -1;

    WebInitParam[] initParams() default {};

    boolean asyncSupported() default false;

    String smallIcon() default "";

    String largeIcon() default "";

    String description() default "";

    String displayName() default "";
}

5.1 注解详解

Tomcat+Servlet_第38张图片

  1. 注解是对包进行扫描, 如果发现某个类是用@WebServlet, 就说明该类是Servlet, 然后读取urlPatterns, 看看请求的资源和urlPatterns的参数是否一致

模拟代码

/**
 * @author 赵志伟
 * @version 1.0
 * 模拟Tomcat是如何通过注解@WebServlet(urlPatterns={"/ok1", "/ok2"})来装载一个Servlet的
 */
@SuppressWarnings({"all"})
public class TestAnnotationServlet {

    private static final HashMap<String, HttpServlet> hm = new HashMap<>();
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //1.首先要得到扫描的包 路径 IO, 进而得到类的全路径
        String path = "com.zzw.servlet.annotation.OkServlet";
        //2.得到OkServlet的Class对象
        Class<?> aClass = Class.forName(path);
        //3.根据class对象得到对应的注解
        WebServlet annotation = aClass.getAnnotation(WebServlet.class);
        String[] urlPatterns = annotation.urlPatterns();
        for (String urlPattern : urlPatterns) {
            System.out.println("urlPattern=" + urlPattern);
        }
        //如果匹配url, 如果是第一次, tomcat就会创建一个OkServlet实例, 放入到HashMap中
        Object instance = aClass.newInstance();
        System.out.println("instance=" + instance);//OkServlet实例

        hm.put("OkServlet", (HttpServlet) instance);
        System.out.println(hm);
    }
}

5.2 initParams

@WebServlet(urlPatterns = {"/ok1", "/ok2"}, initParams = {@WebInitParam(name = "zzw", value = "123"), @WebInitParam(name = "xx", value = "yy")})
public class OkServlet extends HttpServlet {}

等同于

<servlet>
        <servlet-name>OkServletservlet-name>
        <servlet-class>com.zzw.servlet.OkServletservlet-class>

        <init-param>
            <param-name>zzwparam-name>
            <param-value>123param-value>
        init-param>
        <init-param>
            <param-name>xxparam-name>
            <param-value>yyparam-value>
        init-param>
    servlet>

5.3 4种注解url匹配方式

  • 精准匹配
@WebServlet(urlPatterns = {"/ok1/aa/bb", "/ok2"}
  • 目录匹配
@WebServlet(urlPatterns = {"/ok1/*", "/ok2"})
http://localhost:8888/servlet/ok1
http://localhost:8888/servlet/ok1/aa
http://localhost:8888/servlet/ok1/aa/bb/cc
  • 扩展名匹配
@WebServlet(urlPatterns = {"*.action", "/ok2"}
http://localhost:8888/servlet/zzw.action
http://localhost:8888/servlet/zzw.521.action

不能带斜杠

@WebServlet(urlPatterns = {"/*.action", "/ok2"},这样是错误的
  • 任意匹配
@WebServlet(urlPatterns = {"/", "/ok2"}
或者
@WebServlet(urlPatterns = {"/*", "/ok2"}
http://localhost:8888/servlet/aa/bb/cc
http://localhost:8888/servlet/zzw.521.action

5.4 注解注意事项

shortcuts: ctrl+alt+⬅ 回到上次访问的窗口

  1. 当Servlet配置了"/", 会覆盖掉tomcat的DefaultServlet, 当其它的的url-pattern都匹配不上时, 就会走这个默认的Servlet, 这样可以拦截到其它请求中的静态资源

这个默认的Servlet是处理静态资源的, 一旦拦截, 静态资源则不能处理

 
  
  
  
	<servlet>
        <servlet-name>defaultservlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServletservlet-class>
        <init-param>
            <param-name>debugparam-name>
            <param-value>0param-value>
        init-param>
        <init-param>
            <param-name>listingsparam-name>
            <param-value>falseparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>
  1. 当Servlet配置了"/*", 表示可以匹配任意访问路径
  2. 建议不要使用/ 和 /*, 尽量使用精准匹配
  3. 优先级遵守: 精确路径 > 目录路径 > 扩展名路径 > /* > / > DefaultServlet(访问静态资源)
访问:http://localhost:8888/servlet/ok1/aa
@WebServlet(urlPatterns = {"/ok1/aa"}//优先
@WebServlet(urlPatterns = {"/ok1/*"}

6. HTTP协议

6.1 http请求&GET请求

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("LoginServlet doGet method");
        //输出一句话,给浏览器
        //1.通过response获取流Print Writer,它可以给浏览器回复数据
        //2.为了让浏览器显示中文,需要告诉浏览器我们的编码是utf-8
        //解读: setContentType给回送数据设置编码
        //(1)text/html这个是MIME类型即告诉浏览器返回的数据是text类型下的html格式数据[MIME类型 大类型/小类型]
        //(2)charset=utf-8数据编码
        //细节: 设置编码格式要在.getWriter()之前
        response.setContentType("text/html; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("

登陆成功

"
); //flush()会将缓存的数据刷新, 大多数语言的 close() 包含 flush() writer.flush(); //close() 关闭流, 及时释放资源 writer.close(); }

Tomcat+Servlet_第39张图片

6.2 http请求&POST请求

@Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("LoginServlet doPost method");
        response.setContentType("text/html; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("

POST 登陆成功

"
); writer.flush(); writer.close(); }

Tomcat+Servlet_第40张图片
Tomcat+Servlet_第41张图片

6.3 GET请求&POST区别与选择

  • GET请求有哪些
  1. form 标签 method=get
  2. a 标签
  3. link 标签引入 css[以get方式来获取资源]
  4. Script 标签引入 js[以get方式来获取资源]
  5. img标签引入css[以get方式来获取资源]
  6. 在浏览器地址栏中输入地址敲回车
  • POST请求有哪些
  1. form 标签 method=post
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>logintitle>
    <link type="text/css" rel="stylesheet" href="css/my.css">
    <script type="text/javascript" src="js/my.js">script>
head>
<body>

<form action="http://localhost:8080/http/login" method="post">
  username: <input type="text" name="username"/><br/>
  password: <input type="password" name="password"/><br/>
  <input type="submit" value="登录"/>
form>
<a href="http://www.baidu.com">goto百度a>
<img src="imgs/1.png" width="245px">
body>
html>
  • GET传输的数据大小区别
  1. get传送的数据量较小, 不能大于2KB(不同浏览器不一样)
  2. post传送的数据量较大, 数据藏在请求体里, 一般默认不受限制
  • 什么情况下使用POST请求
  1. post请求是会在浏览器上隐藏参数部分的, 在安全要求的部分都会使用到POST请求, 比如用户登录, 数据增删改等等.都会把参数隐藏起来, 这样就不会通过请求暴露自己的参数格式
    比如: del?id=1, 别人就可以用del?id=2来删除你的其它数据
  2. 在向server传递的数据较大的时候, 使用POST, get是有限制的, 比如发帖, 上传文件
  • 什么情况下使用GET请求
  1. 在前台页面展示, 比如分页内容, 可以保留传递参数, 可用来非常好地分享和传播, POST中链接地址是不变化的
  2. get方式的安全性较post方式要差些, 包括机密信息的话, 建议使用post数据提交方式
  3. 在做数据查询时, 建议使用get方式; 而在做数据插入, 改动, 或删除时, 建议使用post方式

6.4 http响应

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>logintitle>
    <link type="text/css" rel="stylesheet" href="css/my.css">
    <script type="text/javascript" src="js/my.js">script>
head>
<body>

<form action="http://localhost:8888/http/login" method="post">
  username: <input type="text" name="username"/><br/>
  password: <input type="password" name="password"/><br/>
  <input type="submit" value="登录"/>
form>
<a href="http://www.baidu.com">goto百度a>
<img src="imgs/1.png" width="245px">
body>
html>

Tomcat+Servlet_第42张图片

6.5 状态码200和404

Tomcat+Servlet_第43张图片

当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
HTTP状态码的英文为HTTP Status Code。

  • 200
    OK 请求成功。一般用于GET与POST请求
    Tomcat+Servlet_第44张图片
    Tomcat+Servlet_第45张图片
  • 404
    Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
    在这里插入图片描述
    Tomcat+Servlet_第46张图片
    Tomcat+Servlet_第47张图片

6.6 状态码500

服务器内部错误, 无法完成请求.
Tomcat+Servlet_第48张图片
Tomcat+Servlet_第49张图片

6.7 状态码302

  • 301
    Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
  • 302
    Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI

步骤

  1. 浏览器请求Status_302
  2. Status_302返回302的状态码, 并且指定浏览器重定向到login.html
  3. 浏览器发出第二次请求 访问login.html
  4. 浏览器测试抓包
    在这里插入图片描述
    Tomcat+Servlet_第50张图片
public class Status_302 extends HttpServlet {
    //将两个请求合并
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //如果有一个请求来了
        // 重定向到servlet/login.html
        // (1)返回302状态码 (2)响应头会带上Location:/login.html
        response.sendRedirect("/servlet/login.html");
        //response.sendRedirect("http://www.baidu.com");
    }
}

6.8 状态码304

  • 304
    Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源

Tomcat+Servlet_第51张图片

6.9 MIME类型

MIME是HTTP协议中的数据类型. MIME的英文全称是"Multipurpose Internet Mail Extension", 即多功能Internet邮件扩展服务, MIME类型的格式是"大类型/小类型", 并与某一种文件的扩展名相对应

文件 MIME类型
超文本标记语言文本 .html, .htm text/html
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
GIF图形 .gif image/gif
JPEG图形 .jpeg, .jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 .mid, midi audio/mid, audio/x-midi
RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG文件 .mpg, .mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz appcalition/x-gzip
TAR文件 .tar application/x-tar

7. 动态WEB开发核心-Servlet

7.1 ServletConfig

  • ServletConfig基本介绍
  1. ServletConfig 类是为Servlet程序配置信息的类
  2. Servlet程序 和ServletConfig对象都是由Tomcat负责创建的
  3. Tomcat在创建的Servlet程序时, 就创建一个对应的ServletConfig对象

功能

  1. 获取Servlet程序的servlet-name值
  2. 获取初始化参数init-param
  3. 获取ServletContext对象

需求: 编写DBServlet.java

  1. 在web.xml中编写连接mysql的用户名和密码
  2. 在DBServlet执行doGet() / doPost()方法时, 均可以获取到web.xml配置的用户名和密码

思路分析
Tomcat+Servlet_第52张图片

实现

public class DBServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //DBServlet的父类GenericServlet有getServletConfig()
        /**
         * 1. getServletConfig()是父类GenericServlet类的
         * 2. 返回的servletConfig对象是GenericServlet中的 private transient ServletConfig config;
         * 3. 当一个属性被transient修饰, 表示该属性不会被串行化
         */
        ServletConfig servletConfig = this.getServletConfig();//拿到的是GenericServlet中的config
        String username = servletConfig.getInitParameter("username");
        String password = servletConfig.getInitParameter("password");
        System.out.println("doPost中=" + servletConfig);
        System.out.println("初始化参数:username=" + username);
        System.out.println("初始化参数:password=" + password);
    }
}

注意事项
Tomcat+Servlet_第53张图片

7.2 ServletContext

  • 引出ServletContext

需求: 如果我们希望统计某个web应用所有的Servlet被访问的次数, 怎么办?
Tomcat+Servlet_第54张图片
Tomcat+Servlet_第55张图片

  • ServletContext介绍
  1. ServletContext是一个接口, 他表示Servlet上下文对象
  2. 一个web工程, 只有一个ServletContext对象实例
  3. ServletContext对象是web工程启动的时候由tomcat创建, 在web工程停止的时候销毁
  4. ServletContext对象可以通过ServletConfig.getServletContext()方法获得ServletContext对象的引用, 也可以通过this.getServletContext()来获得其对象的引用
  5. 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象, 因此Servlet对象之间可以通过ServletContext对象来实现通信. ServletContext对象通常也称之为域对象.

功能(需求)

  1. 获取web.xml 中配置的上下文参数context-param[这个信息和整个web应用相关, 而不是属于某个Servlet]
  2. 获取当前的工程路径, 格式: /工程路径, 比如 /servlet
  3. 获取工程部署后在服务器硬盘上的绝对路径 (比如: D:\idea_project\zzw_javaweb\servlet\out\artifacts\servlet_war_exploded)
  4. 向Map一样存取数据, 多个Servlet共享数据

思路分析
Tomcat+Servlet_第56张图片

准备工作
在这里插入图片描述

实现

public class ServletContext_ extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取web.xml的context-parameter
        // (1)得到ServletContext对象
        ServletContext servletContext = getServletContext();
        // (2)获取website
        String website = servletContext.getInitParameter("website");
        String favorite = servletContext.getInitParameter("favorite");
        //2.获取当前项目的工程路径
        String contextPath = servletContext.getContextPath();// /servlet
        //3.获取项目发布后真正的工作路径
        //  (1)这个/表示我们的发布后的项目的根路径,即
        //  (2)D:\idea_project\zzw_javaweb\servlet\out\artifacts\servlet_war_exploded
        String realPath = servletContext.getRealPath("/");

        System.out.println("website=" + website);
        System.out.println("favorite=" + favorite);
        System.out.println(contextPath);
        System.out.println("项目发布后的绝对路径=" + realPath);
    }
}

7.2.1 网站计数器

  • 准备工作
    创建OrderServlet, PayServlet, 并配置
    Tomcat+Servlet_第57张图片
  • 代码
    OrderServlet
public class OrderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        //从servletContext获取 visit_count属性 k-v
        Object visit_count = servletContext.getAttribute("visit_count");
        //判断visitCount是否为空
        if (visit_count == null) {//说明是第一次访问网站
            visit_count = 1;
            servletContext.setAttribute("visit_count", visit_count);
        } else {
            //取出visit_count的值 + 1
            visit_count = Integer.parseInt(visit_count.toString()) + 1;
            servletContext.setAttribute("visit_count", visit_count);
        }
        //输出
        response.setContentType("text/html; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("

网站被访问的次数 " + visit_count + " 次

"
); //刷新 writer.flush(); writer.close(); } }

PayServlet

public class PayServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        //从servletContext获取 visit_count属性 k-v
        Object visit_count = servletContext.getAttribute("visit_count");
        //判断visitCount是否为空
        if (visit_count == null) {//说明是第一次访问网站
            visit_count = 1;
            servletContext.setAttribute("visit_count", visit_count);
        } else {
            //取出visit_count的值 + 1
            visit_count = Integer.parseInt(visit_count.toString()) + 1;
            servletContext.setAttribute("visit_count", visit_count);
        }
        //输出
        response.setContentType("text/html; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("

网站被访问的次数 " + visit_count + " 次

"
); //刷新 writer.flush(); writer.close(); } }

封装

public class WebUtils {
    private static Object visit_count;
    public static Integer visitCount(ServletContext servletContext, HttpServletResponse response) throws IOException {
        //从servletContext获取 visit_count属性 k-v
        visit_count = servletContext.getAttribute("visit_count");
        //判断visitCount是否为空
        if (visit_count == null) {//说明是第一次访问网站
            visit_count = 1;
            servletContext.setAttribute("visit_count", visit_count);
        } else {
            //取出visit_count的值 + 1
            visit_count = Integer.parseInt(visit_count.toString()) + 1;
            servletContext.setAttribute("visit_count", visit_count);
        }
        return Integer.parseInt(visit_count + "");
    }
}
  • 实现
public class OrderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        int visit_count = WebUtils.visitCount(servletContext, response);
        //输出
        response.setContentType("text/html; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("

网站被访问的次数 " + visit_count + " 次

"
); //刷新 writer.flush(); writer.close(); } }
  • 测试
    Tomcat+Servlet_第58张图片

7.3 HttpServletRequest

  1. HttpServletRequest对象代表客户端的请求
  2. 当客户端/浏览器通过HTTP协议访问服务器时, HTTP请求头中所有的信息都封装在这个对象中
  3. 通过这个对象的方法, 可以获取客户端信息
  • 常用方法
  1. getRequestURI() 获取请求的资源路径 http://localhost:8080/servlet/login.html
  2. getRequestURL() 获取请求的统一资源定位符(绝对路径) http://localhost:8080/servlet/login.html
  3. getHeader() 获取请求头
  4. getParameter() 获取请求的参数
  5. getParameterValues() 获取请求的参数(多个值时使用) 比如checkbox, 或返回的数组
  6. getRemoteHost() 获取客户端的主机
  7. getRemoteAddr() 获取客户端的ip
  8. getMethod() 获取请求的方式(GET或POST)
  9. setAttribute(key, value) 设置域数据
    10.getRequestDispatcher() 获取请求转发对象(核心对象)
public class HttpServletRequestMethods extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /********************************
         *      获取http请求头相关信息      *
         ********************************/
        System.out.println("请求头信息");
        System.out.println("资源路径URI(请求中的)=" + request.getRequestURI());
        System.out.println("统一资源定位符(绝对路径)URL=" + request.getRequestURL());
        System.out.println("客户端ip地址=" + request.getRemoteAddr());
        //获取http请求头的信息: 可以使用request.getHeader("请求头字段")
        // 可以指定 Accept, Accept-Encoding, Accept-Language, Connection, Cookie, Host, Referer
        String accept = request.getHeader("Accept");
        System.out.println("http请求头中的Accept信息=" + accept);
        /********************************
         *        获取表单提交的数据        *
         ********************************/
        //1.获取单个表单数据
        // 解决接收参数的中文乱码问题, 不能写在request.getParameter()后面
        request.setCharacterEncoding("utf-8");//浏览器按照urlEncode编码方式提交数据, 后端要用utf-8来接收
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("username=" + username);
        System.out.println("password=" + password);//前端不填传给后端则是一个空字符串"", 不是null
        //2.获取一组表单数据 复选框, 下拉框
        String[] favorites = request.getParameterValues("favorite");
        if (favorites != null) {//复选框前端不选则后端返回一个null
            for (String favorite : favorites) {
                System.out.println(favorite);
            }
        }
    }
}

7.3.1 细节1

  1. text, date, password, email类型的输入框和下拉框如果不填值会将空字符串传给后端:username=&password=&date=, 后端用request.getParameter()接收这些值便是空字符串
  2. 单选框, 复选框如果不选(不包括下拉框), 则不向后台传值, 即username=&password=&date=这里根本就没有单选框和复选框的参数, 后台通过request.getParameter()或request.getParameterValues()获取实际上是获取了一个不存在的参数. 如果单选框, request.getParameter()返回一个字符串, 这个字符串为null, 如果是复选框, request.getParameterValues()返回字符串数组, 那么这个字符串数组为null, 如果对这个字符串数组遍历会报错, 因为null.length会报错

7.3.2 细节2

  1. 浏览器按照urlEncode编码方式提交数据, 后端要用utf-8来接收: request.setCharacterEncoding(“utf-8”); 且这句话要写在request.getParameter()前面
  2. 后台将接收的数据返回给页面时, 要设置响应头的Content-Type参数为text/html; charset=utf-8, 因为数据中包含中文, 并且是文本类型
    //本质实在http响应头加上Content-Type: text/html;charset=utf-8
    response.setContentType("text/html; charset=utf-8");
    PrintWriter writer = response.getWriter();
    writer.print("

提交的用户名=" + username + "

"
); writer.flush(); writer.close();

7.3.3 细节3

再次理解Http协议Content-Type的含义, text/html 表示返回的数据类型, 浏览器会根据这个类型来解析数据

    //本质实在http响应头加上Content-Type: text/html;charset=utf-8
    // text/plain 表示返回的数据,请浏览器使用文本方式解析
    // application/x-tar 表示返回的是一个文件,浏览器就会以下载文件的方式处理
    response.setContentType("application/x-tar; charset=utf-8");
    PrintWriter writer = response.getWriter();
    writer.print("

提交的用户名=" + username + "

"
); writer.flush(); writer.close();

7.4 Dispathcer

Tomcat+Servlet_第59张图片

  1. 实现请求转发: 请求转发指一个web资源收到客户端请求后, 通知服务器(比如Tomcat)去调用另外一个web资源进行处理
  2. HttpServletRequest对象(也叫Request对象)提供了一个getRequestDispather方法, 该方法返回一个RequestDispacher对象, 调用这个对象的forward方法可以实现请求转发
  3. request对象同时也是一个域对象, 开发人员通过request对象在实现转发时, 把数据通过request对象带给其它web资源
    setAttribute方法
    getAttribute方法
    removeAttribute方法
    getAttributeNames方法
    Tomcat+Servlet_第60张图片

7.4.1 请求转发应用实例

前提: 新建两个Servlet, 并做好配置

public class CheckServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("CheckServlet doPost 输出");
        //根据用户名来确定该用户是什么身份
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        //注意: 如果是同一个request对象(请求转发), 那么可以在不同的Servlet中使用getParameter取出同一个参数
        if ("猫".equals(username)) {
            //分配管理员权限
            request.setAttribute("role", "管理员");
        } else {
            request.setAttribute("role", "普通用户");
        }
        //获取分发器
        //解读一下:1./managerServlet写的是 要转发的servlet的url
        //       2./ 会被解析成 /servlet
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/managerServlet");
        //       3.forward(request, response) 会把当前Servlet的request,response对象传给下一个Servlet使用
        requestDispatcher.forward(request, response);
    }
}
public class ManagerServlet extends HttpServlet {
    private int count;
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        String role = (String) request.getAttribute("role");

        //输出
        response.setContentType("text/html; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("

用户名 " + username + "

"
); writer.print("

角色=" + role + "

"
); writer.flush(); writer.close(); } }

7.4.2 请求转发细节和注意事项

  1. 浏览器地址栏不会发生变化(地址会停留在第1个servlet的url)
  2. 在同一次HTTP请求中, 进行多次转发, 仍然是一次HTTP请求
  3. 在同一次HTTP请求中, 进行多次转发, 多个Servlet可以共享request域/对象的数据(因为始终是同一个request对象)
  4. 可以转发到WEB-INF目录下
  5. 不能访问当前WEB工程外的资源
    Tomcat+Servlet_第61张图片

7.4.3 习题

编写一个Servlet获取请求参数中的操作系统和位数

public class GetInfoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //谷歌浏览器:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36
        String userAgent = request.getHeader("User-Agent");
        String regStr = "\\(([\\w\\ \\.;]+)\\)";
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(userAgent);
        matcher.find();
        //group(0) = (Windows NT 10.0; Win64; x64)
        //group(1) = Windows NT 10.0; Win64; x64
        String[] split = matcher.group(1).split(";");
        System.out.println("操作系统=" + split[0]);
        System.out.println("操作系统位数=" + split[1].trim());
    }
}

7.5 HttpServletResponse

  • 基本介绍
  1. 每次HTTP请求, Tomcat会创建一个HttpServletResponse对象传递给Servlet使用
  • 乱码问题
  1. 处理乱码问题方案1
    Tomcat+Servlet_第62张图片
  2. 处理乱码问题方案2
    在这里插入图片描述

7.5.1 请求重定向

  1. 请求重定向是指: 一个web资源收到客户端请求后, 通知客户端去访问另外一个web资源, 这称之为重定向
  2. 请求重定向分析图
    Tomcat+Servlet_第63张图片
    测试代码
public class DownServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("DownServlet 自己的业务");
        //1.sendRedirect 本质会返回一个 302状态码 和 Location: /servlet/downServletNew
        //2.因此 302状态码 和 /servlet/downServletNew是浏览器解析的
        //3.浏览器会将 /servlet/downServletNew 解析成http://localhost:8080/servlet/downServletNew
        response.sendRedirect("/servlet/downServletNew");
    }
}

public class DownServletNew extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("DownServletNew doPost");
        response.setContentType("application/x-tar; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.println("

下载完成

"
); writer.flush(); writer.close(); } }
<body>
<h2>下载文件h2>
<a href="http://localhost:8888/servlet/downServlet">下载<<三体>>小说a>
body>

测试结果
在这里插入图片描述
Tomcat+Servlet_第64张图片

7.5.2请求重定向注意事项

  1. 最佳应用场景: 网站迁移, 比如原域名是 www.zzw.com 迁移到 www.world.cn, 但是百度抓取的还是原来的网址
  2. 浏览器地址会发生变化, 本质是两次Http请求
  3. 不能共享Request域中的数据, 本质是两次Http请求, 会生成两个HttpServletRequest对象
  4. 不能重定向到WEB-INF下的资源
  5. 可以重定向到Web工程以外的资源, 比如到http://www.baidu.com
  6. 重定向有两种方式, 推荐使用第1种
//第一种重定向使用
response.sendRedirect("/servlet/downServletNew");
//第二种重定向使用
        response.setStatus(302);//设置http响应的状态码
        //设置http响应的Location: /servlet/downServletNew
        response.setHeader("Location", "/servlet/downServletNew");

7.5.3 动态获取到application context

Tomcat+Servlet_第65张图片

//动态获取 application context
String contextPath = getServletContext().getContextPath();
System.out.println(contextPath);// /servlet
response.sendRedirect(contextPath + "/downServletNew");

Tomcat+Servlet_第66张图片

7.5.4 练习题

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>支付页面title>
head>
<body>
<h1>支付页面h1>

<form action="/servlet/myPayServlet">
    用户编号:<input type="text" name="userId"/>
    支付金额:<input type="text" name="money"/>
    <input type="submit" value="点击支付">
form>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>支付成功title>
head>
<body>
<h1>恭喜你支付成功h1>
body>
html>
public class MyPayServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String userId = request.getParameter("userId");
        String money = request.getParameter("money");
        String contextPath = getServletContext().getContextPath();
        if (WebUtils.parseString(money) > 100) {
            response.sendRedirect(contextPath + "/pay_ok.html");
        } else {
            response.sendRedirect(contextPath + "/pay.html");
        }
    }
}
public class WebUtils {
    public static int parseString(String str) {
        int num = 0;
        try {
            //shortcuts: ctrl+alt+t
            num = Integer.parseInt(str);
        } catch (NumberFormatException e) {
            System.out.println("输入的str格式不正确");
        }
        return num;
    }
}
<servlet>
        <servlet-name>MyPayServletservlet-name>
        <servlet-class>com.zzw.servlet.response.MyPayServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>MyPayServletservlet-name>
        <url-pattern>/myPayServleturl-pattern>
    servlet-mapping>

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