JavaLearn#(23)JSP相关语法HTTP协议Servlet介绍Servlet生命周期请求和响应相对路径转发和重定向

Posted LRcoding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaLearn#(23)JSP相关语法HTTP协议Servlet介绍Servlet生命周期请求和响应相对路径转发和重定向相关的知识,希望对你有一定的参考价值。

1. JSP简单内容

1.1 JavaEE

JavaEE 包含JSP

JavaEE是一个开发分布式企业级应用的规范和标准。JavaEE包含之前学过的所有内容(JavaSE)

真正开发中,很少使用JavaEE的原生内容,都是用 SSM 框架进行快速开发

1.2 部署web项目到服务器

简单的总体流程,先看一下效果。

  • 安装服务器软件Tomcat,下载解压即可

  • 创建Web项目(使用IDEA创建Java Enterprise项目),开发静态页面

    新版 IDEA 没有JavaEE的选项,可以在项目中按Alt + Ctrl + Shift + / 键,然后选择 Registry,在弹框中找到 javaee-legacy.project.wizard,然后选中,再进行创建即可

  • 启动Tomcat

  • 不同的用户通过浏览器访问web项目

总结:Web项目需要JavaEE的类库。Web项目中还可以存放静态网页和动态网页

1.3 获取并输出当前时间—JSP

  • 小脚本: <% Java代码 %>
  • 表达式: <%=表达式 %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>获取当前时间</title>
        <!-- 客户端(浏览器获取) -->
        <script type="text/javascript">
        	window.onload = function() 
                var now = new Date();
                document.getElementById("ctime").innerHTML="客户端时间:" + now.toLocaleString();
            ;
        </script>
    </head>
    <body>
        <div id="ctime"></div>
        
        <!-- JSP的小脚本 -->
        <%
        	// 服务器端获取,Java代码
        	Date now = new Date();
        	// out 是 JSP的内建对象,不需要new,可以直接使用
        	out.println("服务器端时间:" + now.toLocaleString());
        %>
        
        <!-- JSP的表达式 -->
        服务器端时间2:<%=now.toLocaleString() %>
    </body>
</html>

JSP是动态网页技术,是动态生成网页数据,而不是具有动态效果的网页

JSP是服务器端技术

由应用服务器(例如Tomcat)来编译和执行嵌入的Java脚本代码,然后将生成的整个页面信息返回给客户端

1.4 JSP执行过程

Web容器处理 JSP文件请求需要经过 3个阶段

  • 翻译/转译阶段:.jsp --> .java(Servlet)
  • 编译阶段: .java --> .class
  • 执行阶段: .class — 解释执行

1.5 声明和注释

  • 声明: <%! 内部可以定义变量和方法 %>,在此处定义的变量和方法,编译后会变成 Servlet的成员变量和方法
  • 注释: <%-- JSP的注释内容 --%>,不会传输到客户端
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>统计次数</title>
</head>
<body>
<%!
    // 在此声明中,不能使用 JSP 的内建对象
    int count = 0;

    public void countTip() 
        count++;
    
%>
<%
    // count++;
    countTip();
    out.println("当前页面访问次数:" + count + "<br>");
%>
</body>
</html>

Servlet/JSP 是一种单实例,多线程的技术

  • 单实例:不管有多少个用户访问(不管有多少个请求),用一个 Servlet/JSP,只创建一个对象
  • 多线程:对于每一次请求,会开辟一个新的线程,调用 service()

1.6 静态包含和动态包含

  • 静态包含: <%@include file="header.jsp"%>
  • 动态包含: <jsp:include page="footer.jsp"></jsp:include>

静态包含与动态包含的区别:

  • 包含的时机不同
    • 静态包含:转译阶段
    • 动态包含:执行阶段
  • 包含的方式不同
    • 静态包含:内容包含
    • 动态包含:方法调用
  • 是否可以有同名变量
    • 静态包含:不可以
    • 动态包含:可以
  • 生成的 class 文件不同
    • 静态包含:被包含文件不生成 class 文件
    • 动态包含:被包含文件生成单独class

创建一个 header.jsp,一个 footer.jsp

在另一个jsp页面中,包含这两个文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>静态包含/动态包含</title>
</head>
<body>
    <%-- 指令标签  【静态包含:直接将整个header.jsp的代码全部拿过来】 --%>
    <%@include file="header.jsp"%>

    <%-- 动作标签  【动态包含】--%>
    <jsp:include page="footer.jsp"></jsp:include>
</body>
</html>

1.7 JSP页面构成

  • 静态内容(等同于HTML)

  • 动态内容

    • JSP标签
      • 指令标签
      • 动作标签
    • Java脚本
      • 小脚本
      • 表达式
      • 声明
  • 注释

1.8 JSP用户登录功能

  • request:JSP内建对象

页面+Java处理,后续加上JDBC

HTML页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
    <form action="doLogin.jsp" method="post">   <!-- get方式参数都在地址栏 -->
        用户名:<input type="text" id="username" name="username" /> <br>
        密码: <input type="text" id="password" name="pwd" /> <br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

JSP页面:doLogin.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>处理登录</title>
</head>
<body>

<%
    // 接收用户编号和密码
    String username = request.getParameter("username"); // 此处是HTML页面 用户输入框的 name 属性
    String pwd = request.getParameter("pwd");

    // 应该调用后台(JDBC)判断登录是否成功;此处直接处理
    boolean flag = false;
    if (username.contains("lwclick") && pwd.length() >= 6) 
        flag = true;
    

    if (flag) 
        out.println("登录成功");
     else 
        out.println("登录失败");
    
%>

</body>
</html>

1.9 理解HTTP协议

HTTP协议

  • Hypertext Transfer Protocol,超文本传输协议
  • 从WWW服务器传输超文本到本地浏览器的传送协议
  • 是一个应用层协议
  • 承载于 TCP协议之上,有时也承载于TLS或SSL协议层,这时就成为了HTTPS(默认端口443)

1.9.1 HTTP请求

HTTP请求工作原理

  • 遵循请求(request)/ 应答(Response)模型
  • 请求需要建立连接,响应结束断开连接,HTTP/1.0,连接不能复用,无状态的
  • HTTP/1.1实现了连接的复用( 声明 Connection:keep-alive ),新的请求可以在上次请求建立的TCP协议上继续发送

请求方式格式

  • 请求行:统一资源标识符(URL)、协议版本号

    POST /demo/login/doLogin.jsp HTTP/1.1

  • 消息报头:包含请求修饰符、客户机信息

    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36 Edg/100.0.1185.29

    Cookie: JSESSIONID=6ED04BBCB0C57FA2BB97A21A473EC3D2; Idea-d39dabc2=423e5159-22a3-425e-95b1-83c72c6ee33f; trdipcktrffcext=1

  • 可能的内容:POST请求的内容

    username=11111lwclick&pwd=a81c

请求方法GetPost、DELETE、PUT等

1.9.2 HTTP响应

响应信息格式

  • 状态行:信息的协议版本号、状态码

    HTTP/1.1 200

  • 消息报头:包括服务器信息、字符编码、MIME类型

    Content-Type: text/html;charset=UTF-8

  • 响应正文

状态代码

  • 1xx:指示信息–表示请求已接收,继续处理
  • 2xx:成功–表示请求已被成功接收、理解、接受; 200:客户端请求成功
  • 3xx:重定向–要完成请求必须进行更进一步的操作; 302:重定向
  • 4xx:客户端错误–请求有语法错误或请求无法实现; 403:服务器收到请求,但是拒绝提供服务。 404:请求资源不存在
  • 5xx:服务器端错误–服务器未能实现合法的请求; 500:服务器发生错误

2. Servlet

Servlet是一个基于Java技术的动态网页技术,运行在服务器端,由Servlet容器管理,用于生成动态的内容。是JSP的前身

编写一个Servlet,实际上就是按照Servlet规范编写一个java类

JSP本质上是一个Servlet(.jsp --- 翻译 --- .java(Servlet) ---- 编译 --- .class ---- 执行—

Servlet/JSP 是单实例,多线程

2.1 使用Servlet开发动态网页

自定义一个 Servlet:

  • implements Servlet:需要实现所有的方法
  • extends GenericServlet:只需要实现 service方法即可
  • extends HttpServlet:自己选择实现,一般使用这个

1.创建MyServlet.java

public class FirstServlet extends HttpServlet 
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
        // 设置字符编码
        resp.setContentType("text/html;charset=UTF-8");
        // 创建一个输出流
        PrintWriter out = resp.getWriter();

        // 使用输出流向客户端输出内容
        out.println("<HTML>");
        out.println("<HEAD>");
        out.println("<TITLE>第一个Servlet</TITLE>");
        out.println("</HEAD>");
        out.println("<BODY>");
        
        Date date = new Date();
        out.println("<p>当前时间是:" + date.toLocaleString() + "</p>");
        
        out.println("</BODY>");
        out.println("</HTML>");

        // 关闭输出流
        out.close();
    

2.修改 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">
    <!-- 配置servlet类信息 -->
    <servlet>
        <servlet-name>FirstServlet</servlet-name>
        <servlet-class>com.lwclick.servlet.FirstServlet</servlet-class>
    </servlet>

    <!-- 配置映射,当请求 /servlet/FirstServlet 时,就转到FirstServlet -->
    <servlet-mapping>
        <servlet-name>FirstServlet</servlet-name>
        <url-pattern>/servlet/FirstServlet</url-pattern>
        <url-pattern>/abc/*</url-pattern>  <!-- 所有以/abc/开始的请求都会转到FirstServlet这个类 -->
    </servlet-mapping>
</web-app>

2.2 使用Servlet进行流程控制

使用 Servlet 修改登录流程,新增一个 success.jsp 页面,成功后跳转到该页面

将所有的判断、跳转逻辑放到 servlet中去处理

public class LoginServlet extends HttpServlet 
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
        // 1. 接收用户编号和密码
        String username = req.getParameter("username"); // 此处是HTML页面 用户输入框的 name 属性
        String pwd = req.getParameter("pwd");

        // 2. 应该调用后台(JDBC)判断登录是否成功;此处直接处理
        boolean flag = false;
        if (username.contains("lwclick") && pwd.length() >= 6) 
            flag = true;
        

        // 3. 根据结果处理
        if (flag) 
            // 跳转到成功页面
            RequestDispatcher requestDispatcher = req.getRequestDispatcher("/login/success.jsp");
            requestDispatcher.forward(req, resp);
         else 
            // 跳回登录页
            req.getRequestDispatcher("/login/login.html").forward(req, resp);
        
    

web.xml中配置 servelt

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

    <!-- 配置servlet类信息 -->
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.lwclick.servlet.LoginServlet</servlet-class>
    </servlet>
    
    <!-- 配置映射,当请求 /servlet/LoginServlet 时,跳转到LoginServlet类进行处理 -->
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/servlet/LoginServlet</url-pattern>
    </servlet-mapping>
</web-app>

修改登录页面的form的action

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
    <!-- action 修改为servlet映射路径(使用相对路径) -->
    <form action="../servlet/servlet/LoginServlet" method="post">
        用户名:<input type="text" id="username" name="username" /> <br>
        密码: <input type="text" id="password" name="pwd" /> <br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

2.3 Servlet生命周期

public class LifeServlet extends HttpServlet 
    /**
     * 构造方法,  只执行一次(单实例)
     * 不管有多少次请求,一个Servlet只实例化一次
     */
    public LifeServlet() 
        System.out.println("构造方法");
    

    /**
     * 初始化   只执行一次
     * 创建对象后执行
     * @param config
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig config) throws ServletException 
        System.out.println("========== init(ServletConfig config) ==========");
    

    /**
     * 服务   每次请求都会调用该方法(每一个请求,Tomcat都会开辟一个新的线程,调用该方法) 多线程的
     * 对请求响应进行处理
     * @param req
     * @param res
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException 
        System.out.println("========== service(ServletRequest req, ServletResponse res) ==========");
    

    /**
     * 销毁   只执行一次
     * 关闭对象前执行
     */
    @Override
    public void destroy() 
        System.out.println("========== destroy() ==========");
    

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">
    <!-- 配置servlet类信息 -->
    <servlet>
        <servlet-name>LifeServlet</servlet-name>
        <servlet-class>com.lwclick.servlet.LifeServlet</servlet-class>
    </servlet>
    <!-- 配置映射,当请求 /servlet/FirstServlet 时,就转到FirstServlet -->
    <servlet-mapping>
        <servlet-name>LifeServlet</servlet-name>
        <url-pattern>/servlet/LifeServlet</url-pattern>
    </servlet-mapping>
</web-app>
  • 加载类

    • 用户在客户端请求某个 servlet: http://localhost:8080/servlet/LifeServlet

    • Tomcat截取 servlet 路径:/servlet/LifeServlet,并且在web.xml中查找

    • 如果没找到,就报404

      如果找到了(servlet-mapping的url-pattern),就用<servlet-name>LoginServlet</servlet-name>的LoginServlet,去找对应的servlet-name,最后找到 com.lwclick.servlet.LifeServlet

    • 获取 Servlet 的完整路径字符串

      String className = “com.lwclick.servlet.LifeServlet”;

    • 获取类的结构信息

      Class clazz = Class.forName( className );

  • 实例化(只执行一次)

    • 不是通过 new LifeServlet() 构造方法创建
    • 是使用反射Servlet servlet = (Servlet) clazz.newInstance();
  • 初始化 init()(只执行一次)

    • Method m1 = clazz.getMethod("init", ServletConfig.class);
    • m1.invoke(servlet, config)
  • 服务 service() (每次)

    • 使用反射执行
  • 销毁 destroy() (一次)

    • 使用反射

Servlet的生命周期和反射密不可分,由 Tomcat负责

加载类、实例化、初始化的时机:

  • 情况1:第一次访问该 Servlet 的时候 – 懒汉模式(默认)
  • 情况2:项目启动时 – 饿汉模式(通过在 web.xml 的 servlet 中添加 <load-on-startup> 指定为饿汉)

2.4 Servlet的API

Servlet必须直接或间接实现 javax.servlet.Servlet 接口

通过继承javax.servlet.GenericServlet 类实现跨协议的 Servlet

通过继承javax.servlet.HttpServlet 实现HTTP Servlet 【一般使用这个】

HttpServlet的 protected service() 根据HTTP请求方法的类型调用相应doXXX()方法,我们自己编写的servlet应该继承HttpServlet,一般要覆盖 doPost 或者 doGet 方法(实际直接重写 service 即可)

2.5 获取上下文和初始化参数

  • ServletConfig 接口:

    • 表示单独的Servlet的配置和参数,只是适用于特定的Servlet

    • 从一个servlet被实例化后,对任何客户端在任何时候访问有效

      仅对本servlet有效,一个servlet的ServletConfig对象不能被另一个servlet访问

      ServletConfig config = this.getServletConfig();

  • ServletContext 接口:

    • WEB容器在启动时,会为每个WEB应用程序都创建一个对应的ServletContext对象(每个模块一个)

    • 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯

      ServletContext context = this.getServletContext();

所有的外部参数都需要在 web.xml 中声明

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
           version="2.5">

    <!-- 【上下文参数】 所有servlet都可以获取的外部参数信息 -->
    <context-param>
        <param-name>path</param-name>
        <param-value>jdbc.properties</param-value>
    </context-param以上是关于JavaLearn#(23)JSP相关语法HTTP协议Servlet介绍Servlet生命周期请求和响应相对路径转发和重定向的主要内容,如果未能解决你的问题,请参考以下文章

JavaLearn#(24)SessionCookieServletContextMVC开发模式JSP九大内建对象及四个作用域JSTL及EL表达式过滤器监听器

JavaLearn#(21)JavaScript入门基本语法函数基本对象数组事件DOM和BOM

JavaLearn#(21)JavaScript入门基本语法函数基本对象数组事件DOM和BOM

JSP/Servlet基础语法

JavaLearn#(25)Ajax相关知识三级联动案例Bootstrap入门栅格系统排版表格字体图标等简单概述

JavaLearn#(25)Ajax相关知识三级联动案例Bootstrap入门栅格系统排版表格字体图标等简单概述