response和request是什么?在开发中,他们又扮演着什么样的角色呢?
web服务器收到客户端的HTTP请求,会针对每一次请求分别创建一个用于代表请求的request对象和代表响应的response对象。
Request和Response对象起到了服务器与客户机之间的信息传递作用。Request对象用于接收客户端浏览器提交的数据,而 Response对象的功能则是将服务器端的数据发送到客户端浏览器。
Response对象
HttpServletResponse对象代表客户端的响应,其中封装了向客户端发送数据、发送响应头、发送状态等信息。
几个常见的应用实例:
1.如何在Servlet中用OutputStream和Writer输出中文和数字?
package com.Cecilia.responseTest;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 需求:在Servlet中用OutputStream输出中文
* @author 芷若初荨
* @Date 2017.5.4
*/
public class responseTest extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
test1(resp);
test2(resp);
test3(resp);
test4(resp);
}
private void test1(HttpServletResponse resp)
throws IOException, UnsupportedEncodingException {
resp.setHeader(
"Content-type",
"text/html;charset=UTF-8");
String data=
"芷若初荨";
OutputStream out=resp.getOutputStream();
out.write(data.getBytes(
"UTF-8"));
}
private void test2(HttpServletResponse resp)
throws IOException, UnsupportedEncodingException {
resp.setHeader(
"Content-type",
"text/html;charset=UTF-8");
String data=
"芷若初荨";
OutputStream out=resp.getOutputStream();
out.write(
"<meta http-equiv='content-type' content='text.html;charet=UTF-8'>".getBytes());
out.write(data.getBytes(
"UTF-8"));
}
private void test3(HttpServletResponse resp)
throws IOException, UnsupportedEncodingException {
resp.setHeader(
"Content-type",
"text/html;charset=UTF-8");
String data=
"芷若初荨";
OutputStream out=resp.getOutputStream();
out.write(data.getBytes(
"UTF-8"));
}
private void test4(HttpServletResponse resp)
throws IOException, UnsupportedEncodingException {
OutputStream out=resp.getOutputStream();
out.write((
1+
"").getBytes(
"UTF-8"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
/**
* 需求:response的writer流输出的数据的问题
* @author 芷若初荨
*
*/
public class WriterTest extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
test1(resp);
}
private void test1(HttpServletResponse resp)
throws IOException {
resp.setContentType(
"text/html;charset=UTF-8");
resp.setCharacterEncoding(
"UTF-8");
String data=
"芷若初荨";
PrintWriter pw=resp.getWriter();
pw.write(data);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
2.如何实现文件下载?
/**
* 需求:实现文件下载
* @author 芷若初荨
*
*/
public class DownloadTest extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String path=
this.getServletContext().getRealPath(
"/source/66.jpg");
String filename=path.substring(path.lastIndexOf(
"\\")+
1);
resp.setHeader(
"content-disposition",
"attachment;filename="+URLEncoder.encode(filename,
"UTF-8"));
InputStream in=
null;
OutputStream out=
null;
try{
in=
new FileInputStream(path);
int len=
0;
byte buffer[]=
new byte[
1024];
out=resp.getOutputStream();
while((len=in.read(buffer))>
0){
out.write(buffer,
0,len);
}
}
finally{
if(in!=
null){
try{
in.close();
}
catch(Exception e){
e.printStackTrace();
}
}
if(out!=
null){
try{
out.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
3.如何控制浏览器定时刷新?(refresh)
/**
* 应用:控制浏览器定时刷新
* @author 芷若初荨
*
*/
public class SetReflur extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
test2(resp);
}
private void test2(HttpServletResponse resp)
throws IOException {
String message=
"<meta http-equiv='refresh' content='3;url=/responseTest/index.jsp'>恭喜你,登陆成功,本页面将在3s后跳回首页,如果没有跳,请<a href=''>点击</a>";
resp.setCharacterEncoding(
"UTF-8");
resp.setContentType(
"text/html;charset=UTF-8");
this.getServletContext().getRequestDispatcher(
"/responseTest/index.jsp");
this.getServletContext().setAttribute(
"message",message);
}
private void test1(HttpServletResponse resp)
throws IOException {
resp.setHeader(
"refresh",
"3");
String data=
new Random().nextInt(
10000)+
"";
resp.getWriter().write(data);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
4.如何实现浏览器缓存当前数据?(expries)
/**
* 需求:控制浏览器缓存当前文件内容
* @author 芷若初荨
*
*/
public class ControlCacheTest extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setDateHeader(
"expries", System.currentTimeMillis()+
1000*
3600);
String data=
"Cecilia";
resp.getWriter().write(data);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
5.如何实现输出随机图片(一般场景用在登录界面页面,防止恶意注册)?
/**
* 需求:输出随机图片(一般场景用在登录界面页面,防止恶意注册)
* BufferImage
* @author 芷若初荨
*
*/
public class RandomPic extends HttpServlet{
public static final int WIDTH=
120;
public static final int HEIGHT=
50;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
BufferedImage img=
new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
Graphics g=img.getGraphics();
setBackground(g);
setBorder(g);
drawRandomLine(g);
drawRandomNum((Graphics2D)g);
resp.setContentType(
"image/ipeg");
ImageIO.write(img,
"jpg", resp.getOutputStream());
resp.setDateHeader(
"expires", -
1);
resp.setHeader(
"Cache-Control",
"no-cache");
resp.setHeader(
"Pragma",
"no-cache");
}
private void drawRandomNum(Graphics2D g) {
g.setColor(Color.red);
g.setFont(
new Font(
"宋体",Font.BOLD,
20));
String base=
"\u7684\u4e00\u4e86\u6765\u4ed6\u6211\u662f";
for(
int i=
0;i<
4;i++){
int x=
5;
int degree=
new Random().nextInt()%
30;
String ch=base.charAt(
new Random().nextInt(base.length()))+
"";
g.rotate(degree*Math.PI/
180,x,
20);
g.drawString(ch, x,
20);
x+=
30;
}
}
private void drawRandomLine(Graphics g) {
g.setColor(Color.GREEN);
for(
int i=
0;i<
6;i++){
int x1=
new Random().nextInt(WIDTH);
int y1=
new Random().nextInt(HEIGHT);
int x2=
new Random().nextInt(WIDTH);
int y2=
new Random().nextInt(HEIGHT);
g.drawLine(x1, y1, x2, y2);
}
}
private void setBorder(Graphics g) {
g.setColor(Color.blue);
g.fillRect(
1,
1, WIDTH-
2, HEIGHT-
2);
}
private void setBackground(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(
0,
0, WIDTH, HEIGHT);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
6.如何使用response重定向?(sendRedirect)
/**
* 需求:实现请求重定向(一般用在登录页面)
**状态码:302
* location
*||resp.sendRedirect("/ResponseWebTest/index.jsp")
* @author 芷若初荨
*重定向的特点:
*1.浏览器会向服务器发送两次,意味着有两个Servlet;
*2.用重定向技术,浏览器地址栏会发生变化。
*/
public class RedirectTest extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.sendRedirect(
"/ResponseWebTest/index.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
小结response使用的一些细节
1.在转发或者做开发的过程中,不要同时调用OutPutStream和getWriter,否则会出现500错误;但是在重定向时,则不会出现这样的问题,因为重定向时创建了两个servlet;
2.HttpServletRequest对象代表客户端的请求,当客户端通过Http协议访问服务器时,Http请求头中的所有信息都封装在这个对象中,可以通过这个对象获取客户的相关信息。
Request对象
HttpServletRequest对象代表客户端的请求,当客户端通过Http协议访问服务器时,Http请求头中的所有信息都封装在这个对象中,可以通过这个对象获取客户的相关信息。
几个常见的应用实例:
1.HttpServletRequest中一些常用的方法
(PS:其中提供5种获取数据的方法)
public class RequestMethodTest extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.
out.println(req.getRequestURI());
System.
out.println(req.getRequestURL());
System.
out.println(req.getQueryString());
System.
out.println(req.getRemoteAddr());
System.
out.println(req.getRemoteAddr());
System.
out.println(req.getRemotePort());
System.
out.println(req.getMethod());
getHeadData(req);
try {
getDataMethods(req);
}
catch (Exception e) {
e.printStackTrace();
}
}
private void getDataMethods(HttpServletRequest req) throws Exception {
String
value=req.getParameter(
"uername");
if(
value!=
null&&!
value.trim().equals(
"")){
System.
out.println(
value);
}
Enumeration e=req.getParameterNames();
while(e.hasMoreElements()){
String name=(String) e.nextElement();
String value1=req.getParameter(name);
System.
out.println(name+
"="+value1);
}
String[] values=req.getParameterValues(
"username");
for(String username:values){
System.
out.println(username);
}
Map<String,String[]> map=req.getParameterMap();
User user=
new User();
System.
out.println(user);
InputStream
in=req.getInputStream();
int len=
0;
byte buffer[]=
new byte[
1024];
while((len=
in.read(buffer))>
0){
System.
out.println(len);
System.
out.println(
new String(buffer,
0,len));
}
}
private void getHeadData(HttpServletRequest req) {
String headValue=req.getHeader(
"Accept-Encoding");
System.
out.println(headValue);
Enumeration e=req.getHeaders(
"Accept-Encoding");
while(e.hasMoreElements()){
String
value=(String) e.nextElement();
System.
out.println(
value);
}
e=req.getHeaderNames();
while(e.hasMoreElements()){
String name=(String) e.nextElement();
String
value=req.getHeader(name);
System.
out.println(name+
"="+
value);
; }
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2.如何解决request中文乱码问题?(提供2种方法)
/**
* 需求:解决request中文乱码问题
* @author 芷若初荨
*
*/
public class MessyCodeTest extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
messyCodeMethodTest(req);
messyCodeMethodTest1(req);
}
private void messyCodeMethodTest1(HttpServletRequest req)
throws UnsupportedEncodingException {
String username=req.getParameter(
"username");
username=
new String(username.getBytes(
"iso8859-1"),
"UTF-8");
System.out.println(username);
}
private void messyCodeMethodTest(HttpServletRequest req)
throws UnsupportedEncodingException {
req.setCharacterEncoding(
"UTF-8");
String username=req.getParameter(
"username");
System.out.println(username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
3.如何通过表单收集客户机的数据? (对于数据的处理,一定要先检查再使用)
/**
* 需求:通过表单收集客户机的数据
* 准备:需要写一个form表单,上面带有用户名,密码,性别,所在地等信息数据
* !!注意:在获取数据时必须要检查数据是否为空,以防因客户机未填写数据而导致空指针问题,提高代码的健壮性。
* @author 芷若初荨
*
*/
public class CollectClientData extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String username=req.getParameter(
"username");
String password=req.getParameter(
"password");
String gender=req.getParameter(
"gender");
String city=req.getParameter(
"city");
String hobbies[]=req.getParameterValues(
"hobbies");
for(
int i=
0;i<hobbies.length;i++){
if(hobbies[i]!=
null&&hobbies[i].trim().equals(
"")){
}
System.out.println(hobbies[i]);
}
if(username!=
null&&!username.trim().equals(
"")){
System.out.println(username);
}
if(password!=
null&&!password.trim().equals(
"")){
System.out.println(password);
}
if(gender!=
null&&!gender.trim().equals(
"")){
System.out.println(gender);
}
if(city!=
null&&!city.trim().equals(
"")){
System.out.println(city);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
4.如何实现防盗链?(使用request)
首先说下,何为防盗链?防盗链是指一个内容不在自己服务器上,而通过技术手段,绕过别人放广告有利益的最终页,直接在自己的有广告有利益的页面上向最终用户提供此内容的现象。(常常是一些名不见经传的小网站来盗取一些有实力的大网站的地址(比如一些音乐、图片、软件的下载地址)然后放置在自己的网站中,通过这种方法盗取大网站的空间和流量)。
有时候我们从一个网站,比如腾讯,转载了一篇文章到自己的博客或空间,发现一些图片显示不了,这就是防盗链在起作用。图片是放在腾讯的服务器上的,腾讯拒绝其它网站的页面访问该资源。
一般情况下,当我们浏览一个网页时,并不是一次请求就会把整个页面的内容传到本地浏览器,尤其是当这个页面带有图片或者其它资源。第一次请求会传回该页面的HTML文本,浏览器解析该文本发现还有图片,会发送第二次请求,请求获得图片。盗链问题在于如果一个网站没有页面中所说的资源,它就会把这个图片链接到别的网站,这样没有任何资源的网站利用了别的网站的资源来展示给浏览者,提高了自己的访问量,而大部分浏览者又不会很容易地发现,这样显然,对于那个被利用了资源的网站是不公平的。一些不良网站为了不增加成本而扩充自己站点内容,经常盗用其他网站的链接。一方面损害了原网站的合法利益,另一方面又加重了服务器的负担。
所以一般情况下,我们需要给自己的网站设置一个防盗链的机制。通过referer,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示它的网页地址。有了referer跟踪来源就好办了,这时就可以通过技术手段来进行处理,一旦检测到来源不是本站即进行阻止或者返回指定的页面。
例如:
/**
* 需求:实现referer防盗链的现象
*
* @author 芷若初荨
*
*/
public class FangdaoLian extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String referer=req.getHeader(
"referer");
if(referer==
null||referer.startsWith(
"http://localhost")){
resp.sendRedirect(
"/ResponseTest/index.jsp");
}
String data=
"芷若初荨";
resp.getWriter().write(data);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
5.如何在MVC模式下,实现请求转发,以及使用request域对象把数据带给转发资源?
(PS:req.getRequestDispatcher(“/index.jsp”).forward(req, resp))
/**
* 需求:在MVC模式下,实现请求转发,以及使用request域对象把数据带给转发资源
* @author 芷若初荨
*
*/
public class RequestForwordTest extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String data=
"芷若初荨";
req.setAttribute(
"cc", data);
req.getRequestDispatcher(
"/index.jsp").forward(req, resp);;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
其中使用到的req.getRequestDispatcher(“/index.jsp”).forward(req, resp)就是转发的核心用法,但是也需要注意下以下细节:
**在请求转发之前,不能将write的流给关掉,否则跳转无效!!!
以下通过一个事例来说明:
eg:
String data="";
if(
true){
request
.getRequestDispatchter(
"/index.jsp")
.forword(request,response);
return;
}
request
.getRequestDispatchter(
"/message.jsp")
.forword(request,response);
**在每次forword跳转之前,会将response中的数据给清空;但是写入的头信息还是有效的。
**每次forword只会发生一次请求,并且地址栏不会发生改变。
PS:如有错,请指正!