一.Request
1.什么是Request
由于Http协议比较复杂, 所以在API中提供了 HttpServletRequest (继承自ServletRequest) 来封装 Http 请求消息;
2.Request的作用
获取客户端的请求信息;
2.1 获取请求行
@WebServlet("/demo1")
public class ServletDem01 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//使用request对象获取请求行的信息
//1. 获取请求的方式(可能会用)
String method = req.getMethod();
System.out.println("method = " + method); // method = GET
//2. 获取客户端的ip地址
String remoteAddr = req.getRemoteAddr();
System.out.println("remoteAddr = " + remoteAddr); // 0:0:0:0:0:0:0:1 ipv6地址
//3. 获取项目部署的路径
String contextPath = req.getContextPath();
System.out.println("contextPath = " + contextPath); // /rzc
//4. 获取请求的url: 统一资源定位符 http://localhost:8080/requestDemo/demo01
StringBuffer requestURL = req.getRequestURL();
System.out.println("requestURL = " + requestURL); // http://localhost:8080/rzc/demo1
//5. 获取请求的uri: 统一资源标识符,在url的基础上省略了服务器路径"http://loaclhost:8080"
String requestURI = req.getRequestURI();
System.out.println("requestURI = " + requestURI); // /rzc/demo1
}
}
- getServerPort(); 获取服务端的端口
- getQueryString(); 获取请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)
2.2 获取请求头
请求头包含的信息比较多, 需要用的时候可以通过 getHeader(String name) 函数来获取;
- User-Agent: 浏览器信息
- Referer: 来自哪个网站(防盗链)
2.3 获取请求体
注册页面
@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 根据参数名,获取一个参数值
String username = req.getParameter("username");
System.out.println("username = " + username);
//2. 根据参数名,获取多个参数值:比如说注册时候的兴趣爱好的复选框
String[] hobbies = req.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println("hobby = " + hobby);
}
//3. 获取所有的请求参数
//getParameterMap()获取所有请求参数,请求参数的参数名就是map的key,请求参数的参数值就是map的value
Map parameterMap = req.getParameterMap();
Set> entries = parameterMap.entrySet();
for (Map.Entry entry : entries) {
String key = entry.getKey();
String[] values = entry.getValue();
for (String value : values) {
System.out.println("key+\"=\"+value = " + key + "=" + value);
}
}
}
}
使用BeanUtils封装这些参数对象
1.需要依赖BeanUtils的jar包
2.Java Bean文件中的属性名需要和参数名一一对应;
BeanUtils.copyProperties(user,parameterMap);
// BeanUtils.populate(user,parameterMap);
2.4 请求转发
/**
* 1. 请求转发的效果的跳转, 跳转到其他页面,或者跳转到其它的servlet
* 2. 请求转发的跳转, 只能是跳转到本项目的资源
* 3. 请求转发的原理是: 服务器进行转发操作,将这次请求发给目标地址,由服务器向目标地址响应资源
*/
@WebServlet("/demo5")
public class ServletDemo5 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 访问此 Servlet 将跳转到 /register.html
// req.getRequestDispatcher("/register.html").forward(req,resp);
// 访问此 Servlet 将跳转到访问 /demo3
req.getRequestDispatcher("/demo3").forward(req,resp);
}
}
2.5 作为域对象
/**
* request 作为域对象在不同的Servlet之间进行数据的共享,它只能在同一次请求中进行数据共享
* request 域对象只有和请求转发一起使用才有意义
*/
@WebServlet("/demo6")
public class ServletDemo6 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name","ccs");
req.getRequestDispatcher("/demo7").forward(req,resp);
}
}
@WebServlet("/demo7")
public class ServletDemo7 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object name = req.getAttribute("name");
System.out.println("name=="+name);
}
}
二.Response
1.什么是Repsonse
由于Http协议比较复杂, 所以在API中提供了 HttpServletResponse (继承自ServletResponse) 来封装 Http 响应消息;
2.Response的作用
响应客户端的请求
2.1 设置响应行信息
/**
* response 设置响应行的信息
* setStatus设置响应状态码
* 200 响应成功
* 302 重定向
* 304 访问缓存
* 403 没有权限访问
* 404 客户端错误
* 500 服务器错误
*/
@WebServlet("/demo8")
public class ServletDemo8 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setStatus(403);
}
}
2.2 设置响应头信息以及重定向
/**
* 常用的响应头,需要使用其它的响应头可以去文档中查找
* Refresh 定时跳转
* Location 重定向地址
* Content-Disposition 告诉浏览器下载
* Content-Type 设置响应内容的MiME类型(服务器告诉浏览器内容的类型)
*/
@WebServlet("/demo9")
public class ServletDemo9 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Refresh 定时跳转
// resp.setHeader("Refresh","3,http://www.baidu.com");
// Location 重定向地址
resp.setStatus(302);
resp.setHeader("Location","/rzc/register.html");
// resp.sendRedirect("/rzc/register.html");
// resp.sendRedirect("http://www.baidu.com");
}
}
2.3 设置响应体信息
@WebServlet("/demo9")
public class ServletDemo9 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//给客户端响应一张图片
//1. 读取b.jpg图片,将其转换成字节输入流,使用ServletContext
// ServletContext servletContext = getServletContext();
// InputStream is = servletContext.getResourceAsStream("b.jpg");
//
// //2. 使用字节输出流,将is中的字节都输出到浏览器
// ServletOutputStream os = resp.getOutputStream();
//
// /*byte[] buffer = new byte[1024];
// int len = 0;
// while ((len = is.read(buffer)) != -1){
// os.write(buffer,0,len);
// }*/
// IOUtils.copy(is,os);
// os.close();
// is.close();
// 给客户端响应一段字符串
resp.setContentType("text/html;charset=UTF-8");
//要向浏览器输出响应体的信息,需要通过流来进行操作
//第一种:字符串,输出文本内容
PrintWriter writer = resp.getWriter();
//使用字符流往浏览器输出文本
//1. writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题
writer.write("你好世界");
//2. print()方法,可以输出数字、字符串
//writer.print(8);
}
}
三.请求转发与重定向的区别
1.跳转的发起者不同
请求转发的跳转发起者:是服务器去重新找到资源响应给浏览器
重定向的跳转发起者:是服务器响应给浏览器一个新的地址,两次都是浏览器;
2.浏览发起的请求次数不同
请求转发:只会请求一次;
重定向:会请求二次;
3.能够跳转到的资源
请求转发:只能是服务器本项目中的资源;
重定向:可以是任意地址;
4.地址样的地址是否发生改变
请求转发:没有发生改变;
重定向:会发生改变
四.路径问题
完整路径, 相对路径, 绝对路径; 完整路径, 是一个完整的访问地址, 可以在不同的项目中访问; 而相对路径与绝对路径都是针对相同项目而言的;
1.完整Url地址
url的组成部分:
例如 http://localhost:8080/rzc/jstl/jstl_test01.jsp
- http:// 表示协议是http协议
- localhost 表示主机地址,就是ip地址
- :8080 表示服务器的端口号 (通过端口号可以找到服务端程序的进程);
- rzc 表示项目的虚拟路径(部署路径), 这个在 idea 中一般为项目名, 可以设置成不包含这个路径的访问地址;
- jstl/jstl_test01.jsp 表示项目上的具体的动态或静态资源;
什么时候会使用完整的url
浏览器地址栏直接访问;
一个项目中,访问另一个项目中的资源;
2.相对路径
路径相关测试
hello world....
访问ServletDemo2
3.绝对路径
路径相关测试
hello world....
访问ServletDemo02
五.案例代码
1.文件下载案例
下载页面
下载a.jpg
下载b.jpg
下载WEB01.zip
下载美女.jpg
下载霉女.jpg
/**
* 浏览器访问DownloadServlet,如果是图片直接在浏览器上显示了,现在需要下载这张图片
* 使用 Content-Disposition 响应头,让浏览器进行文件的下载
* 当文件名是中文的时候,浏览器下载无法显示中文 URLEncoder
* file文件应该在web目录下
*/
@WebServlet("/demo10")
public class DownLoadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//获取请求参数fileName的值
String fileName = req.getParameter("fileName");
//读取对应的文件
InputStream is = req.getServletContext().getResourceAsStream("file/"+fileName);
//告诉浏览器文件的MIME类型(可以不写)
String mimeType = getServletContext().getMimeType(fileName);
System.out.println("mimeType = " + mimeType);
resp.setHeader("Content-Type",mimeType);
//使用字节输出流,将文件输出给浏览器
ServletOutputStream os = resp.getOutputStream();
//响应头中是无法识别中文的,所以有中文的文件名,在下载的时候显示会出现问题
//将文件名进行编码转换,将中文转换成英文
String encodeFileName = URLEncoder.encode(fileName, "UTF-8");
//在输出内容之前,进行响应头的设置,设置Content-Disposition响应头,让浏览器下载文件
resp.setHeader("Content-Disposition", "attachment;filename=" + encodeFileName);
IOUtils.copy(is, os);
os.close();
is.close();
}
}