各种对象介绍、重定向与转发、web项目创建与设置

目录

1 ServletContext对象

1.1 什么是ServletContext对象

1.2 ServletContext对象的作用及演示

 2 Response对象

2.1 Response对象概述

2.2 Response对象设置响应行

2.3 Response对象设置响应头

2.4 Response对象设置响应体

3 重定向

4 Request对象

4.1 Request对象概述

4.2 Request对象获取请求行

4.3 Request对象获取请求头

4.4 Request对象获取请求参数

4.5 Request对象接收表单请求参数时的中文乱码问题解决

5 Request域对象

6 请求转发

7 请求转发与重定向的区别

8 web项目的创建与设置


1 ServletContext对象

1.1 什么是ServletContext对象

 Tomcat服务器中的web的项目也叫做WEB应用程序。在java中,万物皆为对象,应用程序也是对象。在JavaWeb开发中,使用ServletContext对象表示WEB应用程序,如上图。关于web项目的区分见下图:

1.2 ServletContext对象的作用及演示

(1)获取WEB应用程序的初始化参数。
(2)获取WEB应用程序下任意资源的绝对路径。
(3)ServletContext作为域对象,存储数据。

以下代码就是对于上述三个功能的代码演示,实际上就是对于ServletContext实现类对象的方法的使用。

/**
 * ServletContext对象(Servlet上下文对象,它原本是个接口,该接口的实现又Tomcat引擎来完成,该实现类对象在Tomcat启动时就已经被创建好了,直接获取使用就好)
 * ServletContext对象的作用:web应用程序对象,用于描述整个web程序(每个程序只有这一个对象)(webapps目录下有几个文件夹就有几个web程序)
 * Tomcat在启动时,会扫描webapps这个目录下的所有web程序,并且会为每个程序创建一个ServletContext对象
 *
 *  String getInitParameter(String name) 获取web应用的初始化参数(这个参数指的是web.xml文件中的参数,传递键获得值)
 * 目前,获取初始化参数的意义已经不大了,那么在过去,可以通过配置文件拿到数据库的相关信息,但是现阶段都是用连接池技术来获取数据库连接对象
 *
 * String getRealPath(String path) 获取到web应用程序下任何资源的绝对路径,参数传的是相对路径,返回绝对路径
 *
 * ServletContext对象,也是域对象,它的作用域是整个web应用程序。
 *  void setAttribute(key, value) 将键值对存到域对象中
 *  Object getAttribute(key) 取出键值
 *  void removeAttribute(key) 移除键值对
 */

public class Context1Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取ServletContext对象
        ServletContext servletContext = getServletContext();
        //1、获取初始化参数
        String value = servletContext.getInitParameter("key");
        System.out.println(value);
        //2、获取a.txt文件的绝对路径(实际参数是个相对路径,这个相对路径是从每一个web程序文件夹的最外层开始的)
        String a_Path = servletContext.getRealPath("a.txt");
        System.out.println(a_Path);
        //3、ServletContext域对象相关的操作
        servletContext.setAttribute("key1","value1");
        //取出域对象中的数据(这个域对象作用于整个web项目,在Servlet1中定义的键值对,在Servlet2中也能看到)
        Object key1 = servletContext.getAttribute("key1");
        System.out.println(key1);
    }

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


//这个类,用来调用上面那个类中ServletContext对象存储的数据是否能从这个类中提取出来
public class Context2Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取ServletContext对象
        ServletContext servletContext = getServletContext();
        //取出域对象中的数据(这个域对象作用于整个web项目,在Servlet1中定义的键值对,在Servlet2中也能看到)
        Object key1 = servletContext.getAttribute("key1");
        System.out.println(key1);
    }

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

 2 Response对象

2.1 Response对象概述

Response 对象是负责向客户端响应数据的对象。
ServletResponse接口是Sun公司设计的,能适应任意的传输协议,而HttpServletResponse接口是该接口的子接口,该子接口由Tomcat实现和创建,我们直接去使用即可。
该对象可以实现对客户端的响应, 响应内容包括: 响应行,响应头,响应体。

响应行:协议名 状态码
响应头:键值对格式 数据k:v的形式
响应体:页面正文,浏览器显示

2.2 Response对象设置响应行

@WebServlet(urlPatterns = "/line")
public class LineServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求行中的状态码
        response.setStatus(200);
    }

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

 2.3 Response对象设置响应头

response对象,设置响应头
格式k:v
void addHeader(String key, int value) 设置响应头,传递键值对
void addDateHeader(String key, long value) 设置响应头,传递字符串的值(毫秒值)
void setHeader(String key, String value) 设置响应头,传递字符串键值对(前后这么多方法,会这一个就够了,它能自动把时间加进去)
void setIntHeader(String key, int value) 设置响应头,传递字符串键值对
void setDateHeader(String key, long value) 设置响应头,传递字符串的值(毫秒值),
区别:add 一个键可以设置多个值 但是set会覆盖

@WebServlet(urlPatterns = "/header")
public class HeaderServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置响应头
        /*response.addHeader("key1","value");
        response.addIntHeader("key2",123);
        response.addDateHeader("key3",System.currentTimeMillis());*/
        response.setHeader("key4","value4");
    }

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

  2.4 Response对象设置响应体

响应体:是浏览器展示的页面正文部分。
网络之间的数据传递通过IO,这里涉及到了响应体的应用:字符输出流。

(1)字符流向浏览器写数据

//response对象有个getWriter()方法,返回打印流对象PrintWriter,能够在网页上显示文本数据
@WebServlet(urlPatterns = "/body")
public class BodyServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();
        writer.println("hahahahahahahaha");//或者用writer.write 唯一区别就是如果打印数字的话,“.write”方法会把数字转义
    }

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

(2)字节流向浏览器写数据

字节输出流:全能,而不是像前面的字符流一样只能显示文本。
如下的代码是从本地读取一张图片(先要获取图片的全路径),然后转成字节输入流,再转为字节输出流向浏览器写数据。
getOutputStream()返回字节输出流。
另外,Response对象获取的字符流和字节流是互斥的。因为response对象有个缓冲区,数据会先到这个缓冲器,当Servlet结束后,
才会把缓冲区的数据写到浏览器,如果允许字节和字符流同时存在于缓冲区,是难以区分的,所以才只能允许出现一个。

@WebServlet(urlPatterns = "/body2")
public class Body2Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletOutputStream outputStream = response.getOutputStream();
        //字节流可以写数据:字节或者数组

        //获取图片2.jpg的绝对路径,先要获取到ServletContext对象
        ServletContext servletContext = getServletContext();
        String realPath = servletContext.getRealPath("WEB-INF/2.jpg");
        //字节输入流读取图片
        FileInputStream fileInputStream = new FileInputStream(realPath);
        byte[] bytes = new byte[1024];
        int len = 0;
        while((len = fileInputStream.read(bytes))!= -1){
            outputStream.write(bytes,0,len); //写图片
        }
        fileInputStream.close();
    }

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

(3)Response对象 中文乱码问题
Response对象提供方法 setContentType() 设置的是响应头:指导浏览器编码。

@WebServlet(urlPatterns = "/body4")
public class Body4Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*//修改response对象的编码表
        response.setCharacterEncoding("utf-8");
        //告诉浏览器,通过utf-8来解码
        response.getWriter().write("<meta charset=\"utf-8\">");
        //前面两步准备好后,此时浏览器上就不会出现乱码问题了*/

        //前面的方法虽然能解决中文乱码问题,但是挺麻烦的,接下来是简单的方法
        response.setContentType("text/html;charset=utf-8"); //表明响应体是一个文本类型的html文件,utf-8编码
        response.getWriter().write("你好");
    }

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

3 重定向

浏览器向web应用a发起请求,a处理不了,将重定向信息返回给浏览器(返回302以及重定向信息),浏览器再次访问web应用b,b响应浏览器请求。

/**
 * 浏览器重定向:response对象十分重要的应用
 * 浏览器向web应用a发起请求,a处理不了,将重定向信息返回给浏览器(返回302以及重定向信息),浏览器再次访问web应用b,b响应浏览器请求
 * 服务器Servlet接收客户端请求
 * 让客户端浏览器重新定向另一个Servlet:状态码302,设置响应头,告知浏览器要访问的下一个Servlet的地址(这就需要2行代码)
 * 把上面那两个方法合为一个方法:sentRedirect(地址)
 */
@WebServlet(urlPatterns = "/servlet1")
public class Servlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置状态码
        //response.setStatus(302);
        //设置响应头,告知浏览器要访问的下一个Servlet的地址(带上web应用程序的名字)
        //response.setHeader("location","/web02/servlet2");

        //将上面两个方法合并为一个用如下的方法:
        //response.sendRedirect("/web02/servlet2");
        response.sendRedirect("http://www.baidu.com");
    }

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

4 Request对象

4.1 Request对象概述

Request对象负责获取客户端的请求数据。
Request对象是从客户端向服务器发出请求,包括用户提交的信息以及客户端的一些信息。
客户端可通过HTML表单或在网页地址后面提供参数的方法提交数据,然后服务器通过request对象的相关方法来获取这些数据。

查看Servlet中的service方法得知, Servlet中使用的ServletRequest接口, 而我们使用的是ServletRequest的子接口HttpServletRequest, 它继承自ServletRequest, 是与HTTP协议相关的Request请求对象
我们使用的子接口HttpServletRequest, 此接口对象由Tomcat引擎提供
可以实现客户端向服务器发出请求, 请求内容包括: 请求行,请求头,请求体。

4.2 Request对象获取请求行

/**
 * request请求对象
 * 请求数据,都是由此对象获取
 * 接口ServletRequest 适用于任何网络协议,
 * 但网络协议基本都是http,所以有个子接口HttpServletRequest
 * 该对象由Tomcat创建,调用doGet方法时作为实际参数传递到doGet方法
 * <p>
 * 客户端的请求:
 * 请求行:请求方式、请求服务器的地址、请求协议版本
 * 请求头
 * 请求体
 * <p>
 * 客户端的请求行
 * 包含:请求方式、请求服务器的地址、请求协议版本
 * request对象方法:getMethod 获取客户端的请求方式GET、POST
 * 在地址栏中直接输入的地址,发起的请求都是GET,如果是a href="" 也是GET请求
 * 如果想看POST请求,必须要打开要用网页打开一个html且html里面有form标签(表单)且标签中的method属性设置为“post”
 *
 * 获取客户端请求服务器的地址:如下的三个方法都能获得地址,其中getContextPath是最常用的
 * StringBuffer getRequestURL() 全都有:协议、端口、web应用名称、Servlet路径
 * String getRequestURI()       只有:web应用名称、Servlet路径
 * String getContextPath()      只有:web应用名称
 *
 * 获取服务器请求客户端的数据(只适用于GET请求)获取的是服务器地址?后面的参数
 * getQueryString()
 */

@WebServlet(urlPatterns = "/requestLine")
public class RequestsServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String method = request.getMethod();
        System.out.println("客户端请求方式" + method);

        //获取客户端请求服务器的地址
        StringBuffer requestURL = request.getRequestURL();
        String requestURI = request.getRequestURI();
        String contextPath = request.getContextPath();
        System.out.println("requestURL:" + requestURL);
        System.out.println("requestURI:" + requestURI);
        System.out.println("contextPath:" + contextPath);

        //获取服务器请求客户端的数据(只适用于GET请求)获取的是服务器地址?后面的参数
        String queryString = request.getQueryString();
        System.out.println(queryString);
    }

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

4.3 Request对象获取请求头

请求头数据格式键值对, k:v
​请求头中包含指导性信息,用于指导服务器。

/**
 * request 对象获取客户端请求体
 * 数据是k:v的形式
 * request对象的方法:
 * getHeader()获取请求头信息
 * getHeaderNames() 获取所有请求头的键,返回值是向量枚举
 */
@WebServlet(urlPatterns = "/requestHeader")
public class RequestHeader extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求头
        String header = request.getHeader("User-Agent"); //User-Agent的值是浏览器版本、操作系统名称
        System.out.println(header);

        //获取所有请求头的键,返回值是向量枚举
        //集合Collection从JDK1.2开始,对应迭代器Iterator,而在此之前的版本Enumeration是迭代器的前身
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String s = headerNames.nextElement();
            System.out.println(s + "::" + request.getHeader(s));
        }
    }

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

上面代码所涉及到的html如下(html中form表单的action属性需要和这个Servlet绑定): 

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<form action="/web02/requestHeader" method="get">
    <input type="text" name ="user">
    <input type="password" name ="user">

    <input type="submit">
</form>
</body>
</html>

4.4 Request对象获取请求参数

/**
 * request获取表单参数,不分GET还是POST
 * getParameter("表单中name属性值"):获取表单参数value
 * getParameterValues("表单中name属性值"):获取表单参数,针对于“一个键对应多个值checkbox”的情况
 * getParameterMap():获取所有表单参数(键就是表单name属性值,值就是客户在页面中填写的值)
 */
@WebServlet(urlPatterns = "/params")
public class RequestParams extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //getParameter("表单中name属性值"):获取表单参数value,只能拿除了checkbox以外的单值
        String user = request.getParameter("user");
        System.out.println(user);

        //getParameterValues("表单中name属性值"):获取表单参数,针对于“一个键对应多个值checkbox”的情况
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println(Arrays.toString(hobbies));

        //getParameterMap():获取所有表单参数(键就是表单name属性值,值就是客户在页面中填写的值)
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (String s : parameterMap.keySet()) {
            System.out.println(s + "::" + Arrays.toString(parameterMap.get(s))); //从map中根据键s获取值,由于该值是一个数组,不能直接打印所以要toString
        }
    }

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

上面代码所涉及到的html如下(html中form表单的action属性需要和这个Servlet绑定): 

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


<!--
准备一个表单,用于request对象数据的获取
-->
<form action="/web02/params" method="post">
    用户名:<input type="text" name="user"><br>
    密码:<input type="password" name="password"><br>
    爱好:<input type="checkbox" name="hobby" value="hobby1">爱好1
          <input type="checkbox" name="hobby" value="hobby2">爱好2
          <input type="checkbox" name="hobby" value="hobby3">爱好3<br>
    城市选择:<select name="city">
                <option>beijing</option>
                <option>shenzhen</option>
              </select>
    <input type="submit" value="提交数据">
</form>
</body>
</html>

4.5 Request对象接收表单请求参数时的中文乱码问题解决

@WebServlet(urlPatterns = "/params2")
public class RequestParams2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /**
         * 处理客户端请求的中文乱码
         * html里面提交的编码是UTF-8的,然而request对象获取参数时使用ISO8859-1编码
         * 为了解决中文乱码问题,需要设置request对象使用的编码表
         */
        request.setCharacterEncoding("utf-8");
        String user = request.getParameter("user");
        System.out.println(user);
    }

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

5 Request域对象

Request对象其实就是从客户端浏览器向服务器发送的一次请求信息的封装,Request中所保存的数据有效期是“一次请求范围”。
一次请求范围:从客户端浏览器向服务器发送一次请求,服务器针对这次请求对浏览器作出响应。当服务器作出响应之后,请求对象就销毁了,保存在其中的数据就无效了
每次请求都会创建新的request对象, 当响应结束后立刻销毁request对象。

/**
 * request 对象
 * request 对象也是个域对象,和上午的ServletContext相同,都是域对象,都可以存储数据但是作用域不同:
 * ServletContext对象作用域最大,在整个web程序有效
 * request对象作用域相对较小,作用范围为:一次请求有效,再一次请求就无效了
 *
 *  void setAttribute(key, value) 将键值对存到域对象中
 *  Object getAttribute(key) 取出键值
 *  void removeAttribute(key) 移除键值对
 *
 *  request对象方法:getRequestDispatcher(转发后的路径) 返回接口RequestDispatcher()
 *  RequestDispatcher()是个转发器对象,在这个对象中有个方法为:forward()
 */
@WebServlet(urlPatterns = "/request1")
public class Request1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //作用范围为:同一个Servlet中有效,在另外一个Servlet中就无效了(所以在一个Servlet中访问由另一个Servlet所创建的键值对是访问不到的)
        //request 域对象中存储键值对
        request.setAttribute("java","lmy");

        //取值(同一个Servlet中有效)
        Object java = request.getAttribute("java");
        System.out.println(java);

        //(这是请求转发相关的内容和本节无关)进行转发,到request2中(本来客户端访问的是request1,然而到这里被转发到了request2)
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/request2");
        requestDispatcher.forward(request,response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
@WebServlet(urlPatterns = "/request2")
public class Request2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //直接从request域对象中取数据:是取不到的,因为作用域不够
        Object o = request.getAttribute("java");
        System.out.println("request2:" + o);
    }

6 请求转发

对于请求转发,客户端浏览器只发出一次请求,Servlet1把请求转发给Servlet2(HTML、JSP)或其它信息资源,由第2个信息资源响应该请求,两个信息资源共享同一个Request对象。

/**
 * request 对象
 * request 对象也是个域对象,和上午的ServletContext相同,都是域对象,都可以存储数据但是作用域不同:
 * ServletContext对象作用域最大,在整个web程序有效
 * request对象作用域相对较小,作用范围为:一次请求有效,再一次请求就无效了
 *
 *  void setAttribute(key, value) 将键值对存到域对象中
 *  Object getAttribute(key) 取出键值
 *  void removeAttribute(key) 移除键值对
 *
 *  request对象方法:getRequestDispatcher(转发后的路径) 返回接口RequestDispatcher()
 *  RequestDispatcher()是个转发器对象,在这个对象中有个方法为:forward()
 */
@WebServlet(urlPatterns = "/request1")
public class Request1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //作用范围为:同一个Servlet中有效,在另外一个Servlet中就无效了(所以在一个Servlet中访问由另一个Servlet所创建的键值对是访问不到的)
        //request 域对象中存储键值对
        request.setAttribute("java","lmy");

        //取值(同一个Servlet中有效)
        Object java = request.getAttribute("java");
        System.out.println(java);

        //进行转发,到request2中(本来客户端访问的是request1,然而到这里被转发到了request2)
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/request2");
        requestDispatcher.forward(request,response);
    }

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

 

/**
 * request对象方法:getRequestDispatcher(转发后的路径) 返回接口RequestDispatcher()
 * RequestDispatcher()是个转发器对象,这个对象中有个方法为:forward()
 */
@WebServlet(urlPatterns = "/request2")
public class Request2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //直接从request域对象中取数据:是取不到的,因为作用域不够
        //但如果是转发:在request1中设置request的键值对,转发到request2后还是能访问到的!而且,和重定向不同的是,浏览器最后的访问地址仍然是/request1而不是/request2(重定向才是这个)
        Object o = request.getAttribute("java");
        System.out.println("request2:" + o);

        //客户端请求被转发到request2,此时
        response.getWriter().write("i am request2");
    }

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

7 请求转发与重定向的区别

请求转发:1次请求1次响应                 重定向:2次请求2次响应。
请求转发:地址栏不变;                     重定向:地址栏变化。
请求转发:路径不带工程名;              重定向:需要带工程名路径。
请求转发:只能在本web服务器内部; 重定向:可以定向到任何网站。

问题抛出:我们最后发现,无论是重定向还是转发,最后都是由Servlet2来响应浏览器,那么重定向和转发的应用场景究竟为何呢?什么时候用重定向?什么时候用转发? 

8 web项目的创建与设置

(1)创建web项目

(2)设置 web路径

(3)设置web项目的文件结构(这个结构是Tomcat启动时会自动生成的文件结构)

(4)查看web项目的原始路径

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值