HTTP请求和响应
what
- Servlet主要作用就是处理客户端请求,并向客户端做出响应,所以Servlet的每次调用service()方法之前,都会创建两个对象,分别是HttpServeletRequest和HttpServletResponse.
- 每次Servlet都只会创建一个实例对象,接受一个请求,就会重新创建一个request对象和一个response对象,
HttpServletResponse对象
状态码方法:
setStatus( int status):
sendError(int sc): 发送错误信息的状态码
响应消息头相关方法:
- void addHeader(String name,String value):
- void setHeader(String name ,String vlaue):
- void addIntHeader(String name,int value):
- void setIntHeader(String name,int value):
- void setContentLength(int len)
- void setContentType(String type)
- void setLocale(Locale loc) 用于设置响应消息的本地化信息
- void setCharacterEncoding(String charset)
发送响应消息体的方法:
- getOutputStream()方法:
public class MyHttpServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String data = "itcast";
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.write(data.getBytes());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
- getwriter():
public class MyHttpServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String data = "itcast";
//获取字符输出流对象
PrintWriter writer = resp.getWriter();
writer.println(data);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
输出中文乱码
why
computer的数据是以二进制的形式存储,传输文本的时候,发生字符和字节的转换,字符和字节的转换通过查码表完成,字符向字节的转换是编码,字节向字符是解码,编码和解码使用的码表不一致,就会导致乱码问题,这里就相当于response对数据进行编码,使用的是一种码表,而浏览器对数据进行解码使用的是另一种码表,导致中文乱码。、
方法(两种)
- 第一种
resp.setCharacterEncoding("utf-8");
resp.setHeader("Content-Type","text/html;charset=utf-8");
- 第二种
resp.setContentType("text/html;charset=utf-8");
代码
public class MyHttpServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String data = "itcast";
//获取字符输出流对象
PrintWriter writer = resp.getWriter();
/*第一种*/
resp.setContentType("text/html;charset=utf-8");
/*第二种*/
resp.setCharacterEncoding("utf-8");
resp.setHeader("Content-Type","text/html;charset=utf-8");
writer.println(data);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
网页的定时刷新
- setHeader(“Refresh”,“2,URL=http://www.bia.com”);
public class MyHttpServlet3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//两秒后,跳转到指定页面
resp.setHeader("Refresh","2,URL=http://www.it.com");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
public class MyHttpServlet4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 每个三秒定时刷新当前网页
resp.setHeader("Refresh","3");
resp.getWriter().println(new java.util.Date().toLocaleString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
网页重定向
sendRedirect():方法
- 代码
- login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/chapter04/MyHttpServlet5" method="post">
用户名:<input type="text" name="username"/><br/>
密 码:<input type="password" name="password"/><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
- welcome.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登录成功,欢迎您!</h1>
</body>
</html>
- MyHttpServlet5
public class MyHttpServlet5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//用HttpServletRequest对象的getParameter()方法获取用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
if("itcast".equals(username) && "123".equals(password)){
//密码和用户名正确,跳转到欢迎页面
resp.sendRedirect("/chatper04/welcome.html");
}else {
//不正确,跳转到登录页面
resp.sendRedirect("/chapter04/login.html");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
HttpServletRequest对象
获取请求行的相关方法
public class MyHttpServlet6 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
/*HTTP请求种请求方式*/
writer.println(req.getMethod());
/*资源名称部分,主机号和端口号之后,参数部分之前*/
writer.println(req.getRequestURI());
/*参数部分*/
writer.println(req.getQueryString());
/*协议名和版本号*/
writer.println(req.getProtocol());
/*请求URL中属于web应用的路径*/
writer.println(req.getContextPath());
/*Servlet的名称和映射路径*/
writer.println(req.getServletPath());
/*主机的ip地址*/
writer.println(req.getRemoteAddr());
/*客户端的完整主机名*/
writer.println(req.getRemoteHost());
/*客户端的网络连接的端口号*/
writer.println(req.getRemotePort());
/*web服务器上的当前网络连接的ip地址*/
writer.println(req.getLocalAddr());
/*web服务器上的当前网络连接的对应的主机号*/
writer.println(req.getLocalName());
/*web服务器上的当前网络连接的对应的端口号*/
writer.println(req.getLocalPort());
/*host字段中对应的主机名*/
writer.println(req.getServerName());
/*host字段中对应的端口号*/
writer.println(req.getServerPort());
/*请求的协议名 例如:http*/
writer.println(req.getScheme());
/*完整的路径*/
writer.println(req.getRequestURL());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
请求头的方法
- String getHeader(String name):
- Enumeration getHeaders(String name)
- Enumeration getHeaderNames()
- int getIntHeader(String name)
- long getDateHeader(String name)
- String getContentType()
- int getContentLength()
- String getCharacterEncoding()
public class MyHttpServlet7 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
//获取请求消息头中的所有字段
Enumeration<String> headerNames = req.getHeaderNames();
//遍历
while (headerNames.hasMoreElements()){
String name = headerNames.nextElement();
String value = req.getHeader(name);
writer.println(name + ":" + value);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
referer 防盗链
public class MyHttpServlet8 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
//获取referer头
String referer = req.getHeader("referer");
//提取访问地址
String serverName = req.getServerName();
String url ="http://" + serverName;
//判断referer是否为空,这个头的首地址是否是自己的
if(referer != null && referer.startsWith(url)){
writer.println("download");
}else {
//防盗链,跳转到自己的网页
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/download.html");
requestDispatcher.forward(req,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
HttpServletRequest应用
- getParameter(String name)
- get[ara,eterValues(String name)
- getParameterNames()
- getParameterMap()
- setAtrtibute()
- getAttribute()
- removeAttribute()
- getAttributeNames()
form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/chapter04/MyHttpServlet9" method="get">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
兴趣:<input type="checkbox" name="hobby" value="sing">唱歌
<input type="checkbox" name="hobby" value="game">游戏
<input type="checkbox" name="hobby" value="dance">跳舞
<input type="submit" value="get"/>
</form>
</body>
</html>
public class MyHttpServlet9 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username + ":" + password);
String[] hobbies = req.getParameterValues("hobby");
System.out.println("爱好:");
for(int i = 0;i<hobbies.length;i++){
System.out.println(hobbies[i]);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
请求参数乱码
req.setCharacterEncoding("utf-8");
RequestDispatcher对象
- getRequestDispatcher(String path) : 返回封装了路径所指定资源的RequestDispatcher对象
- 创建了对象之后,要通知其他Web资源对该Servlet请求进行处理,为此有两个方法
- forward(req,resq);请求从一个Servlet传递给另一个Web资源
- include(req,resq); 将其他资源作为当前响应内容包含进来
forward
public class MyHttpServlet10 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
req.setAttribute("username","chen");
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/MyHttpServlet11");
requestDispatcher.forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
public class MyHttpServlet11 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
String username = (String) req.getAttribute("username");
if(username != null ){
resp.getWriter().println(username);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
include
public class MyHttpServlet10 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
// req.setAttribute("username","chen");
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/MyHttpServlet11?username=123");
requestDispatcher.include(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
public class MyHttpServlet11 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
String username = (String) req.getAttribute("username");
if(username != null ){
resp.getWriter().println(username);
}
resp.getWriter().println(req.getQueryString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
1、请求转发与重定向的异同点如下:
1) 请求转发和重定向都可以实现访问一个资源时转向当前应用资源
2) 请求转发是一次请求一次响应,而重定向为两次请求两次响应
3)一般情况下应该使用请求转发,减少浏览器对服务器的访问,减轻服务器压力
4)如果需要改变浏览器的地址栏,或更改浏览器的刷新按钮的功能时需要使用重定向
2、禁止浏览器缓存页面的核心代码如下:
response.setDateHeader("Expires",0);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
重定向后,地址栏显示index.jsp
3、实现代码如下:
(1)MyServlet程序类如下:
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException, IOException {
System.out.println("这里是MyServlet!");
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
}
(2)web.xml文件配置如下:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>
cn.itcast.chapter04.servlet.MyServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
4、该功能的实现步骤如下:
1)创建一个DownManagerServlet类,使其继承HttpServlet类并重写该类的doGet()方法。
2)在doGet()方法中,使用HttpServletRequest对象的getHeader("referer")方法得到字段referer的值,并判断是否可以进行资源下载。
3)如果不能下载,则进入下载页(需要在Eclipse的WebContent目录下创建一个download.html)。
(1)DownManagerServlet类的实现代码如下:
public class DownManagerServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
// 获取referer头的值
String referer = request.getHeader("referer");
// 获取访问地址
String sitePart = "http://" + request.getServerName();
if (referer != null && referer.startsWith(sitePart)) {
// 处理正在下载的请求
out.println("dealing download ...");
} else {
// 非法下载请求跳转到download.html页面
RequestDispatcher rd = request
.getRequestDispatcher("/download.html");
rd.forward(request, response);
}
}
}
(2)web.xml文件中DownManagerServlet的映射信息配置如下:
<servlet>
<servlet-name>DownManagerServlet</servlet-name>
<servlet-class>
cn.itcast.chapter04.servlet.DownManagerServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownManagerServlet</servlet-name>
<url-pattern>/DownManagerServlet</url-pattern>
</servlet-mapping>