1.Servlet是JavaEE Web组件,必须运行在Web容器中,如Tomcat,需要容器为其提供运行的环境。
2.本质上,Servlet就是一个java类,不过这个java类要遵守一定的规范,即继承HttpServlet类。
3.HttpServlet类中定义了很多方法,自定义的Servlet类需要覆盖其中的方法,一般情况下,只覆盖doGet和doPost方法。使用Get方式访问时,容器自动调用doGet方法,使用post方式访问时,自动调用doPost方法
在访问Servlet前要告诉容器一些信息,容器才能运行它,这就是配置。配置servlet要在web.xml中进行。配置信息如下:
访问Servlet前,必须配置Servlet,在配置文件web.xml中配置Servlet,配置主要使用两个标签
其中
另外该文件中
服务器会到web.xml中找到配置在
Init()方法://servlet第一次被调用时执行,有且仅执行一次,完成初始化动作
Service()方法://servlet每次被请求时调用
Destroy()方法://servlet被回收时(服务器关闭或者被重启),被调用,有且仅执行一次
servlet的生命周期测试源代码:LifeCycleServlet.java
//init()方法servlet第一次被调用时执行,有且仅执行一次,完成初始化动作
@Override
public void init() throws ServletException {
count=1;
System.out.println("该servlet已经完成初始化.....");
}
//doGet和doPost方法servlet每次被请求时调用
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throwsServletException, IOException {
//设置返回页面的类型
resp.setContentType(CONTENT_TYPE);
PrintWriterout=resp.getWriter();
count++;
out.print("该servlet已被调用了"+count+"次");
System.out.println("该servlet执行了service方法");
}
//destroy()方法servlet被回收时(服务器关闭或者被重启),被调用,有且仅执行一次
@Override
public void destroy() {
System.out.println("该servlet已被销毁....");
}
A: 创建类HelloServlet.java
B: 继承HttpServlet.java
C: 覆写doGet/doPost方法
D: 配置web.xml
访问前首先将项目部署到Tomcat上,启动服务器(Tomcat)。
1.通过地址栏访问Servlet,在地址栏输入Servlet的URL直接访问,该方式是get方式,调用doGet方法。在浏览器中访问路径:http://机器ip地址:8080/部署的项目名称/servlet路径(url-pattern里的路径)
2.通过超链接访问Servlet
在超链接的href属性中写入url-pattern路径。(推荐使用绝对路径:工程名+/url-pattern路径)
3.通过表单提交访问Servlet,使用submit按钮提交
如:http://localhost:8080/servlet1/servlet/FirstServlet
A:servlet中url-pattern中配置的路径必须以"/"开头,是webRoot(项目名)后的路径
B:掌握获取4个路径的方法
//设置返回页面的类型(html文本类型,使用utf-8编码)
resp.setContentType("text/html;charset=UTF-8");
//创建输出对象,服务器响应产生输出流
PrintWriterout=resp.getWriter();//得到输出流
out.print("hello
");
out.print("world
");
//servlet常见的四种路径获取
//1.http://localhost:8080/servlet_1/helloServlet?
out.print(req.getRequestURL()+"
");
//2.部署的工程名/访问路径(/servlet_1/helloServlet)
out.print(req.getRequestURI()+"
");
//3.helloServlet(被请求的servlet名称)
out.print(req.getServletPath()+"
");
//4.servlet_1(动态获取工程名)
out.print(req.getContextPath()+"
");
C:在页面的表单的action属性中建议使用绝对路径:/部署项目名+servlet路径,此时这里的servlet路径就是url-pattern中配置的路径
D:用户提交表单后,执行action所指定的servlet路径所对应的serlvet,调用servcie方法,service方法会根据get/post请求,再去调用doGet/doPost方法。
public void servcie(HttpServletRequestreq,HttpServletResponse resp){
String method = req.getMethod();
if("get".equals(method)){
doGet(req,resp);
}
elseif("post".equals(method)){
doPost(req,resp);
}
else ...
}
E:修改java代码,tomcat服务器不自动重启问题:
修改tomcat配置文件context.xml,在context标签上增加属性:reloadable="true"
一、JSP是运行在服务器端的组件,在html页面中嵌入了java代码用来生成动态页面(html实现静态部分,java代码实现动态部分),JSP也必须使用容器运行(组件均需使用容器),其仍是Servlet。JSP文件必须先放到服务器中,然后通过HTTP的方式访问。因为文件内所有<%%>内代码是被web服务器解释执行的。
二、在一个JSP页面中,主要分为三种元素:编译指令、操作指令、JSP代码。
Ø 编译指令告诉JSP的解释引擎(如Tomcat),需要在编译时做什么动作,比如引入一个其他类,设置JSP页面使用什么语言、编码等。作用是从JSP发送到JSP包容器上的一个信息.用来设置全局变量,如声明类,要实现的方法和输出内容的类型等.他们并不向客户产生任何输出.所有指令都在整个JSP文件的范围内有效.在标签 中指令都是用@字符在标签内标注的.
Ø 操作指令则是在JSP页面被请求时,动态执行的,比如可以根据某条件动态跳转到另外一个页面。
Ø JSP代码(即JSP的脚本元素)指的就是我们自己嵌入在JSP 页面中java代码。主要分为以下几种:
1. 使用<%!.......%>标记:用来声明JSP页面中的变量和方法。例<%! int i=0; %>
2. 使用<%.........%>标记:表示是一段。
3. <%=………………..%>之间插入一个表达式,表达式的值由服务器负责计算,表达式的结果用字符串形式发送到客户端显示。注意:期内语句不可加分号。
· 编译指令标签:
1.语法规则:<%@指令名attribute=”value”....%>
2.三类指令:页面(page)指令,include指令,taglib指令
page指令:用来定义整个JSP页面的一些属性和这些属性的值.<%@属性1=”值1”属性2=”值2”%>
注意:
1.page指令的作用对整个页面有效,与位置无关,习惯写在最前面;
2.一个属性可以指定几个属性值,属性值之间用逗号分隔;
3.可以使用多个page指令给属性import指定几个值,但其他属性只能使用一次page指 令给属性值指定的一个值.
page指令几个常用的属性:
language属性:规定JSP页面使用的脚本语言,该属性的值目前只能取java.
格式:<%@ pagelanguage=”java”%>
import属性:为JSP页面引入java核心包中的类,就可以在JSP页面的程序段中使用该类.
格式:<%@ pageimport=”java包中的类”%>(import可重复,其他不可)
contentType属性:定义JSP页面响应类型和JSP页面字符的编码
格式:<%@ pagecontentType=”text/html;charset=uhf-8”%>
session属性:用于设置是否要使用内置的session对象,该属性值默认为true
include指令:在JSP页面内某处插入一个文件,被插入的文件必须是可使用可访问的,即该文件必须和当前JSP页面在同一个Web项目中.
语法:<%@include file=”文件名称”%>
taglib指令:定义一个标签库以及其自定义标签的前缀.<%@ taglib %>声明此JSP文件使用了自定义的标签,同时引用标签库.
语法:<%@ tagliburi=”URIToTagLibrary” prefix=”tagPrefix”%>
1.输入输出内置对象(3个)
request对象表示客户端请求的内容;response对象表示响应客户端的结果;out对象负责把 数据的结果显示到客户端的浏览器上.
request对象:包含所有请求的信息.常用方法如下
StringgetParameter(String name) 根据页面表单组件名称获取请求页面提交数据
String[ ] getParameterValues(String name)获取页面请求中一个表单组件对应多个值时的用户的请求数据
voidsetCharacterEncoding(java.lang.String env)设置请求内容的字符编码
String getMethod()获取请求方式(取得HTTP的方法get,post)
其他方法:
Cookie[] getCookies()取得与请求有关的cookies
String getHeader(String name)取得name的标头
Enumeration getHeaderNames()取得所有的标头名称
String getRequestURI()取得工程名/访问路径
HttpSession getSession()
String getRemoteAddr()取得用户的IP地址
String getRemoteHost()取得用户的主机名称
String getRemoteUser()取得用户的名称
int getRemotePort()取得用户的主机端口
response对象:主要用来处理JSP生成的响应,将JSP处理数据后的结果传回到客户端,该对象实现了javax.servlet.http.HttpServletResponse接口.常用方法如下:
void setContentType (String name)设置作为响应生成的内容的类型和字符编码
void sendRedirect (Stringname)发送一个响应给浏览器,指示其应请求另一个URL
StringencodeURL(java.lang.String url)构建一个包含会话信息的URL地址
void sendError(int sc)发送一个错误状态信息
void addCookie(Cookie cookie)新增cookie
out对象:输出流(JSPWriter)对象,使用write(),print(),println()方法。调用out.println()可以直接把字符串打印到浏览器上2.作用域内置对象(3个)
pageContext对象:页面的上下文,是PageContext的一个对象,可以从该对象中获取到其他8个隐式对象,也可以从中获取到当前页面的其他信息。
seesion对象:代表浏览器和服务器的一次会话,是HttpSession的一个对象。
application对象:代表当前WEB应用,是ServletContext对象
Exception对象:在声明了page指令的isErrorPage=”true”时,才可以使用。
JSP编译指令是让JSP容器自动采取的动作,但对于web开发人员,有时想自己控制JSP页面的运行,这时可以采用JSP中的操作指令,这些指令就是指JSP标准动作.
主要有以下标准动作:
JSP标准动作的作用:
实例化对象;
与服务器端资源进行通信;
提高组件的可重用性,增强应用的可维护性;
使JSP页面可与JavaBean对象进行交互;
JSP标准动作的语法:
JSP动作标记遵循XML语言的语法;
具有一个名称; 具有一个前缀jsp;
用一对尖括号<>括起来; 在尖括号<>内定义标记.
(1)与JavaBean交互的三个标记:
创建一个Bean实例并指定它的名字和作用范围.语法格式如下:
//设置Bean的属性值语法格式如下:
{
property=”*”?|
property=”propertyName” [param=”parameterName”]?|
property=”propertyName” value=”{string|<%=expression%>}”
} />
name=”beanInstanceName”表示已经在
Property=”*” 储存用户在jsp输入的所有值,用于匹配Bean中的属性.
property=”propertyName” [param=”parameterName”] 用一个参数值来指定Bean中的一个属性值,一般情况下是从request对象中获得的,其中property指定Bean的属性名,patam指定request中的参数名.
(2)jsp:include指令
jsp:include标准动作用于在当前的JSP页面中加入静态和动态的资源.
语法格式:
include操作指令:编译时包括,形成一个整体.
include动作:运行时包括.
(3)jsp:forward动作指令
jsp:forward动作指令用于把当前的JSP页面转发到另一页面上.
基本语法:
(4)jsp:param动作指令
使用jsp:param操作指令可以在执行jsp动作指令forward操作动作时追加参数.
语法:
(5)jsp:plugin动作指令
当JSP文件被编译,送往浏览器时
属性:
1: type=”bean|applet”将被执行的插件对象的类型,因其无缺省值使用时必须指定.
2: code=”classFileName”将会被java插件执行java class的名字,必须以.class结尾
3:codebase=”classFileDtirectotyName”将会被执行的java class文件的路径,如果没有 提供该属性,那么使用
4:name=”instanceName”这个Bean或Applet实例的名字,它将会在JSP其他地方调用.
5:
1. HTML注释:在标记符号之间加入注释内容。
2. JSP注释:在标记符号<%--和--%>之间加入注释内容。
注:<%--注释--%>JSP引擎忽略JSP注释。又被成为隐藏注释,JSP编译器不会对其内的语句进行编译,它不会显示在客户的浏览器中,也不会再源代码中看到
当利用request.getParameter得到form表单中元素值得时候,默认的情况下其字符编码格式为ISO-8859-1,该编码不能正确显示汉字。
几种编码格式:
英文编码:iso8859-1
中文编码:gb2312--->gbk---->gb18030(一个汉字两个字节)
国际编码:utf-8(unicode编码,一个汉字三个字节)
Ø 如果是get请求,有两种解决方法:
1:修改tomcat的配置信息:在server.xml文件中加一个属性:URIEncoding="utf-8"
2:将获得的字符串通过newString进行包装。如下:
<%String username=newString(request.getParameter(“username”).getBytes(“iso8859-1”),”utf-8”);%>
Ø 如果请求方式为post,两种解决方法:
1:在执行操作之前,设置request的编码格式,request.setCharacterEncoding("utf-8");仅对post有效
2:将获得的字符串通过new String进行包装。如下:
<%String username=newString(request.getParameter(“username”).getBytes(“iso8859-1”),”utf-8”);%>
post(推荐):用于发送敏感信息(如信用卡号)或要保存到数据库中的信息;发送的数据没有大小限制
1:不通过url传值
2:理论上所传值的大小没有限制
3:能够传递敏感信息
get:用于检索信息(如文档、图表或数据库请求结果);请求信息作为查询字符串发送;发送的数据有大小限制,0-255字节之间
1:通过url传值
2:值的大小是有限制的,0-255个字节之间
3:不能够传递账号、敏感等信息
总结:如果是表单提交,建议使用post,非表单提交,都是get
pageContext作用域:表示存放在该作用域下的值只在当前页面有效,即使刷新页面,该值无效
request作用域:表示存放在该作用域下的值在一个请求响应范围内有效
(JSP页面发送请求到收到服务器响应成为一个请求响应范围)
Session(会话)作用域:表示存放在该作用域下的值在一个会话范围内有效,一个会话可以有多个请求和响应,当浏览器关闭,会话终止。
application作用域:表示存放在该作用域下的值在整个应用程序范围(服务器关闭或重启)内有效。
四个作用域的范围由小到大依次为:
pageContext
建议:尽量使用request作用域,不行,才考虑使用session及以上作用域
作用域对象存储和取得属性的方法,(以上四种均可使用,注:pageContext无getAttribute()方法)
void setAttribute(String name,Object value) 设定name属性的值为value
并存放到作用域中.
Enumeration getAttributeNamesInScope(int scope)取得所有作用域内的属性
Object getAttribute(String name)从作用域中取出name属性的值
void removeAttribute(String name)从作用域中移除name属性的值
jsp就是servlet,它们都能完成业务逻辑和显示
A:逻辑:相当于一个servlet
B:显示:相当于一个html
testInput.jsp--->testInput1.jsp,display.jsp
本质区别:请求的转发只发出了一次请求,而重定向则发出了两次请求。
A:请求转发
request.getRequestDispatcher(url).forward(request,response); 在一个request作用域范围内有效
在请求对象的转发器对象中写入要转发的url地址,调用气forward方法(带请求和响应参数)
特点:
1:可以保存request作用域内的值
2:浏览器的url地址未发生任何改变
3:请求转发url路径只能是webRoot下的路径
B:响应重定向
response.sendRedirect(url); 在session及以上作用域范围内有效。
特点:
1:只能保存session,application作用域内的值
2:浏览器的url地址发生了改变
3:响应重定向url路径可以是任意路径
HTTP是无状态协议,服务器将唯一的会话 ID 分配给客户端以跟踪用户。Web Server对每一个客户端请求都没有历史记忆,seesion用来保存客户端状态信息,由Web Server写入,存于客户端,客户端每次访问都把上次的session记录传递给Web Server,Web Server读取客户端提交的session来获取客户端的状态信息。
l 理解session对象的方法:
l 获取属性的值:getAttribute(String name)
l 设置session的属性值:setAttribute(Stringname,Objectvalue)
l 设置session的创建时间:long getCreationTime()
l 获取最大活动时间:int getMaxInactiveInterval()
l 获取最后的访问时间:long getLastAccessedTime()
l 注销session:invalidate()
l 移除session中的属性值:removeAttribute(Stringname)
实例:看当前的登陆名和密码是否跟session中保存的登录名和密码相同,如果相同则返回成功页面,否则返回失败页面。
(传值的三种方式:url传值、表单传值、setAttribute()和getAttribute()方法)
Login.jsp:
<form action="<%=request.getContextPath()%>/testLogin.jsp">
username:<input name="username"/><br/>
password:<input type="password" name="pass"/><br/>
<input type="submit" value="登陆"/>
form>
testLogin.jsp:
<%
//获取表单中提交过来的用户名和密码
Stringusername = request.getParameter("username");
Stringpass = request.getParameter("pass");
//比较提交的用户名和密码是否是Mike 123
if ("mike".equals(username)&& "123".equals(pass)) {
//如果一致,将用户名保存起来,在成功页面调用getAttribute()方法,获取该值
request.setAttribute("username", username);
//返回成功页面(请求转发到登陆成功页面)
request.getRequestDispatcher("/success.jsp").forward(request,response);
}else {
//否则返回登陆页面(请求转发到登陆页面)
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
%>
请求参数与请求属性:
Cookie是服务器上根据用户浏览器识别用户并记录一些相关信息的组件。通过Cookie,网站可以识别你是第一次访问还是又一次访问它,在你浏览网站的时候,网站的程序会在你不知不觉中将一个小的Cookie(作为一个文本文件)存储在你的硬盘中。
1.指网站为了辨别用户身份、进行会话跟踪而储存在用户本地终端上的数据(通常经过加密)。
2.Cookie 用于存储Web 服务器发送给客户端的信息。服务器通过设置响应标题中的 Set-Cookie 方法来发送 cookie。
使用Cookie首先要建立一个Cookie,然后设置其属性,再通过response对象的addCookie()方法将其放入客户端,获取Cookie对象可用request对象的getCookies()方法。
创建cookie对象:Cookiecookie=new Cookie(String cookiename,String cookievalue)
保存cookie(存入客户端):response.addCookie(cookie);
设置cookie有效期(单位秒),超过设定时间,该Cookie自动销毁:cookie.setMaxAge(3600);
过滤器的创建步骤:
1.定义一个类并实现Filter接口;
2.实现doFilter()方法;
3.在web.xml中进行配置
javax.servlet.Filter接口定义了过滤器的生命周期其实现类对象按照生命周期,对用户的请求和资源的响应进行过滤.
Filter 接口包含以下方法:
public voidinit(FilterConfig filterConfig) throws ServletException//初次请求时调用,仅一次
public void doFilter(ServletRequestreq, ServletResponse resp, FilterChain chain) throws java.io.IOException,ServletException//每次请求均调用
public voiddestroy() //过滤器不使用时销毁,有且仅执行一次
配置web.xml(配置信息如下:)
A.过滤器定义用于将过滤器名称与部署描述符web.xml中的特定类关联
<filter>
<filter-name>adminFilterfilter-name> //指定过滤器的名称
<filter-class>com.itany.filter.AdminFilterfilter-class> //指定类的全名称
//
filter>
B.使用
<filter-mapping>
<filter-name>adminFilterfilter-name> //指定过滤器的名称
<url-pattern>/*url-pattern> //指定servlet的名称(/*表示所有servlet)
filter-mapping>
注意:过滤器配置信息应刚在所有servlet配置信息之前
FilterChain接口用于调用过滤器链中的一系列过滤器,调用其doFilter()方法可出过滤器.
过滤器应用示例:
publicclassSetCharacterEncodingFilter implements Filter{//实现Filter接口
private Stringcharset="";
@Override
//初始化方法init(),在第一次请求时调用该方法,有且仅执行一次
publicvoid init(FilterConfig filterConfig) throws ServletException {
//从配置信息
charset=filterConfig.getInitParameter("charset");
}
@Override
publicvoid doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding(charset);
//出过滤器
chain.doFilter(request, response);
}
@Override
publicvoid destroy() {
}
}
·EL全名为Expression Language,由两个组开发:
JSP 标准标签库专家组
JSP 2.0 专家组
·重要作用:
1.提供复杂表达式(涉及Java对象)的值(替换<%= %>表达式)
2.访问一个任意Java对象的性质
3.调用JavaBean或其它Java对象的方法
·语法:
以“${”开始,以“}”结尾,如:${EL Expression}
例如:从Seesion的作用域范围内取的用户的性别.
EL表达式写法: ${sessionScope.user.sex}
JSP脚本写法:
User user=(User)session.getAttribute(“user”);
String sex=user.getSex();
· 可在JSP中禁用EL
全页面禁用:
<%@page isELIgnored ="true|false" %>(默认false)
局部禁用: \${……}
· .与[]运算符
${sessionScope.user.sex}等于${sessionScope.user[“sex”]}
1.当要存储的属性名称中包含一些特殊字符(.或-等)非字母和数字的符号,就一定要使用[], 如${user.My-Name}不正确应改为:${user[“My-Name”]}
2.有如下情况:
${sessionScope.user[data]},此时data是一个变量,如data值为”sex”就变成${sessionScope.user.sex},如果要动态取值时,就需用该方法.
·EL变量
例如:${username},意思是取出某一范围中名称为username的变量,没有指定范围,默认会先从page范围找,找不到再到request,session,application范围内找,假如途中找到username就直接回传,不再继续找下去,假如全部范围内都没找到,就回传null.
· EL内置对象(隐式对象11个)
与范围有关:
pageScope:取得page范围内的属性名称所对应的值
requestScope:取得request范围内的属性名称所对应的值
sessionScope:取得session范围内的属性名称所对应的值
applicationScope:取得application范围内的属性名称所对应的值
与输入有关:
param:如同SevletRequest.getParameter(String name)回传String类型值(如:request.getParameter(Stringname)用EL表示为:${param.name})
paramValues:如同SevletRequest.getParameterValues(String name)回传String[]类型的值
cookie:如同HttpServletRequest.getCookies()
注意:如果要用EL输出一个常量,字符串要加双引号,不然EL会默认把这个常量当作一个变量来处理.
PageContext:使用${pageContext}来取得有关用户要求或页面的详细信息.
${pageContext.request.requestURL}取得请求的URL
${pageContext.request.contextPath}取得工程名
${pageContext.request.remoteUser}取得用户名称
${pageContext.request.remoteAddr}取得用户的IP地址
Empty运算符主要用来判断是否为空(如${empty”hello”}结果为false)
·JSTL介绍
1.JSTL:JSPStandard Tag Library(JSP标准标签库),是由JCP所制定的标准规范,提供给JavaWeb开发人员一个标准通用的标签函数库
2.为开发人员提供了一个无脚本环境,可以不使用Java语言,而使用标签完成设计,取代传统的在页面中嵌入服务器端Java脚本的做法
3.使用:
3.1使用前需导入jar包(jstl1.2.jar), JDK1.5默认已带
3.2通过taglib指令在页面中加载JSTL标签库(并给出前缀),以下两种方式:
绝对定位:<%@taglibprefix=”c”uri=”http://java.sun.com/jsp/jstl/core”%>
相对定位:<%@taglibprefix=”c” uri=”WEB-INF/c.tld”%> //(该种方式需将c.tld文件拷贝到项目中.通过前缀prefix可找到该路径)
1.通用标签库用于操作JSP页面内的作用域变量
1)
属性:
- value:要显示的值(可以是EL表达式或常量),必须,无默认值
- default:value值为null时显示default的值,可选,无默认值
- escapeXml:是否转换特殊字符,如”<“转为”<“,可选,默认为true
示例:
-
2)
属性:
- var:被赋值的变量名(用来存放运算式的结果),可选,无默认值
- value:变量值(要被存放的值),可选,无默认值
- scope:变量的作用域,可选,默认为page
示例:
-
3)
属性:
- var:要被删除的变量名,必须,无默认值
- scope:变量的作用域,可选,默认为pageàrequestàsessionàapplication
示例:
-
4)
属性:
- var:存储异常信息的变量,可选,无默认值
示例:
-
……//可能产生异常的代码段
2.通用标签库用于操作JSP页面内的作用域变量
1)
属性:
- test:要判断的条件,必须,返回boolean值
- var:用于存储表达式结果的变量,可选
- scope:变量的作用域,可选,默认值为page
示例:
…………
<formaction=""method="post">
username:<inputname="username"value="${param.username}"/><br/>
<inputtype="submit"value="校验"/>
form>
<%=request.getParameter("username")%><br/>
${param.username }
//如果请求参数username为mike,进入if里设置flag为true
<c:iftest="${param.username=='mike' }">
<c:setvar="flag"value="true"/>
c:if>
2)
主体部分由子标签组成
属性(只有
– test:要判断的表达式,必须,返回boolean值
示例:
<c:choose>
<c:whentest="${flag}"> //test表达式为真,则执行该项
身份有效!
c:when>
<c:otherwise> //否则执行otherwise
身份无效!
c:otherwise>
c:choose>
3.迭代标签库,用于多次计算迭代体
属性:
– var:做循环的对象变量名,若存在items属性,则表示循环集合中对象的变量名
– items:指定要遍历的集合
– varStatus:存放遍历状态的变量
– begin:遍历的起始位置
– end:遍历的结束位置
– step:遍历步长
varStatus的属性:index、count、first、last
总结:
1.JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
JSP 是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"类servlet"。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。
2.请详细描述jsp的运行机制。
当请求到达服务器访问一个jsp,服务器会将.jsp文件转换成一个.java文件,这个文件是一个Servlet。转换是由服务器中一个jsp引擎完成的,然后自动编译(实际上运行的是servlet,也就是在服务器端运行),最后调用和执行的是这个Servlet字节码文件。
由于一个JSP页面在第一次访问时要经过翻译、编译和执行这几个步骤,所以客户端得到响应的时间比较长。当该页面再次被访问时,它对应的class文件已经生成,因此JSP页面的访问速度会很快。
具体步骤如下:
1.用户的客户机访问相应的jsp页面,如http://localhost:8080/TestWeb/index/login.jsp。
2.Tomcat服务器获取URL请求,服务器找到相应的页面,如果获取的后缀名是.jsp,则Tomcat把请求交给JSPServlet处理。
3.服务器将jsp转译(调用service方法编译JSP文件)成servlet的源码(即名为.java的文件)。
4.服务器JSP引擎调用JVM将servlet的源码编译成class文件,如果JSP第一次被调用,将把JSP编译成Servlet,如果JSP不被修改将不会再被编译,否则将会再次编译。通常,在JSP文件没有被修改的前提下,JSP只会被编译一次,所以在第一次访问的时候访问的速度会比较慢。(编译的过程如下:Tomcat调用service方法编译JSP文件,创建一个*_jsp.java文件保存到服务器的\work\Catalina\目录下的相对应的项目文件夹里面,该java文件继承自父类HttpJspBase类 。)
5.创建HttpServletRequest和HttpServletResponse 。
6.调用*_jsp.java继承自父类HttpJspBase的方法service(request,response) 。
7.服务器将class文件加载到内存并执行。
8.服务器将class的文件执行后(在service方法里面会调用_jspService(request,response)方法渲染输出html返回给客户端)生成的html代码发给客户机器,客户机浏览器根据相应的html代码进行显示。