JavaWeb学习(二)之HTTP Servlet
推荐视频 B站:遇见狂神说JavaWeb视频:https://www.bilibili.com/video/BV12J411M7Sj
1、HTTP
1.1、什么是HTTP
HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
简单来说http就是一个简单的请求-响应协议。
工作原理如下
-
HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
-
Web服务器有:Apache服务器,IIS服务器(Internet Information Services)等。
-
Web服务器根据接收到的请求后,向客户端发送响应信息。
-
HTTP默认端口号为80,但是你也可以改为8080或者其他端口。
1.2、HTTP请求
客户端—发请求(Request)—服务器
菜鸟教程
例如360导航:
请求 URL: https://hao.360.com/ 请求地址
请求方法: GET get方法/post方法
状态代码: 200 / OK 状态码:200
1.3、请求行
- 请求行中的请求方式:GET
- 请求方式:Get,Post,HEAD,DELETE,PUT,TRACT…
- get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效。
1.4、消息头
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.
1.5、Http响应
- 服务器—响应-----客户端
百度:
Cache-Control:private 缓存控制
Connection:Keep-Alive 连接
Content-Encoding:gzip 编码
Content-Type:text/html 类型
1.5.1、响应体
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.
Refresh:告诉客户端,多久刷新一次;
Location:让网页重新定位;
1.5.2、响应状态码
200:请求响应成功 200
3xx:请求重定向
- 重定向:你重新到我给你新位置去;
4xx:找不到资源 404
- 资源不存在;
5xx:服务器代码错误 500 502:网关错误
2、Servlet
2.1、什么是servlet
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。我们可以这样理解Servlet是指Java语言实现的一个接口或者是实现了这个Servlet接口的类
2.2、第一个Servlet程序
第一步在 IDEA或者eclipse中创建一个web项目 这里以IDEA为例 下面提供两种创建web项目的方法
- 用Maven创建一个web项目 官网:https://maven.apache.org/ 在网上可以自己找教程下载配置maven
maven目录结构
项目建好后目录结构
2.用普通方法创建web项目
然后就在java目录下创建一个普通类 继承HttpServlet
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet方法开始启动");
PrintWriter writer = resp.getWriter();
writer.print("Hello world ----helloServlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
然后在web.xml中进行配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<!--注册Servlet-->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.song.servlet.HelloServlet</servlet-class> 继承HttpServlet类的路径
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/helloservlet</url-pattern>
</servlet-mapping>
</web-app>
然后就是index.jsp页面 里面的是前端的内容给用户看的 可以自己随便写
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
然后就是配置Tomact 若不会可以自己网上查
配置好后就可以启动呢
2.3、Servlet原理
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
2.4、ServletContext
一个web应用对应一个ServletContext,所以ServletContext的作用范围是整个应用,也就是说web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用 ;
来自于百度百科的图 这里先不用管Cookie和Session
-
ServletContext的作用是什么
作为域对象使用。
初始化参数。
请求转发。
读取资源文件。
-
共享数据
在A Servlet中保存数据 ,可以在B Servelt中获取A 当中存放在ServletContex中数据
//A Servlet public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //servlet上下文 ServletContext servletContext = this.getServletContext(); String username = "SC"; //将一个数据保存在servletContext中 名字为username 值为username servletContext.setAttribute("username",username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
//B Servlet public class GetServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); String username = (String) servletContext.getAttribute("username"); //解决中文乱码问题 resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); resp.getWriter().print("名字:"+username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> <servlet> <servlet-name>helloServlet</servlet-name> <servlet-class>com.song.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>helloServlet</servlet-name> <url-pattern>/helloservlet</url-pattern> </servlet-mapping> <servlet> <servlet-name>getServlet</servlet-name> <servlet-class>com.song.servlet.GetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>getServlet</servlet-name> <url-pattern>/getservlet</url-pattern> </servlet-mapping> </web-app>
-
获取初始化参数
<!--配置一些web应用初始化参数--> <context-param> <param-name>name</param-name> <param-value>vaule</param-value> </context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); //可以使用getServeltContext获取这个name 在配置中写的 String name = context.getInitParameter("name"); resp.getWriter().print(name); }
-
请求转发
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); System.out.println("HelloServelt2"); //RequestDispatcher requestDispatcher = context.getRequestDispatcher("/helloServelt"); //转发的请求路径 //requestDispatcher.forward(req,resp); //调用forward实现请求转发; context.getRequestDispatcher("/helloServelt").forward(req,resp); }
-
读取资源文件
假如说在你的javaweb项目中的resources中有一个properties 里面配置这一些属性 这时 我们可以通过ServletContext读取这个文件
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/song/servlet/db.properties"); Properties prop = new Properties(); prop.load(is); String user = prop.getProperty("username"); String pwd = prop.getProperty("password"); resp.getWriter().print(user+":"+pwd); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
2.5、HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;
-
如果要获取客户端请求过来的参数:找HttpServletRequest
-
如果要给客户端响应一些信息:找HttpServletResponse
以下为 HttpServletResponse 对象可以调用的方法 不要求全部掌握 若想详细了解这些方法 可以看菜鸡教程 以下表格方法引用于菜鸟教程
1 | String encodeRedirectURL(String url) 为 sendRedirect 方法中使用的指定的 URL 进行编码,或者如果编码不是必需的,则返回 URL 未改变。 |
---|---|
2 | String encodeURL(String url) 对包含 session 会话 ID 的指定 URL 进行编码,或者如果编码不是必需的,则返回 URL 未改变。 |
3 | boolean containsHeader(String name) 返回一个布尔值,指示是否已经设置已命名的响应报头。 |
4 | boolean isCommitted() 返回一个布尔值,指示响应是否已经提交。 |
5 | void addCookie(Cookie cookie) 把指定的 cookie 添加到响应。 |
6 | void addDateHeader(String name, long date) 添加一个带有给定的名称和日期值的响应报头。 |
7 | void addHeader(String name, String value) 添加一个带有给定的名称和值的响应报头。 |
8 | void addIntHeader(String name, int value) 添加一个带有给定的名称和整数值的响应报头。 |
9 | void flushBuffer() 强制任何在缓冲区中的内容被写入到客户端。 |
10 | void reset() 清除缓冲区中存在的任何数据,包括状态码和头。 |
11 | void resetBuffer() 清除响应中基础缓冲区的内容,不清除状态码和头。 |
12 | void sendError(int sc) 使用指定的状态码发送错误响应到客户端,并清除缓冲区。 |
13 | void sendError(int sc, String msg) 使用指定的状态发送错误响应到客户端。 |
14 | void sendRedirect(String location) 使用指定的重定向位置 URL 发送临时重定向响应到客户端。 |
15 | void setBufferSize(int size) 为响应主体设置首选的缓冲区大小。 |
16 | void setCharacterEncoding(String charset) 设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。 |
17 | void setContentLength(int len) 设置在 HTTP Servlet 响应中的内容主体的长度,该方法设置 HTTP Content-Length 头。 |
18 | void setContentType(String type) 如果响应还未被提交,设置被发送到客户端的响应的内容类型。 |
19 | void setDateHeader(String name, long date) 设置一个带有给定的名称和日期值的响应报头。 |
20 | void setHeader(String name, String value) 设置一个带有给定的名称和值的响应报头。 |
21 | void setIntHeader(String name, int value) 设置一个带有给定的名称和整数值的响应报头 |
22 | void setLocale(Locale loc) 如果响应还未被提交,设置响应的区域 |
23 | void setStatus(int sc) 为该响应设置状态码。 |
响应的状态码 建议去看菜鸟教程 自己去查找
2.5.1、下载文件
-
要获取下载文件的路径
-
下载的文件名是啥?
-
设置想办法让浏览器能够支持下载我们需要的东西
-
获取下载文件的输入流
-
创建缓冲区
-
获取OutputStream对象
-
将FileOutputStream流写入到buffer缓冲区
-
使用OutputStream将缓冲区中的数据输出到客户端!
public class DownServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 1. 要获取下载文件的路径 String realPath = "D:\\Java练习\\JavaWeb\\Javaweb-02-servlet\\response\\src\\main\\resources\\张三.png"; // 2. 下载的文件名是啥? String sub = realPath.substring(realPath.lastIndexOf("\\") + 1); // 3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码 resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(sub,"UTF-8")); // 4. 获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath); // 5. 创建缓冲区 int len = 0 ; byte buffer[] = new byte[1024]; // 6. 获取OutputStream对象 ServletOutputStream outputStream = resp.getOutputStream(); // 7. 将FileOutputStream流写入到buffer缓冲区 8. 使用OutputStream将缓冲区中的数据输出到客户端! while ((len = in.read(buffer))!=-1){ outputStream.write(buffer,0,len); } //9 . 关闭流资源 in.close(); outputStream.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
2.5.2、实现重定向
response.sendRedirect(url)使用指定的重定向位置 URL 发送临时重定向响应到客户端。
简单实现登录重定向
<%--${pageContext.request.contextPath}代表当前的项目--%>
<form action="${pageContext.request.contextPath}/login" method="get">
用户名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
<input type="submit">
</form>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理请求
String username = req.getParameter("username"); //通过getParameter获取前端表单的name和password
String password = req.getParameter("password");
resp.sendRedirect("/success.jsp"); //自己去写个success.jsp并且配置。。。注意路径问题 不要错呢
}
重定向和转发的区别?
相同点
- 页面都会实现跳转
不同点
- 请求转发的时候,url不会产生变化
- 重定向时候,url地址栏会发生变化;
2.6 、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息
HttpServletRequest对象可以调用的相关方法 去看菜鸟教程 这里就不写呢 菜鸟教程
获取参数,请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
System.out.println(req.getContextPath());
//通过请求转发
//这里的 / 代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
获取参数,请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
System.out.println(req.getContextPath());
//通过请求转发
//这里的 / 代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
如有错误 欢迎纠正哦