关于Tomcat10
支持的是jakartaEE9,使用的是servlet5、jsp3和EL4
和javaEE8最大的区别是包名称,原来的javax.servlet全部变为jakarta.servlet
JSP
####Servlet与JSP区别
简单的说,SUN首先发展出Servlet,其功能比较强劲,体系设计也很先进,只是,它输出HTML语句还是采用了老的CGI方式,是一句一句输出,所以,编写和修改HTML非常不方便。 后来SUN推出了类似于ASP的镶嵌型的JSP,把JSP标签镶嵌到HTML语句中,这样,就大大简化和方便了网页的设计和修改。很多网络语言如ASP,PHP,JSP都是镶嵌型的SCRIPT语言
1、JSP在本质上就是SERVLET,但是两者的创建方式不一样
2、Servlet完全是JAVA程序代码构成,擅长于流程控制和事务处理,通过Servlet来生成动态网页很不直观
3、JSP由HTML代码和JSP标签构成,可以方便地编写动态网页
因此在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页.在struts框架中,JSP位于MVC设计模式的视图层,而Servlet位于控制层.
1、JSP是Servlet技术的扩展,本质上就是Servlet的简易方式
2、JSP编译后是“类servlet”
3、Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP是Java和HTML组合成一个扩展名为.jsp的文件
4、JSP侧重于视图,Servlet主要用于控制逻辑
Servlet实例对象的生命周期
Servlet遵循严格的生命周期,在每个Servlet实例的生命中有三种类型的事件,这三种事件分别对应于由Servlet引擎所唤醒的三个方法:
- init()。当Servlet第一次被装载时,Servlet引擎调用这个Servlet的init()方法,只调用一次。如果某个Sevlet需要特殊的初始化需要。那么Servlet编写人员可以重写该方法来执行初始化任务。这是一个可选的方法。如果某个Servlet不需要初始化,那么默认情况下将调用它父类的init方法。系统保证,在init方法成功完成以前,是不会调用Servlet去处理任何请求的
- service()。这是Servlet最重要的方法,是真正处理请求的地方。对于每个请求,Servlet引擎将调用Servlet的service方法,并把Servlet请求对象和Servlet响应对象最为参数传递给它
- destroy()。这是相对于init的可选方法,当Servlet即将被卸载时由Servlet引擎来调用,这个方法用来清除并释放在init方法中所分配的资源。
Servlet技术的要点:
-
当前应用中的所有Servlet接口实现类的实例对象,只能由服务器负责创建,开发人不能不能手动创建
-
默认情况下以单实例多线程的方式对外提供服务
-
Servlet实例一旦创建则常驻内存,只有当服务器资源不足而导致当前Servlet对象被调度或者服务器关闭时才会被销毁
-
默认情况下,服务器接收到对于当前Servlet接口实现类的第一次请求时自动创建这个Servlet接口实现类的实例对象
- 可以手动配置要求服务器在启动时自动创建某个Servlet接口实现类对象
jsp的运行原理
1、客户端发起请求http://localhost:8080/pp/index.jsp 设计了以<welcome-file-list>
的配置
2、请求到达服务器[IP地址和端口号]
3、服务器进行请求资源的定位 /pp/index.jsp,如果不存在则直接对客户端响应404报错
4、如果存在,因为后缀是.jsp,所以服务器会调用jsp引擎将jsp文件转换为Servlet类文件[.java]
5、Tomcat调用Servlet引擎编译生成的.java文件,得到.class的字节码文件
6、Servlet引擎创建Servlet对象生成响应[html文档]
7、客户端接收到响应的html文档进行渲染显示
- jsp是不能直接运行,jsp究其本质就是servlet
Jsp的核心原理是2次编译,从运行速度(第2次访问)上来说优于php、asp.net.最大的缺点是最差的内存性价比
为什么jsp不能取代servlet
JSP动态Web内容可能是动态Web内容的一项伟大的技术,并可将内容和表示presentation相分离,有些人仍然觉得奇怪,为什么servlets仍然有必要和JSP同时实施。
其实servlets的实用性并不是一个问题。它们在服务器端处理方面的表现非常优秀,而且,由于它们引人注目的安装方式而继续存在着。事实上可以将JSP看作一种servlets的高级抽象,它以Servlet 2.1 API扩展的形式来实现。
仍然不应该不加选择地使用servlets;它们可能并不适用于每个人。例如,当一个页面设计者可以很简单地使用方便的HTML或XML工具来编写JSP页面时,servlets可能更适合那些在后端的开发者。开发者都小心确保在presentation和内容之间不存在紧密结合。
JSP技术原理
利用MySQL、Oracle等海量数据库系统作为数据仓库,利用Servlet的高性能服务器端小程序作为后台总控程序,Servlet接受用户输入并分别调用不同的jsp程序向Client反馈信息,JSP/Servlet通过Http协议连接C/S来传递数据,Jsp/Servlet通过传递参数给JavaBean或EJB组件访问操作数据库,这样系统内部数据得到有效的封装保护,很容易实现分布式网络计算
3大JSP指令
page指令 --用来声明当前JSP页面的基本属性
基础语法:
<%@ page 属性名称="值" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
- language 指定JSP页面使用的脚本语言,默认值为java
- contentType 用来指定JSP页面的响应内容类型和所采用的编码方式, 默认值为“text/html,ISO-8859-1”
MIME多用途互联网邮件扩展协议,解决了通过文件后缀判定文件内容类型的缺陷
- text/html
- image/jpeg
- import 通过该属性来引用脚本语言中使用到的类文件,导入多个类或包用逗号分隔。JSP引擎自动导入
java.lang.*;javax.servlet.*;javax.servlet.jsp.*;javax.servlet.http.*
<%@ page import="java.util.Date" %> 允许在一个页面中出现多次 <%@ page import="java.util.*,java.io.*" %>
- pageEncoding 指定当前JSP页面的编码方式, 默认值为“ISO-8859-1”
从实现上来说,和conentType可以相互替代
<%@ page contentType="text/html; charset=UTF-8"%> <%@ page pageEncoding="UTF-8" %>
- session,用来说明是否创建session对象,默认为true
- buffer,用来指定out对象是否创建buffer缓冲区,并指定缓冲区大小。默认为8kb,none表示不创建缓冲区
- autoFlush,缓冲区是否自动刷新,默认为true,如果为false,缓冲区满后不手动刷新会包异常
- info,定义一个字符串常量,使用getServletInfo方法可以打印
- errorPage,指定异常处理页
可以在web.xml中使用
<error-page>
元素为整个WEB应用程序设置处理页面,其中的<exception-type>
子元素指定异常类的完全限定名,<location>
元素指定以"/"开头的错误处理页面的路径。如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中这是的错误处理将不对该页面起作用。
- isErrorPage用于设定当前页面就是异常处理页,只有在异常处理页中才能直接使用exception对象捕捉异常信息
isThreadSafe=“true”[考试重点]
isThreadSafe="true"用于设置当前页面执行的线程问题,true表示采用多线程的方式执行,如果false则采用单线程的方式运行。如果在Servlet中,Servlet默认采用的是多线程的运行方式,如果定义Servlet实现SingleThreadModel接口则Servlet采用单线程的运行方式
Servlet默认采用单实例多线程的方式对外提供服务,
public class HelloServlet extends HttpServlet implements SingleThreadModel
如果Servlet实现了SingleThreadModel则Servlet采用多实例单线程的方式提供服务,该接口不建议使用
####include 指令
include指令用于引入其他JSP页面,如果使用include指令引入了其他JSP页面, 那么JSP引擎将把这两个JSP翻译成一个Servlet ,所以include指令引入通常也成为静态引入
格式: <%@ include file = "head.jsp"%>
注意: 先包含后编译执行----静态包含
####taglib指令
<%@taglib %>用于实现引入所需要的标签库,使用标签库定义显得自定义标签,在JSP页面中启用定制行为。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<table>
<c:forEach var="k" begin="1" end="9">
<tr>
<c:forEach var="i" begin="1" end="${k}">
<td>${k}*${i}=${i*k}</td>
</c:forEach>
</tr>
</c:forEach>
</table>
JSTL: java标准标签库
##6大页面动作
jsp中实际上定义了21个页面动作,其中大部分是用于控制xml标签的,所以不做介绍
JSP动作元素(action elements): 动作元素为请求处理阶段提供信息。动作元素遵循XML元素的语法,有一个包含元素名的开始标签,可以有属性、可选的内容、与开始标签匹配的结束标签。
JSP标签也称之为JSP Action(JSP动作)元素,它用于在JSP页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。
JSP动作元素包含五大类:
- 与存储JavaBean有关的:
<jsp:useBean>
,<jsp:setProperty>
,<jsp:getProperty>
- JSP1.2规范就有的6个基本动作元素:
<jsp:include>
,<jsp:forward>
,<jsp:param>
,<jsp:plugn>
,<jsp:params>
,<jsp:fallback>
- JSP2.0新增加主要与JSP Document有关的6个动作元素:
<jsp:root>
,<jsp:declaration>
,<jsp:scriptlet>
,<jsp:exception>
,<jsp:text>
,<jsp:output>
- JSP2.0新增加,主要用于动态生成XML元素标签的值,包括3个动作:
<jsp:attribute>
,<jsp:body>
,<jsp:element>
- JSP2.0新增加,只要用在Tag File中:
<jsp:invoke>
,<jsp:dobody>
###动态包含
<jsp:include>
标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容中,这种在JSP页面执行时的引入方式称之为动态引入。
<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
。flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
<jsp:include/>
用于实现动态包含[静态] 【重点】
- 各自独立执行,包含执行结果
<jsp:include page="bb.jsp"/>
将bb.jsp页面包含到当前页面中,其中被包含的页面名称page属性可以使用变量,也可以添加额外参数
<jsp:include page="bb.jsp">
<jsp:param value="123" name="age"/>
</jsp:include>
###<jsp:include>
与<%@include %>
指令比较
<jsp:include>
标签是动态引入, <jsp:include>
标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。 而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。
不管是<jsp:include>
标签,还是include指令,它们都会把两个JSP页面内容合并输出,所以这两个页面不要出现重复的HTML全局架构标签,否则输出给客户端的内容将会是一个格式混乱的HTML文档。但include指令要比<jsp:include>
标签效率高些。
- 不能包含其它应用中的内容
- 动态包含中允许使用变量,静态包含中不允许使用变量
- 动态包含可以额外添加parameter参数,但是静态包含不允许
####动态包含和静态包含之间的区别
<%@include file="bb.jsp" %>
静态包含是先包含目标页的代码,然后在编译执行
<jsp:include page="bb.jsp"/>
各自独立执行,然后将目标页面的执行结果包含进来
注意:被包含页面一般是当前页面的一部分,所以不应该是完整页
####Servlet编程
RequestDispatcher rd=request.getRequestDispatcher("bbb.jsp");
rd.include(request,response);
###请求转发
<jsp:forward/>
用于实现请求转发
语法:
<jsp:forward page="bb.jsp">
<jsp:param value="123" name="age"/> 人为添加parameter参数值,不是attribute
</jsp:forward>
- 目标页和转发页共享request和response
- 允许转发时添加parameter参数
- 不能转发其它应用
Servlet编程
RequestDispatcher rd=request.getRequestDispatcher("bbb.jsp");
rd.forward(request,response);
###页面中构建对象
基本用法:
<jsp:useBean id="now" class="java.util.Date" scope="request"/>
<%=request.getAttribute("now")%>
<jsp:useBean id="dd" class="java.util.Date"/>
用于在页面上构建Date对象,相当于Date dd=new Date();
- id命名引用该Bean的变量。如果能够找到id和scope相同的Bean实例,jsp:useBean动作将使用已有的Bean实例而不是创建新的实例
- class指定Bean的完整包名
- scope指定Bean在哪种上下文内可用,可以取下面的四个值之一:page,request,session和application。默认值是page,表示该Bean只在当前页面内可用(保存在当前页面的PageContext内)。request表示该Bean在当前的客户请求内有效(保存在ServletRequest对象内)。session表示该Bean对当前HttpSession内的所有页面都有效。最后,如果取值application,则表示该Bean对所有具有相同ServletContext的页面都有效。
因为jsp:useBean只有在不存在具有相同id和scope的对象时才会实例化新的对象;如果已有id和scope都相同的对象则直接使用已有的对象,此时jsp:useBean开始标记和结束标记之间的任何内容都将被忽略 - type 指定引用该对象的变量的类型,它必须是Bean类的名字、超类名字、该类所实现的接口名字之一。请记住变量的名字是由id属性指定的
- beanName指定Bean的名字。如果提供了type属性和beanName属性,允许省略class属性。
<jsp:useBean id="dd" class="java.util.Date" scope="request"/>
首先在request中查找名称为dd的日期类型变量,就是request.getAttribute(“dd”),如果获取不到,则新建Date变量,并存放在request中,名称就是id的值
用法1
<jsp:useBean id="now" class="java.util.Date" scope="request">
<jsp:setProperty name="now" property="date" value="20"/> 给名称为now的对象设置属性date,值为20.相当于调用now.setDate(20),要求now对象中必须有对应的setDate方法
</jsp:useBean>
<%=request.getAttribute("now")%>
用法2
请求方式为http://localhost:8080/index.jsp?day=1200,这里在请求参数中有个参数名为day
<jsp:useBean id="now" class="java.util.Date" scope="request">
<jsp:setProperty name="now" property="date" param="day"/>接收parameter中名称day的值,并且赋值到now对象上的date属性 now.setDate(Integer.parseInt(request.getParameter("day")))
</jsp:useBean>
<%=request.getAttribute("now")%>
用法3
请求为http://localhost:8080/index.jsp?year=1000&month=9&date=23,按照名称对应进行赋值属性
<jsp:useBean id="now" class="java.util.Date" scope="request">
<jsp:setProperty name="now" property="*"/>
</jsp:useBean>
<%=request.getAttribute("now")%>
用法4
<%@ page import="java.util.*,java.text.*" %>
<%@ page contentType="text/html;charset=UTF-8" %>
<jsp:useBean id="now" class="java.util.Date" scope="request"/>
<jsp:getProperty name="now" property="year"/>年<jsp:getProperty property="month" name="now"/>月<jsp:getProperty property="date" name="now"/>日<jsp:getProperty property="day" name="now"/>
<%
Date now1=new Date();
DateFormat df=new SimpleDateFormat("yyyy-MM-ddE");
out.println(df.format(now1));
%>
<jsp:plugin>
动作元素用来在JSP中嵌入Java插件,比如Applet。<jsp:plugin>
将会根据浏览器的版本替换成<object>
标签或者<embed>
标签。
<jsp:plugin>
type="bean | applet"
name="Applet名称"
code="java类名"
codebase="Java类所在目录"
align="对齐方式"
height="高度"
width="宽度"
hspace="水平间距"
vspace="垂直间距"
archive="预先加载的类列表"
jreversion="JRE版本"
iepluginurl="URL"
nspluginurl="URL"
>
存放数据的4大范围
- page只在当前页面范围内有效
- request可以在请求转发时在多个页面之间共享数据
- session在当前应用中针对当前用户共享数据
- application当前应用中跨用户数据共享
9大默认对象
典型面试:jsp的9大默认对象,并且每个对象说5个方法
page this 封装页面对象,该对象代表了正在运行的由JSP文件产生的类对象,相当于this。一般情况下不建议使用该对象
request ServletRequest,封装请求对象,代表的是来自客户端的请求HttpServletRequest。包括从GET/POST请求传递过来的参数
response ServletResponse,封装响应对象,代表的是对客户端的响应HttpServletResponse。网页传回客户端的信息
application ServletContext,封装应用程序对象,负责提供应用程序在服务器中运行时的一些全局信息,是一个容器级的共享对象数据
session HttpSession 封装会话对象,代表服务器与客户端所建立的会话,是javax.servlet.http.HttpSession接口。当需要在不同的JSP页面中保留客户信息的情况下用于跟踪用户状态。在客户端允许时,使用Cookie支持;否则一般使用URL重写来支持。即使不存在session引用,这个对象也是自动绑定的。但有一个例外,这就是如果你用page指令的session属性关闭了会话,此时对session变量的引用将导致JSP页面转换成Servlet时出错
config ServletConfig 封装代码配置对象,该对象提供一些该Servlet的配置信息,是javax.servlet.ServletConfig接口的实现
exception 异常信息的对象,封装异常对象,代表了JSP文件运行时所产生的并且没有被捕获的例外对象,此对象不能在一般JSP文件中直接使用,而只能在使用了<%@ page isErrorPage="true "%>
的JSP文件中使用
out 等价于response.getWriter() 封装输出对象,用来向客户端自定义输出内容,代表了向客户端发送数据的对象,是javax.servlet.jsp.JspWriter接口的实现。JspWriter是带缓冲的版本
pageContext 包装页面上下文对象,代表的是当前页面运行的一些属性,例如可以获取session、request、response、exception、ServletContext和ServletConfig的引用。是javax.servlet.jsp.PageContext接口的实现
###config
config对象是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)
常见方法:
- getInitParameter(String name):String
- config.getServletContext():ServletContext—application
- config.getInitParameterNames():Enumeration
- config.getServletName():String
jsp页面中获取配置参数
<%=config.getInitParameter("abc")%>
jsp页面的配置 web.xml
<servlet>
<servlet-name>Index</servlet-name>
<jsp-file>/index.jsp</jsp-file>
<init-param>
<param-name>abc</param-name>
<param-value>yanjun</param-value>
</init-param>
<init-param>
<param-name>age</param-name>
<param-value>1111</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Index</servlet-name>
<url-pattern>/aaa.do</url-pattern>
</servlet-mapping>
扩展点1:类似于Servlet中的init方法定义
<%!
public void jspInit(){
System.out.println("jspInit..");
}
%>
只有在代码段中直接使用9大默认对象,因为从jsp生成Servlet时,自动会添加生成9大默认对象的方法
如果在声明代码段中使用9大默认对象,则必须通过方法进行参数传递
<%!
public String getError(HttpServletRequest request,String key){
Object obj=request.getAttribute(key);
if(obj!=null)
return obj.toString();
return "";
}
%>
<%=this.getError(request,"username")%>
###exception
exception对象是一个例外对象,当一个页面在运行过程中发生了例外,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象
可能会出现异常的页面定义
<%@ page contentType="text/html; charset=UTF-8" errorPage="bbb.jsp" %>
<%
int k=0;
out.println(10/k);
%>
报错信息显示页面,需要通过默认对象exception获取上个页面的Exception对象
<%@ page import="java.io.PrintWriter" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>只有在当前页面种配置isErrorPage=true,否则不能直接使用exception默认对象获取异常信息
<%=exception.toString()%><br/>
<%=exception.getCause()%><br/>
<%exception.printStackTrace();%>
<%exception.printStackTrace(new PrintWriter(out)); %>
<%=exception.getMessage()%>
###out
out对象是JspWriter类的实例,用于服务器端向客户端输出文本内容的常用对象。
Jsp页面的所有数据都是使用javax.serlet.JspWriter对象编写。JspWriter模拟一个java.io.PrintWriter的行为。如果Jsp页面是缓冲的,当然默认也是缓冲的,所以JspWriter模拟一个javax.io.BufferWriter
获取对象
out=pageContext.getOut();
常用方法
out.println(“哈哈!”);//out.println(“<br>")";
out.print(Object);
out.clear();
out.flush();
out.close();关闭输出,其后内容执行但不输出
在页面中可以配置缓冲大小
<%@ page contentType="text/html; charset=UTF-8" buffer="16kb" autoFlush="true" %>
缓冲区大小:<%=out.getBufferSize() %><br/>
<%=out.getRemaining()%><br/>
<% out.newLine(); %>
需求:输出日期
<%@ page import="java.util.Date" %>
<%@ page import="java.text.DateFormat" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page contentType="text/html; charset=UTF-8" buffer="16kb" autoFlush="true" %>
<%
Date now=new Date();
String[] arr=new String[]{"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
out.println(arr[now.getDay()]);
%>
<hr/>
<%
DateFormat df=new SimpleDateFormat("E");
out.println(df.format(now));
%>