(一)JSP运行的机制
JSP是一种建立在Servlet规范功能之上的动态网页技术,它们都是在通常的网页文件中嵌入脚本代码,用于产生动态内容,不过和ASP不同的是JSP文件中嵌入的是Java代码和JSP标记。其实JSP文件在用户第一次请求的时候会被编译成Servlet,然后再由这个Servlet处理用户的请求,所以JSP也可以看成是运行时的Servlet,模糊地将JSP和Servlet是同一个东西。但是他们之间的区别又有哪些呢?
1.Servlet是Java对于CGI的回应(Common Gateway Interface),它们在服务器上的执行和解释浏览器的内容的请求,承担客户端和其他应用程序之间的中间层角色。Servlet主要是动态把内容混合到静态的内容以产生用于回应的HTML。
2.JSP页面在HTML页面之中嵌入Java脚本代码和JSP标记,使得文件长度变短,格式更加清晰。另一个方面,JSP把静态和动态的内容分开,实现了内容的分离表示。
3.JSP的使用过程之中,不需要单独配置每一个文件,只要拓展名是.jsp,JSP容器就会自动识别,将其转化为Servlet为客户端服务。
JSP容器管理JSP页面生命周期的两个阶段:转换阶段和执行阶段,当有一个对JSP页面的客户请求到来的时候,JSP容器检验JSP的页面的语法是否正确,将JSP页面转换为Servlet源文件,然后调用javac工具类来编译Servlet源文件生成字节码文件,这个是在转换的阶段,接下来,Servlet容器加载转换后的Servlet类,实例化一个对象处理客户端的请求,在请求处理完成后响应的对象将被JSP容器接受,容器将HTML格式的响应信息发送到客户端,这个阶段是执行的阶段。
如上图所示,在第一次加载JSP页面的时候,因为要将JSP文件转换为Servlet类,所以响应的速度比较慢,当再次请求的时候,JSP就会直接执行第一次请求时产生的Servlet,而不会重新转换JSP文件,所以其执行速度会和直接运行Servlet的速度几乎相同,在JSP的执行期间,系统会检查JSP文件,看是否有产生更新或者修改。如果有的话,JSP容器就会再次编译JSP或者Servlet,如果没有更新或者修改,就会直接运行之前产生的Servlet。
在JSP2.0规范中的定义,JSP页面转换之后的Servlet类必须要实现javax.servlet.jsp.JspPage接口(与Servlet类似,Servlet类必须实现javax.servlet.Servlet接口,该接口继承自javax.servlet.Servlet接口)除了继承的方法之外,JspPage接口还定义了下面的两个方法:
public void jspInit()
这个方法用于在JSP页面初始化的时候被调用,它类似与Servlet中的init()方法。编程人员可以在JSP的声明之中Override这个方法,但是最好在子类中调用super.init()。
public void jspDestroy()
这个方法是JSP页面在销毁时调用的,它类似于Servlet中的Destroy方法,页面编写者可以在JSP的声明元素中Override这个方法,以进行自己的清楚收尾工作。
因为在绝大多数的情况之下,JSP页面都使用HTTP协议,所以JSP页面转换后的Servlet类实际上必须实现javax.servlet.jsp.HttpJspPage接口,该接口继承自JspPage接口,除了继承的方法之外,HttpJspPage接口只定义了一个方法:
public void _jspService(HttpServletRequest request,HttpServletResponse response)
看到这个方法大家是不是感觉十分亲切了呢?这个Servlet类中的service方法简直是亲生兄弟,当然我们编程经常覆盖的doGet,doPost之类的方法的实质是在service函数之中的一个SwitchBox来实现的service方法的分离包装。
(二)JSP的语法概述
## 对JSP的语法已经有理解的熟练工们可以忽视这一段啦 ##
1.page指令作用于整个JSP页面,定义了许多与页面相关的属性,这些属性将会被用来与JSP容器进行通信。
<%@ page attribute1="xxx" atrribute2="xxx"...%> || <jsp:directive.page attribute1="xxx" attribute2="xxx".../>
page指令的属性主要有15个:
language,extends,import,session,buffer,autoFlush,isThreadSafe,info,errorPage,isErrorPage,contentType,pageEncoding,isELIgnore,defferredSyntaxAllowedAsLiteral,trimDirectiveWhiteSpaces
2.include指令用于在JSP页面中静态包含一个文件,该文件可以是JSP页面,HTML页面,文本文件或者一段JAVA代码。使用了include指令的JSP页面在转换的时候,JSP容器会自动在其中插入所包含的文件的文本或者代码。(file文件的属性的值被解释为当前JSP文件的URL)
<%@ include file="xxx" %> || <jsp:directive.include file="xxxx"/>
3.taglib指令允许页面使用用户定制的新标签:
<%@ taglib (uri="tagLibraryURI" | tagdir="tagDir") prefix="tagPreFix" %> || <jsp:directive.taglib (uri="tagLibraryURI | ")>
4.脚本元素<%! .. %><% .. %><%= ...%>这个三大元老tag我就不多赘述了
(三)JSP中的隐含对象
在JSP容器之中生成的Servlet类的_jspService()方法中,定义了几个隐含对象,而这些隐含对象就是我们在编写JSP页面的时候,可以使用的隐含对象。要注意的是,因为这些隐含对象是在_jspService中方法中的定义的,所以我们只能在脚本段和表达式中使用这些对象。
在JSP页面之中,总共有9个隐含对象:request,response,pageContext,session,application,out,config,page和exception,在基于HTTP协议的实现中,这9个隐含对象与他们各自的类的对应关系显而易见。
下面重点说一下比较重要的几个隐含对象request,response,session,config以及cookie(这个暂且就算作是把!一起讲!)
1.request,response
public void getAttribute(String name)
public Enumeration getAttributeNames()
public void removeAttribute(String name)
public void setAttribute(String name,Object obj)
public String getCharacterEncoding()
public int getContentLength()
public String getContentLength()
public ServletInputSream getInputStream()
public String getParameter(name)
public Enumeration getParameterNames()
public String[] getParameterValues(String name)
public PrintWriter getWriter() throws IOException
public void reset()
public BufferedReader getReader() throws IOException
2.session,config
config通常是作为参数传入init方法里面用于对Servlet类内部的config进行赋值,所以这个config里面就包含了web.xml中我们设置的参数的值。
public String getInitParameter(String name)
public Enumeration getInitParameterNames()
public ServletContext getServletContext()
public String getServletName()
session是用来跟踪会话和管理会话内的状态,利用session,服务器可以把一个客户的所有请求联系在一起,并且记住客户的操作状态,当客户第一次连接到服务器的时候,服务器都会给他建立一个session,并且给客户一个唯一的sessionID标识,以后客户每次提交请求,都要将标识一起提交,服务器根据标识找出特定的session,用这个session记录客户的状态,这个过程根据客户的http请求作出响应。从上面的过程之中,我们可以看出,通过在每一个请求和响应中包含SessionID,服务器就可以将一个用户和另一个用户分开。
三种机制用户会话跟踪:1.SSL(Secure Socket Layer)会话 2.Cookies 3.URL重写
简单说一下SSL是运行在TCP/IP之上像和http这种应用层的协议之下的加密技术,SSL是在HTTPS协议之中使用的加密技术,SSL可以让采用SSL的服务器认证采用SSL的客户端,并且在客户端和服务器之间保持一种加密的连接,在建立了加密连接的过程之中,客户和服务器都可以以产生名叫“会话密钥”的东西,他是一种用于加密和解密消息的对称密钥,基于https协议的服务器可以使用这个客户的对称密钥来建立会话。
关于Cookies是以key-value对的方法记录会话跟踪的内容,服务器利用响应包头set-cookie来发送cookie信息:
响应报头的格式为:NAME=VALUE Comment=value Domain=value Max-Age=value Path=value Secure Version=1*DIGIT
1.关于session的主要接口方法如下:
public Object getAttribute(String name)
public Enumeration getAttributeNames()
public void setAttribute(String name,Object value)
public HttpSession getSession()
2.关于cookie的主要接口方法如下:
public String getComment()
public void setComment(String c)
public String getName()
public String getValue()
public String setValue(String newValue)
public String getPath()
吐槽阶段:!!!
这次ACM预选赛决赛实在是坑了个爹阿看这次排名有木有,亲们有没有发现第二题谁都没做出来有木有!?
对的,这个题的验证答案数据有问题!!而我们恰好在这个上面浪费了两个小时,写了个巨大的测试数据跑阿跑阿跑,就是找不出来BUG我去
还有比赛题目的难度完全是倒序呀- -b 当我颤抖着双手捧起最后一道题的时候,我笑喷了,一个若干关键字的大排序
还好我学过C++ :-P 直接用<algorithm>的stable_sort写了五行AC掉哇哈哈哈 还是没能入围 尽管AC三个排了41..明年有机会再见吧..(真是日了写验证答案的人- -)