目录
重定向过程:
浏览器发送http请求——>服务器接受后发送302状态码进行响应及对应新的 location(请求地址)给浏览器——>浏览器发现是302响应,就会自动再发送一个新的http请求,请求url是接收到的新location (请求地址)——>服务器根据此请求寻找资源并发送给客户。
在这里新的请求地址 location可以重定向到任意URL,既然是浏览器重新发出了请求,那么之前的request就相当于结束了生命周期。最终在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。

通过response设置响应行
设置响应行的状态码
public class LineServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
/**
* setStatus(int status);设置响应的状态码
* 302状态码表示重定向
*/
response.setStatus(302);
}
}
通过response设置响应头
相关方法:
setHeader(String name, String value)
setIntHeader(String name, int value)
setDateHeader(String name, long date)
使用set方式添加的数据,如果之前有同名的key存放了数据,会将其覆盖。
addHeader(String name, String value)
addIntHeader(String name, int value)
addDateHeader(String name, long date)
使用add方式添加的数据,如果之前有同名的key已经存放了数据,会再次添加一个数据进去。
代码
public class HeaderServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
/**
* setHeader(key,value);设置响应头,如果key一样,值不一样,那么后面的会覆盖前面的
*
* addHeader(key,value);设置响应头,如果key一样,值不一样,那么值会叠加
*/
/*response.setHeader("name", "shuishen");
response.setHeader("name","yanyan");
response.setDateHeader("date", System.currentTimeMillis());*/
response.addHeader("name", "shuishen");
response.addHeader("name", "yanyan");
response.getWriter().write("");
}
}
重定向到一个页面或者servlet:
public class RedirecteServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
/**
* 1.设置状态码为302
* 2.设置响应头location
*
* sendRedirect(url);重定向,完成了上述2个操作的封装
*/
System.out.println("实现重定向的操作");
// response.setStatus(302);
// //response.setHeader("location", "http://www.baidu.com");
// response.setHeader("location", "/web03/index.html");
response.sendRedirect("/web03/index.html");
}
}
通过response设置响应体
应用场景: 浏览器显示的内容, 下载文件等.
response 可以将响应内容输出给浏览器,也可以输出一个html个浏览器。
response.getWriter() 获取响应体的字符输出流
response.getOutputStream() 获取响应体的字节输出流
通过这两个流都可以向浏览器响应数据.
注意问题:
- getOutputStream 和 getWriter 相互排斥,调用了其中一个方法就不能调用另外一个方法。
- tomcat会自动调用response输出流的 close方法和flush方法, 因此不需要我们手动关闭流。
字符流响应数据
获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。
public class BodyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//获取一个字符串输出流
PrintWriter writer = response.getWriter();
//将需要响应的数据添加到response缓冲区中,最后有tomcat将数据组装成http响应并发送给客户端
//response缓冲区中默认的字符集是iso8859-1
writer.write("<html>");
writer.write("<head>");
writer.write("<title>Insert title here</title>");
writer.write("</head>");
writer.write("<body>");
writer.write("<a href='/web_day03/demo.html'>点击</a>");
writer.write("</body>");
writer.write("</html>");
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
将username修改成中文的张三后,发现不能响应中文,会乱码。
关于设置中文的乱码问题
原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文,可以通过 response的setCharacterEncoding(String charset) 设置response的编码为utf-8,如:response.setCharacterEncoding("utf-8");
但我们发现客户端还是不能正常显示文字(chrome会自动转换,而火狐没有这功能因此会乱码)
原因:我们将response缓冲区的编码设置成UTF-8,但浏览器的默认编码是本地系 统的编码,因为我们都是中文系统,所以客户端浏览器的默认编码是GBK,我们可以手动修改浏览器的编码是UTF-8。
或者通过设置响应头的方式来设置浏览器对html文件的编码格式:
response.setHeader("content-type", "text/html;charset=utf-8");
我们还可以在代码中直接指定response缓冲区编码方式和浏览器解析页面的解码方式,
response.setContentType("text/html;charset=utf-8");
该行代码同时包含了以下两行代码的作用:
response.setCharacterEncoding("utf-8");
response.setHeader("content-type", "text/html;charset=utf-8");
因此,最终代码可以修改如下:
public class BodyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
/**
* 响应体的设置
* 1.可以使用字符流的响应
* 2.可以使用字节流的响应
*
* 字符流响应存在的乱码问题:响应体的内容被存在放在了tomcat的缓冲区,
* 缓冲是以tomcat默认的iso-8859-1的编码进行编码的。
* 解决方案:我们需要设置缓冲区的编码为utf-8 response.setCharacterEncoding("utf-8");
*
* 依然会存在乱码问题:原因是我们虽然以utf-8进行编码了,但是浏览器没有以utf-8进行解码。所以我们还需要设置浏览器的解码格式
解决方案: 1. writer.write("<meta charset='UTF-8'>")
2. 通过设置响应头的方式,告诉浏览器的解码格式为utf-8
response.setHeader("content-type", "text/html;charset=utf-8");
response.setContentType("text/html;charset=utf-8");是对上述2个方法的封装
*/
/*response.setCharacterEncoding("utf-8");
response.setHeader("content-type", "text/html;charset=utf-8");*/
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<html>");
writer.write("<head>");
/*writer.write("<meta charset='UTF-8'>");*/
writer.write("<title>i like taobao</title>");
writer.write("</head>");
writer.write("<body>");
writer.write("<a href='http://www.baidu.com'>百度</a>");
writer.write("</body>");
writer.write("</html>");
}
}
字节流响应数据
ServletOutputStream getOutputStream()
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,在由Tomcat服务器将字节内容组成Http响应返回给浏览器。
public class ImgServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String sex = (String)getServletContext().getAttribute("sex");
System.out.println("ImgServlet中:"+getServletContext());
System.out.println("ImgServlet中获取的值:"+sex);
/**
* 字节流响应
*/
ServletOutputStream out = response.getOutputStream();
//1.获取文件的绝对路径
String realPath = getServletContext().getRealPath("/img3.jpg");
System.out.println(realPath);
//2.获取文件流对象
FileInputStream fs = new FileInputStream(realPath);
int len = 0;
byte[] buf = new byte[1024];
while((len = fs.read(buf))!=-1){
//3.将文件以字节的方式响应给浏览器
out.write(buf, 0, len);
}
fs.close();
}
}
ServletContext对象
ServletContext对象内部有着该web项目的一些相关信息,这些信息可以被工程中的所有的servlet所共享。
可以通过底层代码查看获取ServletConfig和ServletContext的获取过程和之间的联系
- ServletContext context = config.getServletContext()
- ServletContext context = this.getServletContext();
ServletContext的作用
1.获取全局的初始化信息
getInitParameter(String name)
2.获取web应用的绝对路径
如获取项目中a.txt、b.txt的文件路径
获取路径的方法:getRealPath(“a.tx”),仅仅是起到了拼接web应用的资源路径和方法中字符串的作用
3.域对象:存储数据
什么是域对象:就是存储数据的一块区域。
一个web应用中的所有serlvet可以共享ServletContext中的数据。
常用方法:也是所有域对象都有的方法。
//增加
setAttribute(String name, Object object)
//通过该方法可以将数据以key和value的形式存储到ServletContext中
//删除
removeAttribute(String name)
//通过该方法可以将配置信息从ServletConfig中删除
//获取
getAttribute(String name) :通过key获取value
public class MyServletContextTest extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
/**
* servletContext:指代了当前项目的上下文对象。就代表了当前项目的一些配置信息
* 1.获取全局的初始化参数(了解)
* 2.可以获取文件的绝对路径(常用)
* servletContext.getRealPath("");获取的当前项目发布的绝对路径
* 这个方法是将当前项目的发布的绝对路径和方法的参数做了个字符串的拼接
* 3. 域对象 :servletContext可以作为一个存储数据库的对象。这个区域是有范围的。
* 如下特点:
* setAttribute(key,value);
* getAttribute(key);
* removeAttribute(key);
*/
ServletContext servletContext = getServletContext();
/*String username = servletContext.getInitParameter("username");
System.out.println(username); */
String realPath = servletContext.getRealPath("/WEB-INF/classes/2.txt");
FileInputStream fs = new FileInputStream(realPath);
System.out.println(realPath);
System.out.println("MyServletContextTest类中:"+servletContext);
servletContext.setAttribute("sex", "female");
}}
验证码页面代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>验证码</title>
</head>
<body>
请输入验证码:<input type="text"> <img id="myimg" src="/checkServlet" onclick="changeImgae()"> <a href="#" onclick="changeImgae()">看不清,换一张</a>
</body>
<script type="text/javascript">
function changeImgae(){
var myimg = document.getElementById("myimg");
myimg.src="/checkServlet?id="+new Date().getTime();
}
</script>
</html>
验证码java代码:
package cn.bufanli;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 验证码
*/
public class CheckServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException {
int width = 120;
int height = 40;
//首先获取画板
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics gh = image.getGraphics();
//绘制背景色
//设置画笔的颜色
gh.setColor(Color.white);
//绘制背景
gh.fillRect(0, 0, width, height);
//设置画笔颜色
gh.setColor(Color.red);
gh.drawRect(0, 0, width-1, height-1);
//绘制验证码字符串
Random rd = new Random();
String str = "abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ0123456789";
for(int i=1;i<5;i++){
String s = str.charAt(rd.nextInt(str.length()))+"";
//设置颜色
Color color = new Color(rd.nextInt(256),rd.nextInt(256),rd.nextInt(256));
gh.setColor(color);
//设置字体
Font font = new Font("宋体", Font.ITALIC, 30);
gh.setFont(font);
//绘画字符串
gh.drawString(s, (i-1)*30+5, 30);
}
//绘制干扰线
for(int i=1;i<7;i++){
gh.setColor(new Color(rd.nextInt(256),rd.nextInt(256),rd.nextInt(256)));
gh.drawLine(rd.nextInt(width),rd.nextInt(height), rd.nextInt(width),rd.nextInt(height));
}
//将图片响应给浏览器 第一个参数:将要输出的图片对象 第二个参数:图片的类型 第三个参数:输出流
ImageIO.write(image, "jpg", response.getOutputStream());
}}
web.xml代码
<servlet>
<servlet-name>CheckServlet</servlet-name>
<servlet-class>cn.bufanli.CheckServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CheckServlet</servlet-name>
<url-pattern>/checkServlet</url-pattern>
</servlet-mapping>
694



被折叠的 条评论
为什么被折叠?



