Servlet与JSP进阶笔记(一)

请求与相应

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应用全局对象

你可能感兴趣的:(Servlet与JSP进阶笔记(一))