HTTP 和Request 和Response 及ServletContext 对象
HTTP 协议
HTTP 协议:请求消息和响应消息
请求消息:客户端发送给服务器端的数据
响应消息:服务器端发送给客户端的数据
概念:Hyper Text Transfer Protocol 超文本传输协议
传输协议:定义了,客户端和服务器端通信时,发送数据的格式
特点:
- 基于
TCP/IP 高级协议 - 默认端口号:
80 - 基于请求/响应模型的:一次请求对应一次响应
- 无状态的:每次请求之间相互独立,不能交互数据<
历史版本:
- 1.0:每一次请求响应都会建立新的连接
- 1.1:复用连接
请求消息数据格式
请求消息数据格式有四种:
- 请求行
- 请求头
- 请求空行
- 请求体(请求正文)
1.请求行[记住]
-
? 请求格式:请求方式 + 请求的url + 请求协议/版本号 ? 例如:GET /login.html HTTP/1.1 -
请求方式: ? HTTP 协议有7种请求方式:常用的有2种
GET
- 语法参数在请求行中【其实就是在
url 后跟着参数】 - 请求的
url 长度有限制 - 不太安全
POST
- 请求参数在请求体中
- 请求的
url 长度没有限制的 - 相对安全
请求行的格式:请求方式+url+版本号
请求 URL: http://localhost:8080/javaweb01_war_exploded/httpSer1
请求方法: GET
2.请求头:客户端浏览器告诉服务器一些信息
? 请求头名称:请求头值【键值对形式】
? 常见的请求头:
? 1.User-Agent :浏览器告诉服务器,访问使用浏览器版本信息
? 可以在服务器端获取该头信息,解决浏览器的兼容问题
? 2.Referer :http://localhost/login.html
? 告诉服务器:请求是从哪里来“
? Referer 两个作用:1.防盗链接 2.统计工作
Host: localhost 主机号【IP】
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101
Firefox/60.0 说明浏览器的信息
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
说明能解析的格式
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 说明直接的语言
Accept-Encoding: gzip, deflate 说明压缩包方式
Referer: http://localhost/login.html 告知浏览器请求从哪里来
Connection: keep-alive 说明联接方式一起活着,利用联接
Upgrade-Insecure-Requests: 1
3.请求空行
? 空行:就是用于分割请求头和请求体的
4.请求体(正文)
? 封装post 请求消息的请求参数的【注意是:get 请求是没有请求体的】
referer 的作用 防止盗链接
响应消息数据格式【重点】
响应消息:服务器端发送给客户端的数据
数据格式
1.响应行
1.组成:协议/版本 响应状态码 状态码描述
2.响应状态码:服务器告诉客户端浏览器在本次请求和响应的一个状态
1.状态码都是由3位数字组成
2.分类:
1. 1XX :服务器就收客户端消息,但是没有接受完成,等待一段时间后,发送1XX多状态码
2. 2XX:成功 代表有:200
3. 3XX:重定向:代表有:302(重定向) 304(访问缓存)
4. 4XX:客户端错误:代表有
*404(请求路径没有对应的资源)
*405(请求方式没有对应的doXXX方法)
5. 5XX:服务器端错误 代表有:500(服务器内部出现异常)
案例:HTTP/1.1 200 OK
2.响应头
1.格式: 头名称 : 值
2.常见的响应头:
1.Content-Type: 服务器告诉客户端本次响应体数据格式以及编码格式,否则文件可能打不开
2.Content-disposition:服务器告诉客户端以什么格式打开响应体数据
值:
in-line:默认值,在当前页面内打开
attachment;filename=xxx;以附件形式打开响应体。文件下载【重点】
案例:
Content-Type: text/html;charset=UTF-8 【重要的响应头】
Content-Length: 101
Date: Wed, 06 Jun 2018 07:08:42 GMT
content-Type 响应头是告诉服务器数据格式和编码格式,content-disposition 告诉客户端以什么格式打开响应体数据
3.响应空行
4.响应体
案例:
<html>
<head>
<title>$Title$</title>
</head>
<body>
hello , response
</body>
</html>
响应字符串格式
响应行
HTTP/1.1 200 OK
响应头
Content-Type: text/html;charset=UTF-8
Content-Length: 101
Date: Wed, 06 Jun 2018 07:08:42 GMT
响应体
<html>
<head>
<title>$Title$</title>
</head>
<body>
hello , response
</body>
</html>
Request
Request 对象和Response 对象的执行原理
request 对象和response 对象是由服务器创建的,我们来使用即可request 对象:是来获取请求信息response 对象:是来设置响应信息
Request对象和Response对象的执行原理:
1.用户请求服务器(请求时,会携带着请求数据),服务器会根据url创建请求对象
2.web服务器,同时会创建request对象和response对象,request对象中封装请求消息数据
3.web服务器将request对象和response对象传入service方法,并且调用service方法
4.我们可以通过request对象获取请求消息数据,通过response对象设置响应消息数据
5.服务器在给浏览器做出响应之前 ,会从response对象中获取设置响应消息数据
request 对象继承体系结构
在HttpServletRequest 有一个实现类:【这个类是由于web 服务器创建的】
org.apache.catalina.connector.RequestFacade
request 功能【其实就是获取数据】【重点】
获取请求信息功能
获取数据其实就是HTTP 协议的请求信息【注意没有获取空行,因为没有意思】
1.获取请求行数据
请求行的格式:请求方式 + url + 版本号
例如:GET 方式: GET /day14/demo1?name=zhangsan HTTP/1.1
方法:
1. 获取请求方式 :GET
* String getMethod()
2. (重点)获取虚拟目录:/day14
* String getContextPath()
3. 获取Servlet路径【获取资源路径】: /demo1
* String getServletPath()
4. 获取get方式请求参数:name=zhangsan
* String getQueryString()
5. (重点)获取请求URI:/day14/demo1
* String getRequestURI(): /day14/demo1
* StringBuffer getRequestURL() :http://localhost/day14/demo1
* URL:统一资源定位符 : http://localhost/day14/demo1 中华人民共和国【只代表一个国家,所以范围小】
* URI:统一资源标识符 : /day14/demo1 共和国【代表以共和国结尾的国家,范围大】
6. 获取协议及版本:HTTP/1.1
* String getProtocol()
7. 获取客户机的IP地址:
* String getRemoteAddr()
注意是:URI 的范围比 URL 要大
重点方法:getContextPath() 和getRequestURI() 和getRequestURL()
上述方法的演示:重点方法是:****String getContextPath() 和String getRequestURI() 和StringBuffer getRequestURL()
@WebServlet(urlPatterns = {"/request1"} )
public class RequestMethod extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
System.out.println("请求方法是:"+method);
System.out.println("======================");
String contextPath = req.getContextPath();
System.out.println("获取虚拟目录路径:"+contextPath);
String servletPath = req.getServletPath();
System.out.println("获取资源路径:"+servletPath);
String queryString = req.getQueryString();
System.out.println("获取请求参数:"+queryString);
String requestURI = req.getRequestURI();
System.out.println("获取请求的url路径:"+requestURI);
StringBuffer requestURL = req.getRequestURL();
System.out.println("获取请求的url路径:"+requestURL);
String protocol = req.getProtocol();
System.out.println("获取HTTP协议的版本号:"+protocol);
String remoteAddr = req.getRemoteAddr();
System.out.println("获取客户的IP地址:"+remoteAddr);
}
}
2.获取请求头
获取请求头中值方法:
重点方法:String getHeader(String name); //传入请求头名称
1.重点:获取指定请求头的名称来获取请求头对应的值
String getHeader(String name);
2.了解:获取所有的请求头的名称
Enumeration<String> getHeaderNames();
案例:
@WebServlet(urlPatterns = {"getHead1"})
public class RequestGetHeader extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()){
String name = headerNames.nextElement();
String header = req.getHeader(name);
System.out.println(header);
}
}
}
获取指定名称的请求头
@WebServlet("/requestDemo3")
public class RequestDemo3 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String agent = request.getHeader("user-agent");
if(agent.contains("Chrome")){
System.out.println("谷歌来了...");
}else if(agent.contains("Firefox")){
System.out.println("火狐来了...");
}
}
}
请求referer的作用【也是获取指定的请求头】
@WebServlet("/requestDemo4")
public class RequestDemo4 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String referer = request.getHeader("referer");
System.out.println(referer);
if(referer != null ){
if(referer.contains("/day14")){
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("播放电影....");
}else{
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("想看电影吗?来优酷吧...");
}
}
}
}
3.获取请求体(请求正文)
请求体:只有POST 请求方式,才有请求体,在请求体中封装了POST 请求的参数
获取请求体中的参数步骤:
-
获取流对象 获取流对象的两种方法:
1.获取字符输入流的方式,只可以操作字符类型的数据
BufferedReader getReader();
2.获取字节输入流,可以操作所有类型数据
ServletInputStream getInputStream();
-
设置获取的字符集防止中文乱码问题 req.setCharacterEncoding("utf-8");
-
再从流对象中拿数据
案例:
@WebServlet(urlPatterns = {"/register1"})
public class RequestBody extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
BufferedReader br = req.getReader();
String line = "";
while ((line=br.readLine())!=null){
System.out.println(line);
}
}
}
上述获取请求信息方法中只有三个方法是重点的
getContextPath() :获取虚拟目录
getServletPath() :获取资源路径
getRequestURI() 或getRequestURL() :获取请求的URI路径
其他通用方法【重点的】
1.获取请求参数通用方式:不论是get 还post 请求方式都可以使用下列方法来获取请求的参数
1.根据参数名称获取参数值 【username=海康】可以传入username返回:海康
String getParameter(String var1);
2.获取所有请求的参数名称
Enumeration<String> getParameterNames();
3.根据参数名称获取参数值的数组【Address=海康&Address=湛江】可以传入Address 返回:海康,湛江的字符串数组
String[] getParameterValues(String var1);
4.获取所有参数的map集合【键是请求头名,值就是对象请求的值】【注意一般使用在封装JAVABean对象时,使用,传入获取的Map集合】
Map<String, String[]> getParameterMap();
中文乱码问题:
1.get 方式:tomcat8 版本已经将get 方式乱码问题解决了
2.post 方式:会出现中文乱码问题
解决方案就是:在获取参数前调用requeat 对象中的setCharacterEncoding("编码方式") 方法
注意是:编码方式一定要提交的编码一致,如果提交的表单是utf-8 设置就是utf-8
req.setCharacterEncoding("utf-8");
案例:
@WebServlet(urlPatterns = {"/parameter1"})
public class RequestParameter extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
System.out.println("根据参数名获取对应的参数值:"+username);
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()) {
System.out.println("获取所有的参数名称:" + parameterNames.nextElement());
}
String[] hobbys = req.getParameterValues("hobby");
for (String hobby:
hobbys) {
System.out.println(hobby);
}
Map<String, String[]> parameterMap = req.getParameterMap();
System.out.println("根据参数Map集合:"+parameterMap);
Set<String> strings = parameterMap.keySet();
for (String key:
strings) {
String[] values = parameterMap.get(key);
for (String value:
values) {
System.out.println(value);
}
}
}
}
2.请求转发: 一种在服务器内部的资源跳转方式
注意是:请求转发不需要写入项目的路径【就是虚拟路径】,就是只能跳转到该项目中存在的资源路径
使用步骤:
- 通过
request 对象中的getRequestDispatcher(String path[传入跳转路径]) 方法,返回一个RequestDispatcher 对象 - 使用
RequestDispatcher 对象来进行转发的方法:forward(ServletRequest request,ServletResponse response) 方法,进行跳转
请求转发的特点【面试问题】
- 浏览器地址栏路径不发生改变【就是浏览器中的
url 不改变】 - 只能转发到当前服务器内部资源中【就是只能跳转到该项目中存在的资源路径】
- 转发只会对服务器请求一次
@WebServlet(urlPatterns = {"/forward1"})
public class RequestForward1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("哈哈 请求转发forward1执行了");
req.getRequestDispatcher("/forward2").forward(req,resp);
}
}
@WebServlet(urlPatterns = {"/forward2"})
public class RequestForward2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("哈哈 请求转发forward2执行了");
}
}
共享数据[重点]
- 域对象:一个作用范围的对象,可以在范围内共享数据【意思就是说:request对象可以在一次请求中被多个资源所有共享】
request 域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
共享数据方法:
void setAttribute(String name,Object obj);存储数据
Object getAttribute(String name);通过键获取值
void removeAttribute(String name);通过键移除键值对
案例:
@WebServlet(urlPatterns = {"/forward1"})
public class RequestForward1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("哈哈 请求转发forward1执行了");
req.setAttribute("username","海康");
req.getRequestDispatcher("/forward2").forward(req,resp);
}
}
@WebServlet(urlPatterns = {"/forward2"})
public class RequestForward2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("哈哈 请求转发forward2执行了");
Object user = req.getAttribute("username");
System.out.println(user);
req.removeAttribute("username");
}
}
获取ServletContext 对象
概念:代表整个web 应用,可以和web 服务器(容器)来通信
获取ServletContext 对象方法:
方式一:通过request对象获取
ServletContext getServletContext();
方式二:通过HttpServlet获取
this.getServletContext();
上述两种方式获取的对象是同一个的,因为代表的是web 服务器的启动时,创建的,可以理解为只能一个
案例:
@WebServlet(urlPatterns = "/servletContext")
public class ServletContext1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
ServletContext servletContext1 = this.getServletContext();
System.out.println(servletContext);
System.out.println(servletContext1);
System.out.println(servletContext==servletContext1);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
功能
1.获取MIME 类型
设置文件的数据类型,告知浏览器以什么方式解析
MIME类型:在互联网通信过程中定义的一种文件数据类型
格式:大类型/小类型 如: text/html image/jpeg
获取:String getMimeType(String fileName);
获取MIME 步骤:
- 获取
ServletContext 对象 - 调用
ServletContext 对象中的getMimeType(String fileName);
案例:
@WebServlet(urlPatterns = "/servletContext2")
public class ServletContext2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
String fileName = "a.html";
String mimeType = servletContext.getMimeType(fileName);
System.out.println(mimeType);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
2.域对象:共享数据
注意:ServletContext 对象范围是代表web 服务器启动时创建,说明是所有用户所有请求共享的,这三个方法和request对象中的方法一样,只是对象操作及作用域不同这是与request 对象的区别之处
共享数据有三个方法
1. setAttribute(String name,Object value)
2. getAttribute(String name)
3. removeAttribute(String name)
这三个方法和request对象中的方法一样,只是对象操作不同
3.获取文件的真实(服务器)路径
项目的存在路径
E:\IDEACODE\javawebCOde\out\artifacts\javaweb01_war_exploded 项目的真实路径
IDEA 会为每一个tomcat 部署的项目单独建立一份配置文件 "C:\Users\360\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\f6591a51-1f9e-46f0-a5ac-fc8bfa7a47a5"
其实就是服务器部署项目的路径
步骤:
- 获取
ServletContext 对象 - 使用
String getRealPath(String path); 的方法获取
资源的文件存在有三种情况:
1.存放在web目录下
String path = getRealPath("/文件名");
2.存放在WEB-INF目录下资源访问下
String path = getRealPath("/WEB-INF/文件名");
3.存放在src目录下资源访问下
String path = getRealPath("/WEB-INF/classes/文件名");
注意是:使用类加载器的方式获取文件的路径,只能获取src 下的文件,不能获取web 目录下的,例如:JDBCUtils.class.getClassLoader().getResource("druid.properties").getPath();
@WebServlet(urlPatterns = "/servletContextPath")
public class ServletContextPath extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
String a = servletContext.getRealPath("/a.txt");
System.out.println(a);
System.out.println("===============================");
String b = servletContext.getRealPath("/WEB-INF/b.txt");
System.out.println(b);
System.out.println("===============================");
String c = servletContext.getRealPath("/WEB-INF/classes/c.txt");
System.out.println(c);
}
}
BeanUtils 工具类,简化数据封装【重点】
注意是要使用apache 提交的jar
用于封装JavaBean 的:一般使用在表单提交了数据,使用于封装数据
1.JAVABean :标准的JAVA 类
- 要求
- 类必须被
public 修饰 - 必须提供空参的构造器
- 成员变量必须使用
private 修饰 - 对成员变量提供公共的
setter 方法和getter 方法 - 功能是封装数据
成员变量和属性的概念
成员变量:就是例如下面的id name password
private int id;
private String name;
private String password;
属性:setter 和getter 方法截取后的产物
例如:getId() ---> Id ---> id ==> id就是属性
属性不一定等于成员变量
使用的步骤
- 导入相关的
jar 包commons-beanutils-1.8.0 是apache 提供的 - 调用方法,传入指定的参数
案例:
@WebServlet(urlPatterns = {"/login"})
public class Login extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
User user = new User();
Map<String, String[]> parameterMap = req.getParameterMap();
try {
BeanUtils.populate(user,parameterMap);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
BeanUtils 中的三个重点方法:
-
public static void setProperty(Object bean, String name, Object value);第一参数传入JAVABEAN实体[就是java类和上述的user类一样],第二参数传入javabean中成员变量名,第三参数传入要给javabean成员变量赋值的值
-
public static void getProperty(Object bean, String name);第一参数是传入javabean实体[就是java类和上述的user类一样],第二参数是传入Javabean中成员变量名
-
public static void populate(Object bean, Map properties);第一个参数传入javabean实体[就是java类和上述的user类一样],第二参数传入表单中获取的参数封装的MAP集合
最重要的方法:populate(Object obj,Map properties)
Response 对象功能
功能:设置响应消息
1.设置响应行
? 格式:HTTP/1.1 200 OK
? 设置状态码:setStatus(int sc)
2.设置响应头[重点]
setHaeder(String name,String value);设置响应头
3.设置响应体
使用步骤
-
获取输出流 字符输出流:PrintWriter getWriter();
-
字节输出流 ServletOutputStream getOutputStream();
重定向
重定向:资源跳转的方式
步骤:
- 设置状态码为:
302 - 设置响应头:
location:重定向的路径【项目路径+资源路径】
面试题:转发forward 和重定向redirect 的特点【或区别】
重定向:
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求,不能使用
request 对象来共享数据
转发:
- 地址栏不发生变化
- 转发只能访问当前服务器下的资源
- 转发是一次请求,可以使用
request 对象来共享数据
实现重定向的两种方法
方式一:
1.调用response方法中的setStatus(302);方法传入参数是302
2.调用response方法中的setHeader("location","重定向路径");方法的第一参数传入`location`,第二参数传入路径路径【项目路径+资源路径】
方式二:直接调用response方法中的sendRedirect("重定向路径");
void sendRedirect(String var1) throws IOException;
案例:
@WebServlet(urlPatterns = {"/response1"})
public class ResponseServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/javaweb01_war_exploded/response2");
}
@WebServlet(urlPatterns = {"/response2"})
public class ResponseServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("重定向过来的,呵呵。。。");
}
路径写法
分类:相对路径和绝对路径【注意:一般在jsp 中不推荐使用相对路径,推荐使用绝对路径】
相对路径:通过相对路径不可以确定唯一资源
如:./index.html
不以`/`开头,以`.`开头路径
规则是:找到当前资源和目标资源之间的相对位置关系
`./` : 当前目录【如果是当前目录`./`可以不写】
`../` : 后退一级目录【也就是父级目录】
重点:绝对路径:通过绝对路径可以确定唯一之间的相对位置关系
如: 如:http://localhost/day15/responseDemo2
以/开头的路径
规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
1.给客户端浏览器使用,需要加虚拟目录(项目的访问路径)
建议虚拟目录动态获取:`request.getContextPath();
注意是:由于客户端访问服务器时,需要加虚拟目录,在后端代码中,虚拟目录要使用`request.getContextPath();`动态获取
例如: <a> <form> 重定向【重定向需要加虚拟目录】
2.给服务器使用:不需要加虚拟目录【项目目录】
例如:转发请求【转发路径】
服务器输出字符数据到浏览器
使用的步骤:
- 设置服务器告知客户端浏览器的字符集【注意一定要在获取前设置,否则不起作用】
- 获取字符输出流
- 输出数据
方式一:
设置获取输出流的字符集:注意由于输出流的默认字符集是ISO-8859-1,可以设置为浏览器使用的默认字符集【但是不同用户使用浏览器使用的字符集是不同的,所以这种方式解决不合适】
resp.setCharacterEncoding("gbk");
void setCharacterEncoding(String var1);
方式二:通过设置响应头, 但是每次第一个参数都是固定的,所以 Response对象提供了简化的方法:如方式三:
resp.setHeader("Content-Type","text/html;charset=UTF-8");
void setHeader(String var1, String var2);
方式三:
resp.setContentType("text/html;charset=utf-8");
void setContentType(String var1);
步骤二和三:
// 获取输出流
PrintWriter writer = resp.getWriter();
// 输出内容
writer.write("您好:湛江!");
案例:
@WebServlet(urlPatterns = {"/responseOutPut1"})
public class ResponseOutPut1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.write("您好:湛江!");
}
}
服务器输出字节数据到浏览器
使用步骤:
- 设置服务器告知客户端浏览器的字符集【注意一定要在获取前设置,否则不起作用】
- 获取字符输出流
- 输出数据
方式一:
设置获取输出流的字符集:注意由于输出流的默认字符集是ISO-8859-1,可以设置为浏览器使用的默认字符集【但是不同用户使用浏览器使用的字符集是不同的,所以这种方式解决不合适】
resp.setCharacterEncoding("gbk");
void setCharacterEncoding(String var1);
方式二:通过设置响应头, 但是每次第一个参数都是固定的,所以 Response对象提供了简化的方法:如方式三:
resp.setHeader("Content-Type","text/html;charset=UTF-8");
void setHeader(String var1, String var2);
方式三:
resp.setContentType("text/html;charset=utf-8");
void setContentType(String var1);
案例:
@WebServlet(urlPatterns = {"/responseOutPut2"})
public class ResponseOutPut2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
ServletOutputStream os = resp.getOutputStream();
os.write("您好:海康!".getBytes(StandardCharsets.UTF_8));
}
}
验证码:本质是图片
验证码的作用:防止恶意的注册
画出验证码的步骤:
1.创建一个对象,在内存中图片【验证码图片对象】
2.美化图片
3.将图片输出到页面展示
案例:
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100;
int height = 50;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.setColor(Color.PINK);
g.fillRect(0,0,width,height);
g.setColor(Color.BLUE);
g.drawRect(0,0,width - 1,height - 1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
Random ran = new Random();
for (int i = 1; i <= 4; i++) {
int index = ran.nextInt(str.length());
char ch = str.charAt(index);
g.drawString(ch+"",width/5*i,height/2);
}
g.setColor(Color.GREEN);
for (int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
window.onload = function(){
var img = document.getElementById("checkCode");
img.onclick = function(){
var date = new Date().getTime();
img.src = "/javaweb01_war_exploded/checkCodeServlet?"+ date;
}
}
window.onload = function () {
var a = document.getElementById("change");
a.onclick = function () {
var time = new Date().getTime();
window.location = "/javaweb01_war_exploded/checkCodeServlet?"+ time;
}
}
</script>
</head>
<body>
<img id="checkCode" src="/javaweb01_war_exploded/checkCodeServlet" />
<a id="change" href="/javaweb01_war_exploded/checkCodeServlet">看不清,换一张 </a>
</body>
</html>
文件下载
文件下载需求:
1.页面显示超链接
2.点击超链接后弹出下载提示框
3.完成图片文件下载
分析:
-
由于浏览器默认情况下如果被浏览器解析的文件,则在浏览器中展示,如果不能解析的文件,则弹出下载提示框,所以这不满足需求,我们需求是不管什么文件都需要提示有下载框 -
任何资源都必须提示下载框 -
使用响应头设置资源的打开方式 content-disposition:attchent;filename=xxx
步骤实现
- 定义一个页面,编辑超链接的
href 属性,传递资源名称fileName - 定义
Servlet 类
- 获取文件名称
- 获取
ServletContext 对象 - 获取文件的路径
- 使用字节流关联文件,加载文件进入内存中
- 获取文件的
mime 类型 - 设置文件
response 的响应头,类型为content-type - 设置文件的打开方式
- 写数据回页面
- 关闭流
核心两个步骤:1.设置响应头,就是设置文件的mime 类型 2.设置打开方式
核心步骤1:如果不设置文件的响应头,就会让文件在浏览器端可能打不开
核心步骤2:点击超链接时,提示下载
注意:在设置响应头时,必须先获取文件的mime 类型
上述文件下载存在中文文件名问题
解决方案:
-
获取客户端使用的浏览器版本信息 -
根据不同的版本信息,设置filename 编码方式不同
可以使用一个DownloadUtils 工具类来返回filename
String user_agent = req.getHeader("user-agent");
String fileName = DownLoadUtils.getFileName(user_agent, filename);
resp.setHeader("content-Disposition","attachment;fileName="+fileName);
需要引入下面代码
package cn.itcast.utils;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
案例:
@WebServlet(urlPatterns = {"/fileDownload"})
public class FileDownload extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String filename = req.getParameter("fileName");
System.out.println(filename);
ServletContext servletContext = req.getServletContext();
String filePath = servletContext.getRealPath("\\img\\" + filename);
System.out.println(filePath);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
String mimeType = servletContext.getMimeType(filename);
resp.setHeader("content-type",mimeType);
resp.setContentType(mimeType);
String user_agent = req.getHeader("user-agent");
String fileName = DownLoadUtils.getFileName(user_agent, filename);
resp.setHeader("content-Disposition","attachment;fileName="+fileName);
ServletOutputStream os = resp.getOutputStream();
int length = 0;
byte[] bytes = new byte[1024*8];
while ((length=bis.read(bytes))!=-1){
os.write(bytes,0,length);
}
if (bis!=null){
bis.close();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/javaweb01_war_exploded/fileDownload?fileName=rose.jpg">图片下载</a>
</body>
</html>
源码区
ServletRequest 源码
public interface ServletRequest {
Object getAttribute(String var1);
Enumeration<String> getAttributeNames();
String getCharacterEncoding();
void setCharacterEncoding(String var1) throws UnsupportedEncodingException;
int getContentLength();
String getContentType();
ServletInputStream getInputStream() throws IOException;
String getParameter(String var1);
Enumeration<String> getParameterNames();
String[] getParameterValues(String var1);
Map<String, String[]> getParameterMap();
String getProtocol();
String getScheme();
String getServerName();
int getServerPort();
BufferedReader getReader() throws IOException;
String getRemoteAddr();
String getRemoteHost();
void setAttribute(String var1, Object var2);
void removeAttribute(String var1);
Locale getLocale();
Enumeration<Locale> getLocales();
boolean isSecure();
RequestDispatcher getRequestDispatcher(String var1);
String getRealPath(String var1);
int getRemotePort();
String getLocalName();
String getLocalAddr();
int getLocalPort();
ServletContext getServletContext();
AsyncContext startAsync() throws IllegalStateException;
AsyncContext startAsync(ServletRequest var1, ServletResponse var2) throws IllegalStateException;
boolean isAsyncStarted();
boolean isAsyncSupported();
AsyncContext getAsyncContext();
DispatcherType getDispatcherType();
}
HttpServletRequest 源码
public interface HttpServletRequest extends ServletRequest {
String BASIC_AUTH = "BASIC";
String FORM_AUTH = "FORM";
String CLIENT_CERT_AUTH = "CLIENT_CERT";
String DIGEST_AUTH = "DIGEST";
String getAuthType();
Cookie[] getCookies();
long getDateHeader(String var1);
String getHeader(String var1);
Enumeration<String> getHeaders(String var1);
Enumeration<String> getHeaderNames();
int getIntHeader(String var1);
String getMethod();
String getPathInfo();
String getPathTranslated();
String getContextPath();
String getQueryString();
String getRemoteUser();
boolean isUserInRole(String var1);
Principal getUserPrincipal();
String getRequestedSessionId();
String getRequestURI();
StringBuffer getRequestURL();
String getServletPath();
HttpSession getSession(boolean var1);
HttpSession getSession();
boolean isRequestedSessionIdValid();
boolean isRequestedSessionIdFromCookie();
boolean isRequestedSessionIdFromURL();
boolean isRequestedSessionIdFromUrl();
boolean authenticate(HttpServletResponse var1) throws IOException, ServletException;
void login(String var1, String var2) throws ServletException;
void logout() throws ServletException;
Collection<Part> getParts() throws IOException, ServletException;
Part getPart(String var1) throws IOException, ServletException;
}
ServletResponse 源码
public interface ServletResponse {
String getCharacterEncoding();
String getContentType();
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentType(String var1);
void setBufferSize(int var1);
int getBufferSize();
void flushBuffer() throws IOException;
void resetBuffer();
boolean isCommitted();
void reset();
void setLocale(Locale var1);
Locale getLocale();
}
HttpServletResponse 源码
public interface HttpServletResponse extends ServletResponse {
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
void addCookie(Cookie var1);
boolean containsHeader(String var1);
String encodeURL(String var1);
String encodeRedirectURL(String var1);
@Deprecated
String encodeUrl(String var1);
@Deprecated
String encodeRedirectUrl(String var1);
void sendError(int var1, String var2) throws IOException;
void sendError(int var1) throws IOException;
void sendRedirect(String var1) throws IOException;
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
void setStatus(int var1);
@Deprecated
void setStatus(int var1, String var2);
int getStatus();
String getHeader(String var1);
Collection<String> getHeaders(String var1);
Collection<String> getHeaderNames();
default void setTrailerFields(Supplier<Map<String, String>> supplier) {
}
default Supplier<Map<String, String>> getTrailerFields() {
return null;
}
}
ServletContext 源码
public interface ServletContext {
String TEMPDIR = "javax.servlet.context.tempdir";
String ORDERED_LIBS = "javax.servlet.context.orderedLibs";
String getContextPath();
ServletContext getContext(String var1);
int getMajorVersion();
int getMinorVersion();
int getEffectiveMajorVersion();
int getEffectiveMinorVersion();
String getMimeType(String var1);
Set<String> getResourcePaths(String var1);
URL getResource(String var1) throws MalformedURLException;
InputStream getResourceAsStream(String var1);
RequestDispatcher getRequestDispatcher(String var1);
RequestDispatcher getNamedDispatcher(String var1);
Servlet getServlet(String var1) throws ServletException;
Enumeration<Servlet> getServlets();
Enumeration<String> getServletNames();
void log(String var1);
void log(Exception var1, String var2);
void log(String var1, Throwable var2);
String getRealPath(String var1);
String getServerInfo();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();
boolean setInitParameter(String var1, String var2);
Object getAttribute(String var1);
Enumeration<String> getAttributeNames();
void setAttribute(String var1, Object var2);
void removeAttribute(String var1);
String getServletContextName();
Dynamic addServlet(String var1, String var2);
Dynamic addServlet(String var1, Servlet var2);
Dynamic addServlet(String var1, Class<? extends Servlet> var2);
<T extends Servlet> T createServlet(Class<T> var1) throws ServletException;
ServletRegistration getServletRegistration(String var1);
Map<String, ? extends ServletRegistration> getServletRegistrations();
javax.servlet.FilterRegistration.Dynamic addFilter(String var1, String var2);
javax.servlet.FilterRegistration.Dynamic addFilter(String var1, Filter var2);
javax.servlet.FilterRegistration.Dynamic addFilter(String var1, Class<? extends Filter> var2);
<T extends Filter> T createFilter(Class<T> var1) throws ServletException;
FilterRegistration getFilterRegistration(String var1);
Map<String, ? extends FilterRegistration> getFilterRegistrations();
SessionCookieConfig getSessionCookieConfig();
void setSessionTrackingModes(Set<SessionTrackingMode> var1);
Set<SessionTrackingMode> getDefaultSessionTrackingModes();
Set<SessionTrackingMode> getEffectiveSessionTrackingModes();
void addListener(String var1);
<T extends EventListener> void addListener(T var1);
void addListener(Class<? extends EventListener> var1);
<T extends EventListener> T createListener(Class<T> var1) throws ServletException;
JspConfigDescriptor getJspConfigDescriptor();
ClassLoader getClassLoader();
void declareRoles(String... var1);
}
|