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脚本
- 小脚本
- 表达式
- 声明
- JSP标签
-
注释
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
请求方法:Get
、Post
、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