tomcat(WEB服务器)

  • 启动tomcat一定要配置java的环境变量,且环境变量的名称只能是JAVA_HOME,不然启动时会闪一下,然后启动失败

  • 关闭tomcat要在使用bin目录下的shutdown.bat脚本,点击x关闭的是意外退出,不会有日志写入

    tomcat目录的说明

servlet(小服务程序)

  • UML类图

  • servlet的特点

    1. 他是由服务器端调用和执行的
    2. 他是用java语言编写的,本质就是Java类
    3. 他是按照Servlet规范开发的
    4. 功能强大,可以完成几乎所有的网站功能
  • servlet3.0前使用web.xml,servlet3.0版本以后(包括3.0)支持注解,同时支持web.xml配置

  • web.xml文件主要用来配置web应用使用到Servlet

  • servlet是单例的,常驻内存,只能有一个

Servlet快速入门

  • 开发servlet需要实现Servlet接口
  • 实现Servlet接口需要实现Servlet的五个抽象方法
    1. init()方法
      1. 初始化servlet
      2. 当创建HelloServlet实例列时,就会调用init方法
      3. 该方法只会被调用一次
    2. ServletConfig()方法
      1. 返回ServletConfig对象
      2. 也就是返回Servlet的配置
    3. service()方法
      1. service方法处理浏览器的清求(包括get/post)
      2. 当浏览器每次清求Servlet/时,就会调用一次service
      3. 当tomcat调用该方法时,会把http请求的数据封装成实现ServletRequest接口的request对象
      4. 通过servletRequest.对象,可以得到用户提交的数据
      5. servletResponse对象可以用于返回数据给刘览器tomcat->刘览器
    4. getServletlnfo()方法
      1. 返回servlet的信息
    5. destroy()
      1. 该方法是在servlet销毁时被凋用
      2. 只会调用一次
  • 当tomcat重新发布或重新加载时,会销毁HashMap集合中的Servlet对象,并调用destroy()方法,浏览器再次访问时还是会发生创建servlet
  • 浏览器的每次http请求,tomcat都会开启一个新的线程处理
  • 当web应用被终止,或者Servlet:容器终止运行,或者Servlet类重新装载时,会调用destroy()方法
  • 配置web.xml文件开发Servlet代码演示(实现接口Servlet的方式)
package com.hspedu.servlet;

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

/**
 * @Projectname: servlet
 * @Filename: HelloServlet
 * @Author: 杨逸
 * @Data:2023/4/2 20:00
 * @Description: TODO
 */

/**
 *1.开发servlet需要实现Servlet接口
 * 2.实现Servlet接口需要实现Servlet的五个抽象方法
 */
public class HelloServlet implements Servlet {

    /**
     * 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 {
        System.out.println("service");
        //tomcat每次处理http请求,都会开一个新的线程处理
        System.out.println("线程id=" + Thread.currentThread().getId());
    }

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

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

    }
}

web.xm配置文件的配置

  • web.xml主要用来配置web应用使用到Servlet
    1. :给Servlet取名,该名字唯一,不能重复
    2. :Servlet的类的全路径:Tomcat在反射生成Servlet需要使用到类的全路径
    3. :表示在tomcat启动时,会自动的加载servlet实例,标签的'1'表示自动加载的循序
    4. 中的内容一定要和中的一样
    5. :这个就是该servlet访问的UrL的配置(路径)
    6. 这时我们应该这样(http://localhost:8080/servlet/helloServlet)访问servlet
    7. 取名是程序员决定的
<?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">
    <!--web.xml主要用来配置web应用使用到Servlet-->
    
     <!--Filter过滤器的配置-->
    <filter>
        <filter-name>AuthFilter</filter-name>
        <filter-class>com.hsp.housefurnishings.filter.AuthFilter</filter-class>
        <init-param>
            <param-name>exclude</param-name>
            <param-value>/views/manage/manage_login.jsp,/views/member/login.jsp,</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>AuthFilter</filter-name>
        <!--
        1.在filter-mapping的url-pattern配置要拦截/验证url
        2.对于我们不去拦截url,就不配置
        3.对于要拦截的目录的某些要放行的资源,在通过init-param配置指定
        -->
        <url-pattern>/views/cart/*</url-pattern>
        <url-pattern>/views/manage/*</url-pattern>
        <url-pattern>/views/member/*</url-pattern>
        <url-pattern>/views/order/*</url-pattern>
        <url-pattern>/cartServlet</url-pattern>
        <url-pattern>/manage/furnServlet</url-pattern>
        <url-pattern>/orderServlet</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>TransactionFilter</filter-name>
        <filter-class>com.hsp.housefurnishings.filter.TransactionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>TransactionFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!--    配置HelloServlet-->
    <servlet>
        <!--
        1.servlet-name:给Servlet取名,该名字唯一,不能重复
        2.servlet-class:Servlet的类的全路径:Tomcat在反射生成Servlet需要使用到类的全路径
	    3.load-on-startup:表示在tomcat启动时,会自动的加载servlet实例,标签的'1'表示自动加载的循序
        -->
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.hspedu.servlet.HelloServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <!--
        3.<servlet-mapping>中的<servlet-name>内容一定要和<servlet>中的<servlet-name>一样
        4.url-pattern:这个就是该servlet访问的UrL的配置(路径)
        5.这时我们应该这样访问servlet, http://localhost:8080/servlet/helloServlet
        6.url-pattern取名是程序员决定的
        -->
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/helloServlet</url-pattern>
    </servlet-mapping>
    
    <!--错误页面的配置-->
    <error-page>
        <error-code>404</error-code>
        <location>/views/error/404.jsp</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/views/error/500.jsp</location>
    </error-page>
</web-app>

浏览器请求Servlet的流程

  • 如果是第一次请求(tomcat)

    1. 查询web.xml

    2. 看看请求的资源/helloServlet,在web.xml配置中的url-pattern

    3. 如果找到url-pattern,就会得到(servlet-name) HelloServlet

    4. Tomcat维护了一个大的HashMap<id,Servlet>,查询该HashMap看看有没有这个Servlet实例

    5. 如果没有查询到该serletname对应的id,即没有这个Servlet实例

    6. 就根据servlet.name去得到servlet-classs(类的全路径)

    7. 使用反射技术,将servlet实例化(调用init()方法),并放入到Tomcat维护的HashMap<id,Servlet>

  • 如果不是第一次请求(tomcat)

    1. 查询web.xml
    2. 看看请求的资源/helloServlet,在web.xml配置中的url-pattern
    3. 如果找到url-pattern,就会得到(servlet-name) HelloServlet
    4. Tomcat维护了一个大的HashMap<id,Servlet>,查询该HashMap看看有没有这个Servlet实例
    5. 如果找到了该实例servlet,就调用servlet的service()方法
  • 总的流程就是,查询web.xml文件,得到url-pattern,HashMap集合存在对应的实例就调用,没有就创建并加入到HashMap集合

  • 使用注解开发Servlet代码演示(继承HttpServlet的方式)

package com.hspedu.servlet.annotation;

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;

/**
 * @Projectname: servlet
 * @Filename: OkServlet
 * @Author: 杨逸
 * @Data:2023/4/3 14:38
 * @Description: TODO
 */

/**
 * 1.使用注解的方式配置Servlet,使用注解后就不需要配置web.xml文件
 * 2.urlPatterns对应web.xml文件的<url-pattern></url-pattern>
 * 3.{"/ok1","/ok2"}表示对应多个访问该Servlet的url
 * 4.
 */
@WebServlet (urlPatterns = {"/ok1","/ok2"})
public class OkServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("注解 的 get");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("注解的 post");
    }
}
  • 重写init()方法时,如果在其他地方需要使用config对象,就需要在重写的init()方法中调用super.init()方法,将配置信息传递到父类中

  • 使用注解配置urlPattern的四种方式

  • 使用注解可以同时匹配多个url

    1. 精确匹配

      @WebServlet (urlPatterns = {"/ok1","/ok2"})

    2. 目录匹配(就是在ok1目录下的任意匹配)

      @WebServlet (urlPatterns = {"/ok1/*"})

    3. 扩展名(后缀)匹配(不能带斜杠"/")

      @WebServlet (urlPatterns = {"*.java","*.html"})

    4. 任意匹配(使用"/"或"/*")

      @WebServlet (urlPatterns = {"/"})

  • 使用注解设置urlPattern为任意匹配时,会覆盖默认的DefaultServlet,该Servlet是用于管理静态资源的,一旦设置任意匹配就会拦截对静态资源的访问,使的静态资源不能被访问

  • 尽量使用精准匹配

ServletConfig

  • 用于获得Servlet程序的servlet-name的值
  • 用于获得Servlet程序的init-param初始化参数的值
  • 用于获得Servlet程序的ServletContent对象
package com.hspedu.servletConfig;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Projectname: servlet
 * @Filename: DBServlet
 * @Author: 杨逸
 * @Data:2023/4/5 9:52
 * @Description: TODO
 */
public class DBServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        //一系列操作后,调用super.init()方法,将配置信息传递到父类的config对象中
        //如果后续相使用config对象,进行操作,就一定要调用super.init()方法
        super.init();
    }
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通过ServletConfig对象获得web.xml配置的信息
        //获得config对象
        ServletConfig servletConfig = getServletConfig();
        //获得web.xml配置的init-param中的值
        String username = servletConfig.getInitParameter("username");
        String pwd = servletConfig.getInitParameter("pwd");
        System.out.println("用户名" + username);
        System.out.println("密码" + pwd);
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

ServletContext

  • ServletContext是一个接口,它表示Servlet上下文对象
  • 一个web工程,只有一个ServletContext对象实例,可以通过ServletContent对象统计每个Servlet被访问的次数
  • ServletContext对象是在web程启动的时候创建,在web工程停止的时销毁
  • ServletContext对象可以通过ServletConfig.getServletContext方法获得对ServletContext对象的引用,也可以通过this.getServletContext()来获得其对象的引用。
  • 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现多个Servlet间通讯。ServletContext对象通常也被称之为域对象.
  • ServletContext的作用
    1. 获取web.xml中配置的上下文参数context-param[信息和整个web应用相关,而不是属于某个Servlet]
    2. 获取当前的工程路径,格式:/工程路径=》比如/servlet
    3. 获取工程部署后在服务器硬盘上的绝对路径
    4. ServletContext属性像Map一样存取数据,多个Servlet共享数据
  • 使用SrevletContext统计网站访问次数的演示
    • 创建了两个Servlet
    • 创建一个WebUilts工具类,使用工具类进行次数统计
    • 先获得ServletContext对象,然后获得统计次数的属性
    • 第一次需要先判断统计次数属性是否为空,再进行次数的增加
    • 最后响应到页面上
public class OrderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获得ServletContext对象
        ServletContext servletContext = getServletContext();
        //将ServletContext对象传进去,对统计属性进行加一操作
        Integer visit_count = WebUilts.webCount(servletContext);

        //设置响应输出流的类型和编码
        resp.setContentType("text/html;charset=utf-8");
        //获得输出流
        PrintWriter writer = resp.getWriter();
        //写出内容
        writer.print("网站被访问了"+visit_count+"次");

        //刷新关闭
        writer.flush();
        writer.close();

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
//工具类
public class WebUilts {
    public static Integer webCount(ServletContext servletContext){
        //获得统计网站被访问的次数的属性
        Object visit_count = servletContext.getAttribute("visit_count");
        //判断是否为空
        if (visit_count == null){//如果为空就创建该属性
            servletContext.setAttribute("visit_count",1);
            visit_count = 1;
        }else {
            //次数加一,然后将属性重新设置
            visit_count = Integer.parseInt(visit_count + "") + 1;
            servletContext.setAttribute("visit_count",visit_count+"");
        }
        return Integer.parseInt(visit_count + "");
    }
}

HttpServletRequest(http请求头类)

  • 常用方法
    1. getRequestURI()获取请求的资源路径
    2. getRequestURL()获取请求的统一资源定位符(绝对路径)
    3. getRemoteHost()获取客户端的主机,getRemoteAddr()
    4. getHeader()获取请求头
    5. getParameter()获取请求的参数
    6. getParameterValues()获取请求的参数(多个值的时候使用),比如checkbox,返回的数组
    7. getMethod()获取请求的方式GET或PoST
    8. setAttribute(key,value);设置域数据
    9. getAttribute(key)i获取域数据
    10. getRequestDispatcher()获取请求转发对象,请求转发的核心对
  • 在读取http或响应http时,要先设置编码格式,如果存在中文会出现乱码现象
  • 演示获得http请求头的数据的和提交的数据
public class RegisterServletRequest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获得http请求的数据

        //获得请求的资源路径URI
        String requestURI = req.getRequestURI();
        System.out.println("请求资源的URI=" + requestURI);

        //获得请求的统计资源定位符URl
        StringBuffer requestURL = req.getRequestURL();
        System.out.println("URL=" + requestURL);

        //获得请求客户端的ip地址
        String remoteAddr = req.getRemoteAddr();
        System.out.println("客户端的ip地址=" + remoteAddr);

        //获得http请求头的host
        String remoteHost = req.getRemoteHost();
        System.out.println("http请求头的host=" + remoteHost);

        //获得http的请求方式
        String method = req.getMethod();
        System.out.println("http的请求方式" + method);

        //获得其他的http请求头字段可以使用getHeader()方法
        String date = req.getHeader("Referer");
        System.out.println("发起请求的页面" + date);

        //获得客户端浏览器的类型
        String header = req.getHeader("User-Agent");
        String[] s1 = header.split(" ");
        System.out.println("客户端使用的浏览器=" + s1[s1.length - 2].split("/")[0]);

        //读取数据和写入数据时,一定要先设置编码格式,不然会出现乱码现象
        req.setCharacterEncoding("utf-8");
        //获得提交的数据,使用getParameter()方法,
        //提交如果是复选框的数据使用getParameterValues()方法
        String username = req.getParameter("username");
        System.out.println("提交的用户名" + username);
        String[] hobbies = req.getParameterValues("hobby");
        for (String s :hobbies) {
            System.out.println("表单提交的爱好=" + s);
        }
    }

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

请求转发

  • 一般用于对响应处理的分步处理(问题分解,解耦)
  • req.getRequestDispatcher("/manage"),获得转发器并设置转发的目标Servlet
  • requestDispatcher.forward(req,resp),正式转发,并把请求的实例和响应的实例作为参数传进去
  • 请求转发的细节
    1. 浏览器的地址栏不会变化
    2. 在同一次HTTP请求中,进行多次转发,仍然是一次HTTP请求
    3. 在同一次HTTP请求中,进行多次转发,多个Servlet可以共享request.域/对象的数据,即reqeust.域/对象的数据(参数,属性)的作用域,是在一次HTTP请求有效
    4. 可以转发到WEB-INF目录下(一般情况下半年访问到WEB-INF目录)
    5. 不能访问当前WEB工程外的资源(只能在服务区的内部进行转发)
    6. 因为浏览器地址栏会停止在第一个servlet,如果你刷新页面,会再次发出请求(并且会带数据),所以支付页面情况下,不要使用请求转发,否则会造成重复支付(可以使用重定向)
  • 请求转发的演示
//转发请求的Servlet
public class CheckServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获得http请求的信息
        //获得提交的用户名
        String username = req.getParameter("username");
        //根据用户名,在设置ServletContext设置用户的权限
        if ("tom".equals(username)){
            getServletContext().setAttribute("role","管理员");
        }else {
            getServletContext().setAttribute("role","普通用户");
        }

        //开始请求转发
        //转发到用户管理的Servlet,响应具体的请求

        //获得转发器
        //getRequestDispatcher("/manage"),获得转发器的方法,参数是转发的目的Servlet地址
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/manage");
        //把HttpServletRequest和HttpServletResponse放到转发器中开始转发
        //使用forward()方法正式转发
        requestDispatcher.forward(req,resp);
    }

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

//请求转发的接受Servlet
public class ManageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //这里根据转发的请求进行具体的响应

        //获得servletContext
        ServletContext servletContext = getServletContext();
        //获得用户的身份信息
        String role = (String) servletContext.getAttribute("role");
        //获得提交的用户名
        String username = req.getParameter("username");
        //设置响应的类型和编码
        resp.setContentType("text/html;charset=utf-8");
        //获得输出流
        PrintWriter writer = resp.getWriter();
        writer.print("<h1>用户"+username+"的身份是"+role+"</h1>");

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

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

  • HttpServletRequest的作业

  • 将表单提交的数据,返回显示

  • 注意读取数据和写入数据前都要设置编码格式

    <!--表单-->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>注册表单</title>
    </head>
    <body>
    <form action="http://localhost:8080/servlet/register_homework" method="post">
    <p>用户注册信息</p>
        用户名称:<input type="text" name="username" value="默认testuser"><br>
        用户密码:<input type="password" name="pwd1"><br>
        确认密码:<input type="password" name="pwd2"><br>
        <p>请选择你喜欢的运动项目</p>
        <span>篮球</span><input type="checkbox" name="sport" value="篮球" checked>&nbsp;<span>足球</span><input type="checkbox" name="sport" value="足球">&nbsp;<span>羽毛球</span><input type="checkbox" name="sport" value="羽毛球"><br>
        选择你的性别:男<input type="radio" name="sex" value="男" checked>女<input type="radio" name="sex" value="女"><br>
        选择你喜欢的城市:
        <select name="city">
            <option>选择你喜欢的城市</option>
            <option value="深圳">深圳</option>
            <option value="北京">北京</option>
            <option value="广州">广州</option>
        </select><br>
        自我介绍:<br>
        <input type="textarea" name="自我介绍" ><br>
        选择你喜欢的文件<input type="file" name="文件"><br>
        <input type="submit" value="提交">  <input type="reset" value="重置表单">
    </form>
    
    </body>
    </html>
    
    //处理表单的HttpServlet
    package com.hspedu.request;
    
    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.io.PrintWriter;
    
    /**
     * @Projectname: servlet
     * @Filename: ServletRequestHomework
     * @Author: 杨逸
     * @Data:2023/4/5 18:16
     * @Description: TODO
     */
    public class ServletRequestHomework extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //设置编码格式
            req.setCharacterEncoding("utf-8");
            //获得用户名
            String username = req.getParameter("username");
            //获得密码
            String pwd1 = req.getParameter("pwd1");
            String pwd2 = req.getParameter("pwd2");
            //获得喜欢的运动
            String[] sports = req.getParameterValues("sport");
            //获得性别
            String sex = req.getParameter("sex");
            //获得喜欢的城市
            String city = req.getParameter("city");
            //获得自我介绍
            String introduce = req.getParameter("自我介绍");
    
            //拼接要响应的字符串
            String sport = "";
            for (String s : sports) {
                sport += s + ",";
            }
    
            String s = "用户名是" + username + "\n第一次密码是" + pwd1 + "\n第二次密码是"
                    + pwd2 + "\n用户的性别是" + sex + "喜欢的运动是" + sport + "\n喜欢的城市是" +
                    city + "\n自我介绍是" + introduce ;
            //设置编码
            resp.setContentType("text/plain;charset=utf-8");
            //获得输出流
            PrintWriter writer = resp.getWriter();
            writer.print(s);
    
            writer.flush();
            writer.close();
    
    
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req,resp);
        }
    }
    
    

HttpServletResponse

  • 响应http请求时,中文出现乱码问题的两种解决方法

    1. 设置服务端的编码,再给响应头指定类型和编码

      //给服务端设置编码格式
      resp.setCharacterEncoding("utf-8");
      //设置响应头的资源类型和编码
      resp.setHeader("ContextType","text/html;utf-8");
      
    2. 给输出流设置类型和编码

      //设置编码
      resp.setContentType("text/plain;charset=utf-8");
      //获得输出流
      PrintWriter writer = resp.getWriter();
      
  • 重定向的两种方式

    1. 直接重定向

      //参数是重定向的资源位置(URI),是web项目的资源的具体路径
      resp.sendRedirect("servlet/newServet");
      
    2. 先设置状态码,然后设置响应头

      resp.setStatus(302);
      resp.setHeader("Location","/servlet/newServlet");
      
  • 重定向的细节

    1. 最佳应用场景:网站迁移,比如原域名是WWw.hsp.com迁移到www.hsp.cn,但是百度抓取的还是原来网址.
    2. 浏览器地址栏会发生变化,本质是两次http请求
    3. 重定向后由浏览器解析
    4. 不能共享Request域中的数据,本质是两次http请求,会生成两个HttpServletRequest对象
    5. 不能重定向到/WEB-INF下的资源(转发可以访问到/WEB-INF下的资源)
    6. 可以重定向到Web工程以外的资源,比如到www.baidu.com
    7. 重定向有两种方式,推荐使用第1种.
    8. 使用getServletContext().getContextPath()方法可以动态获得WEB项目的路径(/servlet)