学习目标
第一章-request
知识点-request概述
1.目标
- 知道什么是request以及作用
2.讲解
2.1什么是request
在Servlet API中,定义了一个HttpServletRequest接口,它继承自ServletRequest接口,专门用来封装HTTP请求消息。由于HTTP请求消息分为请求行、请求头和请求体三部分,因此,在HttpServletRequest接口中定义了获取请求行、请求头和请求消息体的相关方法.
Web服务器【tomcat】收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。(request对象和response对象是由Web服务器tomcat 创建的)
Request:封装请求信息,获取请求信息
Request体系结构:request-->RequstFacade-实现->HttpServletRequest-继承->ServletRequest
2.2request作用(处理请求信息)
- 操作请求信息
- 请求转发【资源跳转】
- 共享数据
3.小结
- request:由服务器创建,传递给service方法,用于封装请求信息,获取请求信息。
- Request体系结构:request-->RequstFacade-实现->HttpServletRequest-继承->ServletRequest
- 作用
- 操作请求信息
- 转发
- 共享数据
知识点-操作请求行和请求头
1.目标
- 掌握使用request对象获取客户机信息(操作请求行)和获得请求头信息(操作请求头)
2.路径
- 获取客户机信息(操作请求行)
- 获得请求头信息(操作请求头)
3.讲解
3.1获取客户机信息(操作请求行)
请求方式 请求路径(URI) 协议版本
GET /day22/login.html?username=admin&password=123 HTTP/1.1
- getMethod();获取请求方式
- getRemoteAddr() ;获取客户机的IP地址(知道是谁请求的)
- getContextPath();获得当前应用工程名(部署的路径 虚拟路径);
- getRequestURI();获得请求地址,不带主机名和端口号
- getRequestURL();获得请求地址,带主机名
- getServerPort();获得服务端的端口
- getQueryString();获得请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)
package com.itheima.web.request;
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("/request02")
public class RequestServlet02 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RequestServlet02...");
// GET /day24/request02?username=admin&password=123 HTTP/1.1
//1.获取请求方式get|post String getMethod()
String method = request.getMethod();
System.out.println("method = " + method);
//2.获取资源地址uri String getRequestURI() 不包含协议、ip地址、端口号
String requestURI = request.getRequestURI();
System.out.println("requestURI = " + requestURI);
//3.获取请求请求路径url StringBuffer getRequestURL() 包含协议、ip地址、端口号一个完整的地址
StringBuffer requestURL = request.getRequestURL();
System.out.println("requestURL = " + requestURL);
//4.获取项目虚拟路径 getContextPath()
String contextPath = request.getContextPath();
System.out.println("contextPath = " + contextPath);
//5.获取参数 getQueryString()
String queryString = request.getQueryString();
System.out.println("queryString = " + queryString);
//6.获取客户端ip地址 getRemoteAddr()
String remoteAddr = request.getRemoteAddr();
System.out.println("remoteAddr = " + remoteAddr);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
3.2.获得请求头信息(操作请求头)
请求头: 浏览器告诉服务器自己的属性,配置的, 以key value存在, 可能一个key对应多个value
getHeader(String name);
- User-Agent: 客户端浏览器信息
- Referer:来自哪个网站(防盗链)
@WebServlet("/request03")
public class RequestServlet03 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RequestServlet03...");
//user-agent:获取客户端浏览器信息 方便根据浏览器的版本,解决浏览器的兼容性问题
//referer:获取从哪里进来的 方便做防盗链处理
String userAgent = request.getHeader("user-agent");
System.out.println("userAgent = " + userAgent);
String referer = request.getHeader("referer");
System.out.println("referer = " + referer);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
4.小结
-
操作请求行
- getMethod():获取请求方式 get|post
- getContextPath():获取项目发布的虚拟路径
- getRequestURI():获取请求地址(不带协议、ip地址、端口号)
-
操作请求头
- user-agent:获取客户端浏览器的版本信息
- referer:获取客户端从哪一个地址进来
知识点-操作请求体(获得请求参数)【重点】
1.目标
- 掌握获得请求参数, 以及乱码的解决
2.路径
- 获得请求参数
- 请求参数中文乱码的处理
- 使用BeanUtils封装请求参数到JavaBean
3.讲解
3.1获得请求参数【通用】
法名 | 描述 |
---|---|
String getParameter(String name) | 获得指定参数名对应的值。如果没有则返回null,如果有多个获得第一个。 例如:username=jack |
String[] getParameterValues(String name) | 获得指定参数名对应的所有的值。此方法专业为复选框提供的。 例如:hobby=抽烟&hobby=喝酒&hobby=敲代码 |
Map<String,String[]> getParameterMap() | 获得所有的请求参数。key为参数名,value为key对应的所有的值。 |
@WebServlet("/request05")
public class RequestServlet05 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RequestServlet05...");
//get方式请求:不乱码 tomcat8以后已经处理好了
//post方式请求:乱码 需要添加一句代码解决 设置服务器解析请求信息使用的字符集
request.setCharacterEncoding("UTF-8");
//获取请求参数 通用方法【无论是get请求还是post方式请求都可以使用】
//getParameter():获取单个值
//getParameterValues():获取多个值 指的是获取复选框的值
//getRequestMap():获取所有参数封装到map集合中 参数名称作为key,参数值作为value
String username = request.getParameter("username");
System.out.println("username = " + username);
String password = request.getParameter("password");
System.out.println("password = " + password);
String[] hobbies = request.getParameterValues("hobby");
System.out.println("hobby----");
for (String hobby : hobbies) {
System.out.println(hobby);
}
System.out.println("--------------------------------------------------");
Map<String, String[]> parameterMap = request.getParameterMap();
Set<String> keys = parameterMap.keySet();
for (String key : keys) {
System.out.println(key);
String[] values = parameterMap.get(key);
for (String value : values) {
System.out.println(value);
}
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
3.2 请求参数乱码处理
我们在输入一些中文数据提交给服务器的时候,服务器解析显示出来的一堆无意义的字符,就是乱码。
那么这个乱码是如何出现的呢?如下图所示:
- get方式, 我们现在使用的tomcat>=8.0了, 乱码tomcat已经处理好了
- post方式, 就需要自己处理
void setCharacterEncoding(String env); //设置请求体的编码
//处理post请求中文乱码
request.setCharacterEncoding("UTF-8");
乱码处理:保证编码和解码所使用的字符集一致,即可解决乱码。
3.3使用BeanUtils封装
现在我们已经可以使用request对象来获取请求参数,但是,如果参数过多,我们就需要将数据封装到对象。
以前封装数据的时候,实体类有多少个字段,我们就需要手动编码调用多少次setXXX方法,因此,我们需要BeanUtils来解决这个问题。
BeanUtils是Apache Commons组件的成员之一,主要用于简化JavaBean封装数据的操作。
使用步骤:
- 导入jar
- 使用BeanUtils.populate(user,map)
- 表单 reg.html
<form action="request06" method="post">
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br>
hobby:<input type="checkbox" name="hobby" value="sing">唱歌
<input type="checkbox" name="hobby" value="dance">跳舞
<input type="checkbox" name="hobby" value="code">敲代码
<input type="submit" value="注册">
</form>
- RequestServlet06
/**
* 使用BeanUtils封装请求参数到javabean对象
* 1.导入jar包
* 2.获取所有请求参数 getParameterMap()
* 3.创建javabean对象
* 4.将map集合中的参数信息封装到javabean对象中 使用BeanUtils工具类的方法populate(Object obj,Map map);
* 注意:map的key要和java对象属性一致
*/
@WebServlet("/request06")
public class RequestServlet06 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RequestServlet06...");
//解决请求中文乱码
request.setCharacterEncoding("UTF-8");
try {
Map<String, String[]> parameterMap = request.getParameterMap();
User user = new User();
//注意:map的key要和java对象属性一致
BeanUtils.populate(user,parameterMap);
System.out.println("user = " + user);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
4.小结
-
获取请求参数【通用】
- getParameter(String name):根据参数名称获取单个值
- getParameterValues(String name):根据参数名称获取多个值 用于复选框
- getParameterMap():获取所有请求参数封装到Map集合中
-
请求参数中文乱码处理
- get方式:没有中文乱码 无需处理 tomcat8.0版本以后已经处理了
- post方式:需要处理 request.setCharacterEncoding("UTF-8");
-
使用BeanUtils将所有请求参数map集合中的数据封装到javabean对象
-
导入jar包
-
BeanUtils.populate(Object bean,Map map);
注意:Map集合的key一定要和javabean的属性一致。
-
知识点-请求转发【重点】
1.目标
- 掌握请求转发
2.讲解
请求转发:服务器内部资源跳转的一种方式
html:a标签、form表单action
js:location.href="..."
//转发:就是将客户端的请求交给另外一个Servlet处理
//转发实现步骤
//1.获取转发对象
request.getRequestDispatcher("转发地址");
//2.跳转
forward(request,response);
//经常就一步完成
request.getRequestDispatcher("转发地址").forward(request,response);
RequestServlet07.java
/**
* 转发
*/
@WebServlet("/request07")
public class RequestServlet07 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RequestServlet07...");
//共享数据
request.setAttribute("rkey","rrr");
//转发实现 相对路径
request.getRequestDispatcher("request08").forward(request,response);
//转发实现 绝对路径 服务器端使用/:表示http://localhost:8080/虚拟路径
//request.getRequestDispatcher("/request08").forward(request,response);
//转发不能访问到外部资源
//request.getRequestDispatcher("https://www.baidu.com").forward(request,response);
//转发可以访问到WEB-INF下的资源
//request.getRequestDispatcher("WEB-INF/haha.html").forward(request,response);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
RequestServlet08.java
package com.itheima.web.request;
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("/request08")
public class RequestServlet08 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("RequestServlet08...");
//转发一次请求 可以使用Request对象共享数据
Object rkey = request.getAttribute("rkey");
System.out.println(rkey);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
特点:
1. 转发发生在服务器内部,不能请求外部资源
2. 转发地址栏不发生改变
3. 转发发送一次请求
4. 转发一般使用相对路径
5. 转发请求数据不会丢失
6. 转发可以访问到WEB-INF下的资源
3.小结
-
转发 :指的是将客户端的请求,服务端接收之后再交给第三方处理,是一种服务器内部资源跳转方式。
-
实现:request.getRequestDispacther("转发地址").forward(request,response);
-
特点:
-
1.转发只发送一次请求,转发地址栏不发生改变 2.转发请求信息不会丢失 3.转发只能请求服务器内部【当前web应用】资源,不能请求外部资源 4.转发可以请求WEB-INF下的资源 5.转发使用的是相对路径
-
知识点-作为域对象存取值
1.目标
- 掌握request作为域对象存取值
2.讲解
ServletContext:域对象 代表的是整个应用
域对象:一个有作用范围的对象 ,在它的作用范围中可以实现数据共享。
request域对象:一次请求,因此一般只能在转发中使用数据共享。
域对象是一个容器,这种容器主要用于Servlet与Servlet/JSP之间的数据传输使用的。
- Object getAttribute(String name) ;
- void setAttribute(String name,Object object) ;
- void removeAttribute(String name) ;
3.小结
-
request域对象:在一次请求中共享数据,只能用在转发中
-
API
- setAttribute(String name,Object value);
- getAtrribute(String name);
- removeAttribute(String name);
第二章-Response
知识点-Response概述
1.目标
- 掌握什么是Response,以及Response的作用
2.讲解
2.1HttpServletResponse概述
Response:封装响应信息,响应给客户端浏览器
体系结构:response-->RequestFacade-实现->HttpServletResponse-继承->ServletResponse
在Servlet API中,定义了一个HttpServletResponse接口(doGet,doPost方法的参数),它继承自ServletResponse接口,专门用来封装HTTP响应消息。由于HTTP响应消息分为响应行、响应头、响应体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码、响应头、响应体的方法
2.2作用
- 设置响应的三部分(响应行,响应头,响应体)
3.小结
- Response:封装响应信息,设置响应信息 响应给客户端浏览器
- 体系结构:ServletResponse--继承-->HttpServletResponse--实现-->ResponseFacade
- tomcat创建了request和response对象,开发中只需要使用这两个对象即可,使用request对象获取请求信息,使用response对象设置响应信息。
- 作用:设置响应内容
知识点-操作响应行
1.目标
- 掌握操作响应行的方法
2.讲解
响应行
HTTP/1.1 200
响应头
响应体
常用的状态码:
200:请求成功
404:请求资源不存在 【请求地址写错】
500:服务器内部错误 【java代码报错】
302:重定向
304:读取缓存数据
403:请求禁止 没有权限访问
406:请求和响应的内容不一致
3.小结
-
设置的API: response.setStatus(int code);
-
http状态码
- 200:成功
- 404:请求资源不存在
- 500:服务器内部错误
知识点-操作响应头【重点】
1.目标
- 掌握操作响应头的方法, 能够进行定时刷新和重定向
2.路径
- 操作响应头的API介绍
- 定时刷新
- 重定向
3.讲解
3.1操作响应头的API
响应头: 是服务器指示浏览器去做什么
一个key对应一个value
一个key对应多个value
关注的方法: setHeader(String name,String value);
常用的响应头
Refresh:定时跳转 (eg:服务器告诉浏览器5s之后跳转到百度)
Location:重定向地址(eg: 服务器告诉浏览器跳转到xxx)
Content-Disposition: 告诉浏览器下载
Content-Type:设置响应内容的MIME类型(服务器告诉浏览器内容的类型)
3.2定时刷新
response.setHeader("refresh","秒数;url=跳转的路径"); //几秒之后跳转到指定的路径上
response.setHeader("refresh","5; url=http://www.baidu.com");
3.3 重定向【重点】
response.sendRedirect("demo09");
package com.itheima.web.response;
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;
/**
* 重定向 客户端请求response02,被重定向到response03
*/
@WebServlet("/response02")
public class ResponseServlet02 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ResponseServlet02...");
//重定向实现方式一:
//设置响应码
//response.setStatus(302);
//设置响应头
//response.setHeader("location","response03");
//重定向实现方式二: response.sendRedirect("新的地址");
//response.sendRedirect("response03");
//重定向访问外部资源
//response.sendRedirect("http://www.baidu.com");
//使用绝对路径重定向
response.sendRedirect("/day23/response03");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- 重定向
response.sendRedirect("重定向的路径");
特点:
1. 重定向地址栏发送改变
2. 重定向发生了两次请求
3. 重定向不能访问WEB-INF下的资料,并且请求数据会丢失
4. 重定向可以访问外部资源
5. 重定向一般使用绝对路径,如果是同一个项目内的资源,可以使用相对路径。
4.小结
4.1操作响应头
response.setHeader(String name,String value)
4.2重定向
重定向 :服务端让客户端重新发送一次请求
实现:response.sendRedirect("重定向地址");
转发和重定向的区别 【forward和redirect的区别?】:
1. 转发发送一次请求,地址栏不发生改变;重定向发送两次请求,地址栏发送改变
2. 转发请求信息不会丢失;重定向请求信息会丢失
3. 转发只能请求服务器内部资源;重定向既可以请求服务器内部资源,又可以请求外部资源
4. 转发可以访问WEB-INF下的资源;重定向不行
5. 转发一般使用相对路径,重定向使用一般使用绝对路径
知识点-相对路径和绝对路径
讲解
相对路径:有参照物,根据当前位置进行参照选择资源
./:当前位置
../:上一级目录
eg:
index.html:<a href="request05">转发</a><br> :相对的就是当前页面 【静态资源】
ResponseDemo01:response.sendRedirect("response02"); :相对的是当前Servlet地址 【动态资源】
绝对路径:直接通过地址定位唯一资源
1. 以盘符开头的:D:\czbk\java119\day24-request&response
2. 以Http开头的:http://localhost:8080/day24/WEB-INF/a.html
相对路径
index.html:http://localhost:8080/day24/index.html
response01:http://localhost:8080/day24/response01
所以:这里 我从index.html页面跳转到response01的Servlet 使用相对路径 直接写response01就可以了
路径跳转加/: /表示的是绝对路径
前端加/: /加在前端代表的是服务器的地址:http://localhost:8080
后台加/: 注意这个地址给谁用:
如果是服务器使用【转发】,表示的就是当前应用地址:http://localhost:8080/day24
如果是给客户端用【重定向】,表示的就是服务器的地址:http://localhost:8080
一般情况下,项目中建议使用相对路径。
知识点-操作响应体
1.目标
- 掌握操作响应体以及响应乱码的解决
2.步骤
- 操作响应体的API介绍
- 响应乱码的解决
3.讲解
3.1操作响应体的API
页面输出只能使用其中的一个流实现,两个流是互斥的.
3.2响应乱码处理
- 解决字符流输出中文乱码问题
response.setContentType("text/html;charset=utf-8");
- 使用字节输出流输出中文乱码问题
//设置浏览器打开方式
response.setHeader("Content-type", "text/html;charset=utf-8");
//得到字节输出流
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write("你好".getBytes("utf-8"));// 使用平台的默认字符(utf-8)集将此 String 编码为 byte 序列
package com.itheima.web.response;
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;
/**
* 操作响应体
*/
@WebServlet("/response04")
public class ResponseServlet04 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ResponseServlet04...");
//设置响应内容的字符编码集
//response.setCharacterEncoding("UTF-8");
//服务器直接告诉浏览器我给你响应的内容 你应该使用什么字符集编码解析
response.setContentType("text/html;charset=UTF-8");
//以字符流的方式向客户端浏览器输出内容
//response.getWriter().print("Hello SZ118");
//response.getWriter().print("中国威武!");
//以字节流的方式向客户端浏览器输出内容
ServletOutputStream outputStream = response.getOutputStream();
//outputStream.write("Hello World!".getBytes());
outputStream.write("打倒小日本!".getBytes("UTF-8"));
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
4.小结
- 操作响应体
- 字符流输出:response.getWriter().print("...");
- 字节流输出:response.getOutPutStream.write(byte[]);
- 响应中文乱码
- 原因:内容在编码和解码时使用的字符编码集不一致导致。
- 解决:response.setContentType("text/html;charset=UTF-8");
案例-完成文件下载
1.需求分析
- 创建文件下载的列表的页面,点击列表中的某些链接,下载文件.
2.文件下载分析
2.1什么是文件下载
将服务器上已有的文件拷贝到本地(客户端)
IO流操作 response.getOutputStream()向客户端写入流
2.2文件下载的方式
-
第一种:超链接方式(不推荐)
链接的方式:直接将服务器上的文件的路径写到href属性中.如果浏览器不支持该格式文件,那么就会提示进行下载保存, 如果浏览器支持这个格式(eg: png, jpg....)的文件,那么直接打开,不再下载了
-
第二种:手动编码方式(推荐)
手动编写代码实现下载.无论浏览器是否识别该格式的文件,都会下载.
3.思路分析
3.1超链接方式
- 准备下载资源
- 编写下载页面 编写a标签
- 浏览器访问下载
3.2编码方式
3.2.1手动编码方式要求
设置两个头和一个流
设置的两个头:
Content-Dispostion: 服务器告诉浏览器去下载
Content-Type: 告诉浏览器文件类型.(MIME的类型)
设置一个流:
获得要下载的文件的输入流.
3.2.2思路
- 处理请求响应中文乱码
- 获取要下载的文件名称
- 使用ServletContext对象获取要下载文件的字节输入流
- 设置响应头,告诉浏览器执行下载操作
- 设置响应头,告诉浏览器要下载的文件类型
- 使用response以字节流的方式将下载文件内容输出到客户端浏览器
4.代码实现
package com.itheima.web.response;
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.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.处理请求响应中文乱码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 1.获取请求参数 【要下载的文件名称】
String filename = request.getParameter("filename");
// 2.获取要下载文件的字节输入流
InputStream inputStream = this.getServletContext().getResourceAsStream("download/" + filename);
// 3.设置响应头 告诉浏览器你要下载
//防止下载文件 文件名称中文乱码显示不正常 所以对文件名进行编码
//目前主流浏览器默认的编码解码方式使用的是UTF-8
System.out.println("编码前:"+filename);
filename = URLEncoder.encode(filename,"UTF-8");
System.out.println("编码后:"+filename);
response.setHeader("Content-Disposition","attachment;filename="+filename);
// 4.设置响应头 告诉浏览器 我给你下载的文件类型
String mimeType = this.getServletContext().getMimeType(filename);
response.setHeader("Content-Type",mimeType);
// 5.使用response将文件的字节输入流输出到客户端浏览器
ServletOutputStream outputStream = response.getOutputStream();
byte[] b = new byte[1024];
int i = -1;
while((i=inputStream.read(b))!=-1){
outputStream.write(b,0,i);
}
inputStream.close();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
5.细节处理
- 告诉浏览器设置的响应头里面不支持中文的, 抓包来看:
-
解决方案: 手动进行编码再设置进去就ok了
filename = URLEncoder.encode(filename,"UTF-8");
第三章-综合案例
案例-注册
1. 需求
说白了:就是向数据库中插入一条用户记录
2. 路径
- 完成注册功能
3. 代码实现
3.2 完成注册案例
3.2.1准备工作
- 数据库
create database day24;
use day24;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(40) DEFAULT NULL,
`password` varchar(40) DEFAULT NULL,
`address` varchar(40) DEFAULT NULL,
`nickname` varchar(40) DEFAULT NULL,
`gender` varchar(10) DEFAULT NULL,
`email` varchar(20) DEFAULT NULL,
`status` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
- JavaBean
public class User implements Serializable{
private Integer id;
private String username;
private String password;
private String address;
private String nickname;
private String gender;
private String email;
private String status;
//...
}
- 导入jar
- 工具类和配置文件
- register.html
3.2.2 注册案例思路
3.2.3 注册案例实现
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//0.中文乱码处理
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 1.获取请求参数【注册用户信息】
Map<String, String[]> parameterMap = request.getParameterMap();
// 2.使用BeanUtils将参数封装到user对象中 map的key要和java对象的属性一致
User user = new User();
BeanUtils.populate(user,parameterMap);
// 3.将注册用户信息插入到数据库
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "insert into user values(null,?,?,?,?,?,?,?)";
int rows = queryRunner.update(sql,user.getUsername(),user.getPassword(),user.getAddress(),user.getNickname(),user.getGender(),user.getEmail(),user.getStatus());
// 4.响应 根据插入数据返回的受影响的行数判断
// 如果rows>0 注册成功// 否则 注册失败
if(rows>0){
response.getWriter().print("注册成功!");
}else{
response.getWriter().print("注册失败!");
}
} catch (Exception e) {
e.printStackTrace();
response.getWriter().print("服务器异常!");
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
4. 小结
- 注册:本质就是向数据库中插入一条数据
- 思路:
- 获取请求参数
- 将注册信息插入数据库
- 根据处理结果进行响应
案例-登录
1.需求
- 点击登录按钮, 进行登录. 查询数据库中是否存在对应的一条记录!
- 登录成功,显示login Success
- 登录失败,显示login failed
2.思路
3.代码实现
3,1准备工作
- 页面的准备 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
</head>
<body>
<center>
<h1>用户登录</h1>
<form action="login" method="post">
姓名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="登录"/>
</form>
</center>
</body>
</html>
3.2代码实现
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//1.获取请求参数【用户名和密码】
String username = request.getParameter("username");
String password = request.getParameter("password");
//2.查询数据库 返回user对象
QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
String sql = "select * from user where username=? and password=?";
User user = queryRunner.query(sql, new BeanHandler<>(User.class), username, password);
//3.响应 user!=null表示用户存在 登录成功 ;user==null表示用户不存在 登录失败
if(user!=null){
response.getWriter().print("登录成功!");
}else{
response.getWriter().print("登录失败!");
}
} catch (Exception e) {
e.printStackTrace();
response.getWriter().print("服务器异常!");
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
4.小结
- 登录:根据用户名和密码去查询数据库 看是否存在一条用户记录
- 思路:
- 获取请求参数
- 根据用户名密码查询数据库
- 根据返回的user对象 user==null 表示登录失败 user!=null 表示登录成功
总结
-
request
-
概念:request用来封装请求信息
-
体系结构:HttpServletRequest-继承->ServletRequest
-
request对象来源:由服务器tomcat创建并传入Servlet
-
作用:操作请求信息、请求转发、作为域对象存储数据
-
操作请求行
// 获取请求方式 get|post request.getMethod(); // 获取请求地址URI(不包含主机ip地址和端口号) request.getRequestURI(); // 获取项目的虚拟路径 eg:/day24 request.getContextPath();
-
操作请求头
// 获取客户端浏览器信息 为了解决浏览器兼容性 request.getHeader("User-Agent"); // 获取进入当前资源的上一个地址 作用:防盗链 request.getHeader("Referer");
-
操作请求体【获取请求参数 重点】
// 获取单个值 request.getParameter("name属性值"); // 获取多个值 request.getParameterValues("name属性值"); // 获取全部请求参数 并封装到Map集合 参数名称作为key 参数值作为value request.getParameterMap(); // 请求中文乱码处理 request.setCharacterEncoding("UTF-8"); // 使用BeanUtils封装请求信息到javabean BeanUtils.populate(javabean名称,参数map集合);
-
请求转发
request.getRequestDispatcher("转发的地址").forward(request,response);
-
作为域对象存储数据
// request域对象存储数据有效范围:一次请求中 // 使用场景:转发中使用 //存 request.setAttribute(String key,Object value); //取 request.getAttribute(String key); //删 request.removeAttribute(String key);
-
-
response
-
response:封装响应信息
-
体系结构:HttpServletResponse-继承->ServletResponse
-
response来源:由服务器tomcat创建 并传入到Servlet中
-
作用:操作响应信息
-
操作响应行 setStatus(int statusCode);
-
操作响应头
// 定时刷新 response.setHeader("Refresh","5; url=http://www.baidu.com"); // 重定向 response.sendRedirect("重定向的地址"); // 告诉浏览器下载 response.setHeader("Content-Disposition","attachment;filename="+filename); // 告诉浏览器下载的文件类型 response.setHeader("content-type",mimeType);
-
操作响应体
// 处理响应中文乱码 response.setContentType("text/html;charset=UTF-8"); // 输出字符流到客户端浏览器 response.getWriter.print("输出内容"); // 输出字节流到客户端浏览器 response.getOutputStream.write("输出内容");
-