web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象和代表响应的response对象。request和response对象既然代表请求和响应,那我们获取客户机提交过来的数据,只需要找request对象即可,要向客户机输出数据,只需要找response对象即可。这一节我们来看看Servlet的这两个对象:HttpServletResponse对象和HttpServletRequest对象。

1. HttpServletRequest对象

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

1)获取客户机环境信息常用的方法如下:(具体见Demo1)

getRequestURL();   //返回客户端发出请求时的完整URL
getRequestURI(); //返回请求行中的资源名部分
getQueryString(); //返回请求行中的参数部分
getRemoteAddr(); //返回发出请求的客户机的IP地址
getRemoteHost(); //返回发出请求的客户机完整主机名
getRemotePort(); //返回客户机所使用的网络端口号
getLocalAddr(); //返回WEB服务器的IP地址
getLocalName(); //返回WEB服务器的主机名
getMethod(); //得到客户机请求方式

相应的示例代码Demo1如下:

//获取客户机环境信息常见的方法
public class RequestDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { //uri标识一个资源,url标识互联网上的一个资源,所以url是uri的子集
System.out.println(request.getRequestURL());//会打印出http://localhost:8080/test/servlet/RequestDemo1
System.out.println(request.getRequestURI());//会打印出/test/servlet/RequestDemo1 //请求http://localhost:8080/test/servlet/RequestDemo1?name=eson_15
System.out.println(request.getQueryString());//打印出name=eson_15 System.out.println(request.getRemoteAddr());//打印出来访地址:127.0.0.1
System.out.println(request.getRemoteHost());//打印来访主机:127.0.0.1
System.out.println(request.getRemotePort());//打印来访端口号:3969
System.out.println(request.getLocalAddr());//打印出服务器地址:127.0.0.1 System.out.println(request.getMethod());//打印访问方式:GET/POST
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doGet(request, response);
}
}

2)获取请求信息常用的方法--Map如下:(Demo2)

//获得客户机请求头
getHeader(String name);
getHeaders(String name); //获取指定名称的头的所有值
getHeaderNames(); //获取所有头的名称 //获得客户机请求参数(客户端提交的数据)
getParameter(name);
getParameterValues(String name); //获取指定参数名的所有值
getParameterNames(); //获取所有参数名
getParameterMap(); //获取封装数据的map集合,在框架中使用频繁

相应的示例代码Demo2如下:

public class RequestDemo2 extends HttpServlet {  

    public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
<pre name="code" class="java"> //获取压缩方式 gzip,deflate.实际中在输出数据之前可以用该方法先判断浏览器是否支持gzip方式
System.out.println(request.getHeader("Accept-Encoding")); //获取指定名称的头的所有值
Enumeration e = request.getHeaders("Accept-Encoding");
while(e.hasMoreElements()) {
String value = (String) e.nextElement();
System.out.println(value);
}
System.out.println("----------------------------");
//获取所有的头和值
e = request.getHeaderNames();
while(e.hasMoreElements()) {
String name = (String) e.nextElement();
String value = request.getHeader(name);
System.out.println(name + "=" + value);
}
System.out.println("----------------------------");
//http://localhost:8080/day06/servlet/RequestDemo2?name=eson_15
System.out.println(request.getParameter("name"));//eson_15 //http://localhost:8080/day06/servlet/RequestDemo2?like=sing&like=dance
String likes[] = request.getParameterValues("like");//获取指定参数名的所有值
//重要!获取数组数据的方式(可避免空指针异常)
for(int i = 0; likes != null && i < likes.length; i++) {
System.out.println(likes[i]);//sing dance
}
System.out.println("----------------------------");
//http://localhost:8080/day06/servlet/RequestDemo2?name=eson_15&like=swim&love=you
e = request.getParameterNames();//获取所有参数名
while(e.hasMoreElements()) {
String name = (String) e.nextElement();
String value = request.getParameter(name);
System.out.println(name + "=" + value);
}
System.out.println("----------------------------");
////http://localhost:8080/day06/servlet/RequestDemo2?name=eson_15&like=swim&love=you
Map<String, String[]> map = request.getParameterMap();
for(Map.Entry<String, String[]> me : map.entrySet()) {
String name = me.getKey();
String value[] = me.getValue();
System.out.println(name + "=" + value[0]);
}
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

3)实现请求转发:(Demo3/test.jsp/Demo4)

request对象实现请求转发:请求转发指一个web资源受到客户端请求后,通知服务器去调用另一个web资源进行处理。请求转发应用场景:MVC设计模式        request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forwoard方法可以实现请求转发。        request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其他web资源处理。相关方法如下:

setAttribute();    //设置属性
getAttribute(); //获得属性值
removeAttribute(); //删除某个属性
getAttributeNames(); //获得所有属性名
//以上所有方法中的参数我都省略了,括号里为空并不代表没有参数!!

相应的示例代码如下:

//Demo3:请求转发:MVC 重点
public class RequestDemo3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { String data = "abcd"; //开发中不能用ServletContext做容器,因为用户公用一个ServletContext,一个用户设置了数据后,另一个用户如果也设置了,将会覆盖第一个用户的值
// this.getServletContext().setAttribute("data", data); //request本身就是一个容器,我们可以用request来传递数据,不同的用户有不同的request,相互之间不会产生影响
request.setAttribute("data", data); //转发方法1,框架习惯用这种
// RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/test.jsp");
// rd.forward(request, response); //转发方法2, 开发习惯用这种。这两种方法没有区别
RequestDispatcher rd = request.getRequestDispatcher("/test.jsp");
rd.forward(request, response);
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doGet(request, response);
}
}

相应的test.jsp页面如下:

<html>
<head>
</head>
<body>
<%
//String data = (String) this.getServletContext().getAttribute("data");
String data = (String) request.getAttribute("data");
out.write(data);
%>
</body>
</html>

4)获取用户提交数据(Demo4/form.html)
        首先看一下前台页面form.html,主要是获得几个参数:

<!DOCTYPE html>
<html>
<head>
<title>form.html</title> <meta name="keywords" content="keyword1,keyword2,keyword3">
<meta name="description" content="this is my page">
<meta name="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body>
<form action="/test/servlet/RequestDemo4" method="get">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
性别:
<input type="radio" name="gender" value="male"/>男
<input type="radio" name="gender" value="female"/>女<br/> 城市:
<select name="city">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
</select><br/> 爱好:
<input type="checkbox" name="like" value="sing">唱歌
<input type="checkbox" name="like" value="dance">跳舞
<input type="checkbox" name="like" value="basketball">篮球
<input type="checkbox" name="like" value="football">足球
<br/> 简历:
<textarea rows="5" cols="60" name="resume">请输入简历</textarea>
<br/> 相片:
<input type="file" name="file"/><br/> <input type="hidden" name="name" value="xxx"><br/> <input type="submit" value="提交"/> </form>
</body>
</html>

当用户提交后,自动跳转到RequestDemo4这个Servlet来处理:

public class RequestDemo4 extends HttpServlet {  

    public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { request.setCharacterEncoding("UTF-8");//通过UTF-8获得浏览器中的数据 (post方式有效)
//关于GET方式,请见下面这个帖子,写的很详细,请认真阅读一下
//http://blog.csdn.net/xh16319/article/details/8456547 System.out.println(request.getParameter("username"));
System.out.println(request.getParameter("gender"));
System.out.println(request.getParameter("city")); String likes[] = request.getParameterValues("like");
for(int i = 0; likes != null && i < likes.length; i++){
System.out.println(likes[i]);
} System.out.println(request.getParameter("resume"));
System.out.println(request.getParameter("name"));
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doGet(request, response);
} }

request比较简单,在开发中主要是用来获取前台带来的数据,以及实现跳转等等。下面看看response对象。

2. HttpServletResponse对象

这个对象是指服务器的响应,这个对象中封装了想客户端发送数据,发送响应头,发送响应状态码的方法。如:

PrintWriter getWriter();  /得到字符流
ServletOutputStream getOutputStream(); //得到字节流
void setStatus(int sc); //设置要发送的状态码
void setHead(String name, String value); //响应头 等等

response常见应用有如下几个:

1)向客户端输出中文数据:分别以OutputStream和PrintWriter输出(Demo1)

public class ResponseDemo1 extends HttpServlet {  

    public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { // outputChineseByByte(response);
outputChineseByChar(response);
} private void outputChineseByChar(HttpServletResponse response)
throws IOException {
String data = "中国"; response.setHeader("content-type", "text/html;charset=UTF-8");//通知浏览器以UTF-8打开,注意里面是分号不是逗号
response.setCharacterEncoding("UTF-8");//通过response以UTF-8输出
/*
* 上面两个步骤可以用一个方法来等价
* response.setContentType("text/html;charset=UTF-8");
* 在这个方法里相当于做了以上两件事,开发中用该方法比较方便,但是不方便理解,视个人习惯而定
*/
PrintWriter out = response.getWriter();//一定要先将上面设置好才能输出
out.write(data);
} //以字节流方式输出
private void outputChineseByByte(HttpServletResponse response)
throws IOException, UnsupportedEncodingException {
//在服务器端,数据是以哪个码表输出的,那么就要控制浏览器用哪个码表打开
String data = "中国";
OutputStream out = response.getOutputStream(); response.setHeader("content-type", "text/html;charset=UTF-8");//告诉浏览器用utf-8编码打开
// 这种用html来模拟http响应头的方式也可以,即告诉浏览器以UTF-8的方式打开
// out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes()); out.write(data.getBytes("UTF-8"));//将“中国”这个字符通过字节输出,一定会查码表,浏览器在打开的时候若查的不是这个码表,则就会出错
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doGet(request, response);
} }

2)文件下载和中文文件下载(Demo2)

public class ResponseDemo2 extends HttpServlet {  

    public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { // downloadFile(response); downloadErrorDemo(response);
} //中文文件的下载,中文文件名要经过URL编码
private void downloadFile(HttpServletResponse response) throws FileNotFoundException, IOException {
String realPath = this.getServletContext().getRealPath("/狗狗.jpg"); //狗狗.jpg存放在WebRoot下
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1); //URLEncoding
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName)); FileInputStream in = new FileInputStream(realPath);
int len = 0;
byte buffer[] = new byte[1024];
OutputStream out = response.getOutputStream();
while((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
} in.close();
} //文件下载注意事项:字节流可以处理任意类型的数据,字符流只能处理字符数据,如果用字符流处理字节数据会导致数据丢失
private void downloadErrorDemo(HttpServletResponse response) throws FileNotFoundException, IOException {
String realPath = this.getServletContext().getRealPath("/狗狗.jpg");
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1); response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName)); FileReader in = new FileReader(realPath);
int len = 0;
char buffer[] = new char[1024];
PrintWriter out = response.getWriter();
while((len = in.read(buffer)) > 0){
out.write(buffer, 0, len);
}
/*
* 该程序下载下来的文件无法打开的原因:
* 因为任意文件都是通过二进制保存的,那么字符流在读取图片文件时,每次读取一个字符大小的二进制数,该二进制数在gb2312中可能并没有相对应的码,结果就用?代替。
* 然后写到浏览器的时候,浏览器拿到?并不能正确解析出原始的二进制数,就用0代替,这样就造成了数据的丢失。
* 所以字符流不能去读取字节数据,会导致数据的丢失
*
*/
in.close();
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doGet(request, response);
} }

3)输出随机图片(Demo3)

public class ResponseDemo3 extends HttpServlet {  

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  

        //6. 设置头,控制浏览器不要缓存图片数据
response.setHeader("cache-control", "no-cache"); //5. 通知浏览器以图片方式打开
response.setHeader("content-type","image/jpeg"); //1. 在内存中创建一幅图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB); //2. 得到图片
Graphics2D g = (Graphics2D)image.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, 80, 20);//用白色填充整个矩形背景 //3. 向图片上写数据
g.setColor(Color.RED);//设置图片背景
g.setFont(new Font(null,Font.BOLD,20));//设置文字
g.drawString(makeNum(), 0, 20);//写上随机数 //4. 将图片写给浏览器
ImageIO.write(image, "jpg", response.getOutputStream());
} private String makeNum() {
Random r = new Random();
String num = r.nextInt(9999999) + "";//0-9999999
StringBuffer sb = new StringBuffer();
for(int i = 0; i < 7-num.length(); i++){
sb.append("0");
}
return sb.toString() + num;
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doGet(request, response);
} }

4)发送http头以及请求重定向(这一块放在下一篇博客里解说)

3. web工程中url地址的写法

在程序中有写:

//web工程中url地址的写法
public class ResponseDemo4 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { /*只要是写地址,请统统以"/"开始,若"/"是给服务器用的则代表web工程,若"/"是给浏览器用的则代表webapps**/ //servletContext
this.getServletContext().getRealPath("/dog.jpg");//给服务器用的 //forward
this.getServletContext().getRequestDispatcher("/servlet/ResponseDemo3");//给服务器用的 //sendRedirect
response.sendRedirect("/test/servlet/ResponseDemo3");//给浏览器用的 //html <a href="/test/servlet/ResponseDemo3"></a> //给浏览器用的
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doGet(request, response);
} }

HttpServletRequest和HttpServletResponse就介绍这么多,如有错误之处,欢迎留言指正~

Servlet的API(二)的更多相关文章

  1. Struts2(二)— Result结果配置、Servlet的API的访问、模型驱动、属性驱动

    一.Result结果配置 1.全局和局部结果 ​ 平常我们设置跳转页面,是在action标签里面加上 result标签来控制,这种设置的页面跳转,称之为局部结果页面但是我们有时候在很多个action里 ...

  2. Servlet 常用API学习(二)

    Servlet常用API学习 一.HTTP简介 WEB浏览器与WEB服务器之间的一问一答的交互过程必须遵循一定的规则,这个规则就是HTTP协议. HTTP是 hypertext transfer pr ...

  3. 七 Struts2访问Servlet的API方式二:原生方式

    Struts2访问Servlet的API方式二:原生方式 和解耦合的方式不同,原生方式既可以拿到域对象,也可以调用域对象中的方法 前端jsp: <%@ page language="j ...

  4. springmvc使用pojo和servlet原生api作为参数

    一.Pojo作为参数: 实体: package com.hy.springmvc.entities; public class User { private String username; priv ...

  5. struts2:在Action中使用Servlet的API,设置、读取各种内置对象的属性

    有两种方式可以实现在Action中使用Servlet的API.一种是使用org.apache.struts2.ServletActionContext类,另一种是使用com.opensymphony. ...

  6. Struts2学习第2天--Struts2的Servlet的API的访问 Struts2的结果页面的配置 Struts2的数据的封装(包括复杂类型)

    启动后访问jsp 输入姓名密码: 提交后跳转打action 打印: 修改类: 配置同上 结果同上. 实现这俩接口 就得到了 以上代码附上: struts.xml: <?xml version=& ...

  7. struts2学习笔记(四)——访问Servlet的API&结果跳转&数据封装

    一.Struts2访问Servlet的API 前面已经对Struts2的流程执行完成了,但是如果表单中有参数如何进行接收?又或者我们需要向页面保存一些数据,又要如何完成呢?我们可以通过学习Struts ...

  8. (转)Struts2访问Servlet的API及......

    http://blog.csdn.net/yerenyuan_pku/article/details/67315598 Struts2访问Servlet的API 前面已经对Struts2的流程已经执行 ...

  9. Servlet 常用API学习(三)

    Servlet常用API学习 (三) 一.HTTPServletRequest简介 Servlet API 中定义的 ServletRequest 接口类用于封装请求消息. HttpServletRe ...

  10. Servlet 常用API学习(一)

    Servlet常用API学习 一.Servlet体系结构(图片来自百度图片) 二.ServletConfig接口 Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外 ...

随机推荐

  1. java基础练习 18

    import java.util.Scanner; public class Eightheen { /*判断一个素数能被几个9整除*/ public static void main(String[ ...

  2. 检查URL Protocol是否安装的项目

    https://github.com/ismailhabib/custom-protocol-detection

  3. vs2015 建立项目报错:值不能为空,参数名:path1的错误解决与“未将对象引用到对象的实例”

    “值不能为空,参数名:path1” 的错误.原因就是安卓sdk的路径不正确. 最简单的解决办法如下: 找到C:\Program Files (x86)\Android\android-sdk.进入文件 ...

  4. 找出数字数组中最大的元素(使用Math.max函数)

    从汤姆大叔的博客里看到了6个基础题目:本篇是第1题 - 找出数字数组中最大的元素(使用Match.max函数) 从要求上来看,不能将数组sort.不能遍历.只能使用Math.max,所以只能从java ...

  5. (3)WPF 布局

    一.布局原则 二.布局过程 三.布局容器 核心布局面板 布局属性

  6. Python的并发并行[1] -> 线程[2] -> 锁与信号量

    锁与信号量 目录 添加线程锁 锁的本质 互斥锁与可重入锁 死锁的产生 锁的上下文管理 信号量与有界信号量 1 添加线程锁 由于多线程对资源的抢占顺序不同,可能会产生冲突,通过添加线程锁来对共有资源进行 ...

  7. Python的网络编程[1] -> FTP 协议[1] -> 使用 pyftplib 建立 FTP 服务器

    使用 pyftplib 建立 FTP 服务器 pyftplib 主要用于建立 FTP Server,与 ftplib 建立的 Client 进行通信. 快速导航 1. 模块信息 2. 建立 FTP 服 ...

  8. POJ 2482 Stars in Your Window 离散化+扫描法 线段树应用

    遇见poj上最浪漫的题目..题目里图片以上几百词为一篇模板级英文情书.这情感和细腻的文笔深深地打动了我..不会写情书的童鞋速度进来学习.传送门 题意:坐标系内有n个星星,每个星星都有一个亮度c (1& ...

  9. hdu 1506 Largest Rectangle in a Histogram 构造

    题目链接:HDU - 1506 A histogram is a polygon composed of a sequence of rectangles aligned at a common ba ...

  10. pyttsx的中文语音识别问题及探究之路

    最近在学习pyttsx时,发现中文阅读一直都识别错误,从发音来看应该是字符编码问题,但搜索之后并未发现解决方案.自己一路摸索解决,虽说最终的原因非常可笑,大牛们可能也是一眼就能洞穿,但也值得记录一下. ...