一、web项目,是通过response和request对象通信,request封装请求消息,response对象封装返回消息。
1.服务器会根据请求url中的资源路径创建对应的Servlet的对象。
2.服务器会创建request和respones对象。
3.服务器将request和response两个对象传递给service()方法。
4.程序员可以通过request对象获取请求数据,通过respones对象设置响应消息数据。
5.服务器在给浏览器做出响应之前,会从response对象中拿出程序员设置的响应消息数据。
二、request
结构
1.ServletRequest -- 接口
2.HttpServletRequest --接口(实现ServletRequest)
3.org.apache.catalina.connector.RequestFacade (tomCat创建用于实现HttpServletRequest接口)
功能
1.获取请求行数据
1.获取请求方式 String getMethod()
2.获取虚拟目录(项目根目录) String getContexPath()
3.获取Servlet路径(定义的servlet请求路径) String getServletPath()
4.获取get方式请求参数 String getQueryString();
5.获取URI String getRequestURI() --请求的路径
6.获取url StringBuffer getRequestURL(); --http://IP:端口/请求路径
//URL:统一资源定位符;URI:统一资源标识符
7.获取协议及版本 String getProtocol() --http/1.1
8.获取客户机IP String getRemoteAddr()
package com.xiaoqiang.web;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet("/demo/requestDemo")
public class RequestDemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求行数据
// 1.获取请求方式 String getMethod()
String method = req.getMethod();
System.out.println("获取请求方式 String getMethod():" + method);
// 2.获取虚拟目录(项目根目录) String getContexPath()
String contextPath = req.getContextPath();
System.out.println("获取虚拟目录(项目根目录) String getContexPath():" + contextPath);
//3.获取Servlet路径(定义的servlet请求路径) String getServletPath()
String servletPath = req.getServletPath();
System.out.println("3.获取Servlet路径 String getServletPath():" + servletPath);
//4.获取get方式请求参数 String getQueryString();
String queryString = req.getQueryString();
System.out.println("获取get方式请求参数 String getQueryString():" + queryString);
//5.获取URI String getRequestURI() --请求的路径
String requestURI = req.getRequestURI();
System.out.println("获取URI String getRequestURI() --请求的路径:"+requestURI);
//6.获取url StringBuffer getRequestURL(); --http://IP:端口/请求路径
StringBuffer requestURL = req.getRequestURL();
System.out.println("获取url StringBuffer getRequestURL(); --http://IP:端口/请求路径:" + requestURL.toString());
//7.获取协议及版本 String getProtocol() --http/1.1
String protocol = req.getProtocol();
System.out.println("获取协议及版本 String getProtocol() --http/1.1:" + protocol);
//8.获取客户机IP String getRemoteAddr()
String remoteAddr = req.getRemoteAddr();
System.out.println("获取客户机IP String getRemoteAddr():" + remoteAddr);
//获取请求头数据
// 1.getHeaderNames()获取所有的请求头名称
Enumeration<String> headerNames = req.getHeaderNames();
// 2.遍历获取到的请求头名称,String getHeader(String name) 通过请求头的名称获取请求头的值
while (headerNames.hasMoreElements()){ //hasMoreElements() 迭代标志,是否有下一个请求头
String s = headerNames.nextElement();//获取下一请求头名称
String header = req.getHeader(s); //通过请求头的名称获取请求头的值
System.out.println("请求头"+s +"的值是:" + header);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求体
// 1.获取字符流
BufferedReader reader = req.getReader();
String line=null;
while ((line = reader.readLine()) != null){
System.out.println(line);
}
}
}
2.获取请求头数据
1.getHeaderNames():获取所有的请求头名称
2.String getHeader(String name) 通过请求头的名称获取请求头的值
3.获取请求体数据
*请求体:只有POST请求才有请求体,在请求体中封装了POST请求的请求参数
步骤*
1.获取流对象(字节流、字符流)
BufferedReader getReader() 获取字符输入流
ServletInputStream getInputStream() 获取字节输入流,可以操作有类的数据
2.从流对象中获取数据
4.其他功能
1.获取请求参数通用方式
String getParameter(String name);根据参数名称获取参数值
String[] getParameterValues("");根据参数名称获取参数值数组(多用于复选框)
Enumeration<String> getParameterNames();获取所有参数名称
Map<String, String[]> getParameterMap();获取所有参数的map集合,将参数名和参数值转换为Map集合, String[]避免参数有多个值的获取
//避免中文乱码,设置的值需要和请求页面的值要一致request.setCharacterEncoding("utf-8");
package com.xiaoqiang.web;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
@WebServlet("/obtainParameterServlet")
public class ObtainParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//避免中文乱码,设置的值需要和请求页面的值要一致
req.setCharacterEncoding("utf-8");
// String parameter = req.getParameter("");
// String[] parameterValues = req.getParameterValues("");
// Enumeration<String> parameterNames = req.getParameterNames();
// Map<String, String[]> parameterMap = req.getParameterMap();
//请求示例:http://localhost:8080/studyWeb/obtainParameterServlet?name=11111&passWord=22222
// 获取所有参数名
// Enumeration<String> parameterNames = req.getParameterNames();
// while (parameterNames.hasMoreElements()){
// String s = parameterNames.nextElement();
// 根据参数名获取参数值
// String parameter = req.getParameter(s);
// System.out.println("参数" + s +"的值是:" + parameter);
// }
//请求示例:http://localhost:8080/studyWeb/obtainParameterServlet?name=11111&name=222&name=333&paw=44444
Map<String, String[]> parameterMap = req.getParameterMap();
Set<String> strings = parameterMap.keySet();
for (String str : strings) {
String[] values = parameterMap.get(str);
String v = "";
for (String value : values) {
v = v + value + " ";
}
System.out.println("参数" + str + "的值是:" + v);
}
//请求示例:http://localhost:8080/studyWeb/obtainParameterServlet?name=11111&name=222&name=333
// String[] parameterValues = req.getParameterValues("name");
// for (String str : parameterValues) {
// System.out.println("name的值:" + str + " ");
// }
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//采用通用的获取参数的方式,post和get获取请求值的方式不再有区别,写一份获取值的代码即可
this.doGet(req, resp);
}
}
package com.xiaoqiang.web;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/responseDemo2Servlet")
public class ResponseDemo2Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("responseDemo2Servlet.....");
//获取字符输出流前设置编码格式,并告诉浏览器使用什么编码格式解码,防止乱码
// resp.setCharacterEncoding("utf-8");
// resp.setHeader("content-type","text/html;charset=utf-8");
resp.setContentType("text/html;charset=utf-8");
//获取字符输出流
PrintWriter writer = resp.getWriter();
//输出数据
writer.println("<h1>你好 response</h1>");
}
}
2.请求转发 - 服务器内部资源跳转方式
RequestDispatcher getRequestDispatcher(String path);获取请求对象转发器
forward(req,resp);调用转发器的方法转发请求
特点:1.浏览器地址栏路径不发生变化
2.只能转发到当前服务内的资源
3.转发基于客户端的一次请求即可
3.共享数据
域对象:一个有作用范围的对象,在范围内都可以访问该对象。
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据。
方法:
void setAttribute(String name,Object obj);存储数据
Object getAttribute(String name);获取数据
void removeAttribute(String name)移除数据
4.获取ServletContext
ServletContext getServletContext(); 获取ServletContext对象
package com.xiaoqiang.web;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/forwardServlet")
public class ForwardServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("source","访问来源forwardServlet");
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/receiveServlet");
requestDispatcher.forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
package com.xiaoqiang.web;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/receiveServlet")
public class ReceiveServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String source = (String) req.getAttribute("source");
System.out.println("接收者:receiveServlet" +"__" + source);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
三、response的继承结构
1.设置响应行
格式:HTTP/1.1 200 OK
设置状态码 void setStatus(int sc)
2.设置响应头
void setHeader(String name,String value)
3.设置响应体
1.步骤:
1.获取输出流
1.字符输出流 PringWriter getWriter()
为避免浏览器解析输出数据中文乱码,需要告诉浏览器使用什么格式解码
resp.setHeader("content-type","text/html;charset=utf-8") 或者 resp.setContentType("text/html;charset=utf-8")
2.字节输出流 ServletOutputStream getOutputStream();
2.使用输出流将数据输出到客户端
4.重定向:浏览器请求资源A,资源A告诉浏览器需要请求资源B,浏览器会去请求资源B
1.设置状态码为301或302告诉浏览器重定向
2.在请求头中设置请求头location,值为需要重定向到地址的资源路径
3.java简单的重定向方法:void sendRedirect(String s)
转发(forward)和重定向(redirect)的区别
转发:转发地址栏不变化、只能访问当前服务下的资源、转发浏览器只请求一次,可以使用request域共享数据
重定向:地址栏发生变化,可以访问其他服务器资源,重定向浏览器接会有两次请求,会产生两个request对象,不能通过request共享数据
绝对路径和相对路径
1.相对路径:不以/开头的资源路径,通过相对路径不可以确定唯一资源
例如:./index.html 或者 index.html
规则:相对路径会以当前资源为基准,寻找目标资源,要使用相对路径需要确定当前资源和目标资源的相对的关系
当前目录 ./ 或者直接写目标的名称会从当前资源所在的路径开始
后退一级 ../
2.绝对路径:以/(项目根目录或者说项目虚拟目录)开头的路径,通过绝对路径可以确定唯一资源
例如:http://localhost:8080/studyWeb/responseDemo2Servlet
可以简写为:/studyWeb/responseDemo2Servlet
3.使用规则:判断路径给谁用的
1.给客服端使用:需要加虚拟目录(项目访问路径)
建议动态获取虚拟目录:request.getContextPath()
2.给服务器使用:不需要加虚拟目录
package com.xiaoqiang.web;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/responseServlet")
public class ResponseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("responseServlet......");
//设置状态码, 告诉浏览器需要重定向
// resp.setStatus(302);
//设置请求头,告诉浏览器请求的地址
// resp.setHeader("location","/studyWeb/responseDemo2Servlet");
// JAVA封装的重定向方法
// resp.sendRedirect("/studyWeb/responseDemo2Servlet");
//动态获取项目虚拟目录,防止虚拟目录变更造成资源请求404
String contextPath = req.getContextPath();
resp.sendRedirect(contextPath + "/responseDemo2Servlet");
//获取输出流--字符输出流
// PrintWriter writer = resp.getWriter();
// writer.println("");
//获取输出流-- 字节输出流
// ServletOutputStream outputStream = resp.getOutputStream();
}
}
package com.xiaoqiang.web;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/responseDemo2Servlet")
public class ResponseDemo2Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("responseDemo2Servlet.....");
//获取字符输出流前设置编码格式,并告诉浏览器使用什么编码格式解码,防止乱码
// resp.setCharacterEncoding("utf-8");
// resp.setHeader("content-type","text/html;charset=utf-8");
resp.setContentType("text/html;charset=utf-8");
//获取字符输出流
PrintWriter writer = resp.getWriter();
//输出数据
writer.println("<h1>你好 response</h1>");
}
}
package com.xiaoqiang.web;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
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.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Random;
@WebServlet("/responseDemo3Servlet")
public class ResponseDemo3Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//告知浏览器解码格式
// resp.setContentType("text/html;charset=utf-8");
//获取字节输出流
// ServletOutputStream outputStream = resp.getOutputStream();
//输出字节
// outputStream.write("你好".getBytes(StandardCharsets.UTF_8));
//创建图片对象
int width=100;
int height=50;
BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//美化图片
//填充颜色
Graphics graphics = bufferedImage.getGraphics();//获取画笔
graphics.setColor(Color.yellow);//设置画笔颜色
graphics.fillRect(0,0,width,height);
//画边框
graphics.setColor(Color.blue);
graphics.drawRect(0,0,width,height-1);
String strs = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
Random random = new Random();
graphics.setColor(Color.black);
for (int i = 0; i < 4; i++) {
int index = random.nextInt(strs.length());
String str = strs.substring(index,index+1);
graphics.drawString(str,width/5*i,height/2);
}
ImageIO.write(bufferedImage,"jpg",resp.getOutputStream());
}
}