请求与相应
HTTP请求的结构
HTTP 请求包含三部分:请求行,请求头,请求体
POST请求方法有请求体,而GET则没有
示例程序如下:
RequestServlet类
package servlet;
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("/request")
public class RequestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("this is get method");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("this is post method");
}
}
input.html
Title
提交表单后跳转到页面:
通过Chrome开发者工具可以看到请求的具体信息:
修改表单的提交方式为POST
提交表单后发生页面跳转:
通过Chrome开发者工具可以看到请求的具体信息:
利用请求头开发多端应用
在请求头中,有一个key为User-Agent,我们可以通过获取User-Agent来让用户请求页面之后跳转到手机页面或者是PC页面,示例程序如下:
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("/user_agent")
public class UserAgentServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userAgent = request.getHeader("User-Agent");
response.setContentType("text/html;charset=utf-8");
String output = "";
if(userAgent.indexOf("Windows") != -1){
output = "这是Windows PC页面
";
}
if(userAgent.indexOf("iPhone") != -1 || userAgent.indexOf("Android") != -1){
output = "这是手机页面
";
}
response.getWriter().println(output);
}
}
在Windows操作系统上,访问页面:
使用Chrome开发者工具,将页面调成手机端,刷新页面:
所以,通过请求头的User-Agent可以将用户引导到适配的页面上。
响应的结构
HTTP响应包含三部分:响应行,响应头,响应体
HTTP响应行中包含报文的协议及版本信息,状态码以及状态描述,可以参考我的文章 浅谈HTTP
状态码其实大家都见过,而且最常见的应该就是404了吧。
想一想 当出现404页面的时候 上面说了些什么? 绝大部分是这句话:页面找不到了
其实可以这样理解:状态码就是服务器对浏览器说的话。
本小节会简单介绍一些常见的HTTP状态码。
在介绍常见的状态码前,先了解一下以这些数字开头的状态码代表什么含义
- 1xx : 信息响应(不常用)
- 2xx:成功
- 3xx:重定向
- 4xx:客户端错误
- 5xx:服务端错误
MDN:HTTP状态码
本文不会将所有的状态码全部介绍,仅会介绍常用的状态码 希望了解更多可点击上方MDN的链接
200
请求成功301
被请求的资源已永久移动到新位置,通常会发送HTTP Location来重定向到正确的新位置。返回301请求码进行跳转被Google认为是将网站地址由 HTTP 迁移到 HTTPS 的最佳方法302
请求的资源暂时驻留在不同的URI下面401
当前的请求需要进行用户的验证。403
403是HTTP协议中的一个状态码,可以理解为 没有权限访问此网站,服务器接收到了用户的请求,并理解了请求,但是拒绝为其提供服务404
HTTP 404 即 Not Found
请求所希望得到的资源未被在服务器上发现
通常是因为,用户所访问的网页已经被删除被移动 或从未存在。500
500状态码表示内部服务器错误,服务器遇到了不知道如何处理的情况。502
此错误响应表明服务器作为网关需要得到一个处理这个请求的响应,但是得到一个错误的响应。503
服务器没有准备好处理请求。 常见原因是服务器因维护或重载而停机。
常见的http状态码介绍完毕。
ContentType
ContentType决定浏览器采用何种方式对响应体进行处理
MIME类型 | 描述 |
---|---|
text/plain | 纯文本 |
text/html | HTML文档 |
text/xml | XML文档 |
application/x-msdownload | 需要下载的资源 |
image/jpeg,image/gif... | 图片资源 |
通过setContentType方法可以设置返回的响应文件的类型,例如:
response.setContentType("text/html;charset=utf-8");
这样响应的格式将被解析成HTML。
请求转发与重定向
请求转发与响应重定向的使用
多个Servlet(JSP)之间跳转有两种方式:
- 请求转发
request.getRequestDipatcher().forward()
- 响应重定向
response.sendRedirect()
示例程序:
请求转发
CheckLoginServlet类:
@WebServlet("/check_servlet")
public class CheckLoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 请求转发
request.getRequestDispatcher("/index_servlet").forward(request,response);
}
}
IndexServlet类:
@WebServlet("/index_servlet")
public class IndexServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().println("This is index page.");
}
}
在浏览器地址输入栏中输入URL:http://localhost:8080/servlet_advanced/check_servlet
,请求转发至IndexServlet处理:
可以看到页面跳转到了index page,但是URL并没有发生变化。
响应重定向
CheckLoginServlet类
@WebServlet("/check_servlet")
public class CheckLoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("/servlet_advanced/index_servlet");
}
}
注意,在重定向方法sendRedirect传入的路径需要添加项目的路径,在浏览器地址输入栏中输入URL:http://localhost:8080/servlet_advanced/check_servlet
。页面变化如下:
可以看到页面发生了跳转,并且URL也发生了变化。
请求转发与响应重定向的原理
请求转发
- 请求转发是服务器内部的跳转,也就是说只会产生一次请求
- 请求转发:
request.getRequestDispatcher().forward();
请求转发的示意图如下:
响应重定向
- 响应重定向是浏览器的跳转,会产生两次请求
- 响应重定向:
response.sendRedirect()
响应重定向的示意图如下:
设置请求自定义属性
- 请求允许创建自定义属性
- 设置请求属性:
request.setAttribute(属性名,属性值)
- 获取请求属性:
Object attr = request.getAttribute(属性名)
示例程序如下:
CheckLoginServlet类
@WebServlet("/check_servlet")
public class CheckLoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 请求转发
request.setAttribute("username","admin");
request.getRequestDispatcher("/index_servlet").forward(request,response);
// 响应重定向,重定向的地址需要额外添加 工程名
//response.sendRedirect("/servlet_advanced/index_servlet");
}
}
IndexServlet类
@WebServlet("/index_servlet")
public class IndexServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = (String) request.getAttribute("username");
response.getWriter().println("Hello," + username);
}
}
页面显示结果如下:
如果在CheckLoginServlet类中,使用响应重定向的方式那么在IndexServlet中就无法获取设置的属性值,因为重定向的本质就是浏览器向服务端发送了两次请求。
cookie与session
浏览器Cookie
- Cookie是浏览器保存在本地的文本内容
- Cookie常用于保存登录状态,用户资料等小文本
- Cookie具有时效性,Cookie内容会伴随请求发送给Tomcat
示例程序如下:
LoginServlet类
@WebServlet("/cookies/login")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("username","admin");
cookie.setMaxAge(60 * 60 * 24 * 7); // 设置cookie的有效期为 7 天
response.addCookie(cookie);
response.sendRedirect("/servlet_advanced/cookies/index");
}
}
IndexServlet类
@WebServlet("/cookies/index")
public class IndexServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
if(cookies == null){
response.getWriter().println("user not login");
return;
}
String username = null;
for(Cookie c : cookies){
if(c.getName().equals("username")){
username = c.getValue();
}
}
if(username == null){
response.getWriter().println("user not login");
}else{
response.getWriter().println("Hello," + username);
}
}
}
示例程序在浏览器地址栏上输入:http://localhost:8080/servlet_advanced/cookies/login
,页面跳转:
直接输入
http://localhost:8080/servlet_advanced/cookies/index
,因为设置了Cookie的时效性为7天,所以依然可以正常登录index。
用户会话Session
Session即:用户会话
- Session用于保存与"浏览器窗口"对应的数据
- Session的数据存储在Tomcat服务器的内存中,具有时效性
- Session通过浏览器Cookie的SessionId值提取用户数据
示例程序如下:
LoginServlet
@WebServlet("/session/login")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("username","张三");
request.getRequestDispatcher("/session/index").forward(request,response);
}
}
IndexServlet
@WebServlet("/session/index")
public class IndexServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String username = (String)session.getAttribute("username");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("您好," + username);
}
}
浏览器地址框中输入:http://localhost:8080/servlet_advanced/session/login
页面显示如下:
Session的实现原理
见图
ServletContext与三大作用域对象
ServletContext
- ServletContext(Servlet上下文对象),是Web应用全局对象
- 一个Web应用只会创建一个ServletContext对象
- ServletContext随着Web应用启动而自动创建
示例程序:
ServletContextInit类
@WebServlet("/servlet_context/init")
public class ServletContextInit extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("title","This is a title");
response.getWriter().println("init success");
}
}
ServletContextDefault类
@WebServlet("/servlet_context/default")
public class ServletContextDefault extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
String title = (String) servletContext.getAttribute("title");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("" + title + "
");
}
}
在浏览器的地址栏输入:http://localhost:8080/servlet_advanced/servlet_context/init
在浏览器的地址栏输入:
http://localhost:8080/servlet_advanced/servlet_context/default
Java Web三大作用域对象
- HttpServletRequest - 请求对象
- HttpSession - 用户会话对象
- ServletContext - web应用全局对象