JSP 知识基本
from:http://blog.csdn.net/caipeichao2/article/details/38589293
more:http://www.2cto.com/kf/web/jsp/4.html
JSP的全称是Java Server Pages。它的本质其实就是Servlet,在运行的过程中会编译成Servlet代码。在JSP中可以访问数据库,记录用户的选择信息,访问JavaBean组件。
JSP与CGI的差别。一、性能更加优越,JSP可以直接在HTML网页中嵌入动态的元素,而不需要单独引用CGI文件。二、JSP是已经编译好的,持续运行的程序,一次载入可以服务多次请求,而CGI每次都要载入程序再执行,执行完成之后程序就退出了。三、Java是拥有强大的企业级Java API,包括JDBC,JNDI,EJB,JAXP等。四、JSP页面可以和servlet一起使用。
JSP处理流程。
- 首先是服务器收到一个请求。服务器判断这个请求是JSP请求,因此将JSP传递给JSP引擎。
- JSP引擎从磁盘中读取JSP文件并将其转换成Servlet类。这种转换只是简单的把文本替换成println语句,将所有的JSP元素转换成Java代码。
- JSP引擎将Servlet类编译成字节码,然后将原始请求传递给Servlet引擎。
- Web服务器中的某个组件会调用Servlet引擎,然后载入并执行Servlet类。一个Servlet对象可以服务多次请求。
- 在执行的过程中,Servlet产生HTML格式的文本输出并将其存放在HTTP response中上交给服务器。
- Web服务器以静态的HTML网页形式将HTTP response返回到浏览器中。
JSP的生命周期和Servlet类似,只不过多了一个编译的过程。分为四个阶段:
- 编译阶段。Servlet容器将JSP编译成Servlet代码,再将Servlet编译成字节码。
- 初始化阶段。加载对应的Servlet类,调用jspInit()方法。
- 执行阶段。调用\_jspService()方法。
- 销毁阶段。调用jspDestroy()方法。
基本语法
JSP只是在html的基础上嵌入一些动态的元素。下面是HelloWorld代码:
- <html>
- <%
- out.println("hello world");
- %>
- </html>
以上代码中的<% %>就是动态元素。JSP中所有的特殊语法如下:
<% %>:用于表示一段Java代码。这段代码在编译之后会放在_jspService()方法中。
<%! %>:多了一个叹号,也用于表示一段Java代码,但是这段代码编译之后会放在JSP生成的Servlet类中,因此可以用它定义方法或者成员变量。
<%@ %>:多了一个@符号,是JSP指令,用于对JSP文件进行设置。
<%= %>:多了一个等号,相当于out.println()。
<%-- --%>:这是注释。不会在返回结果中显示。
JSP指令。可以设置的指令有三种:
- <%@ page %>
- <%@ include %>
- <%@ taglib %>
page指令可以设置的属性如下:
- buffer 设置out对象缓冲区的大小。
- autoFlush 控制out对象的缓冲区。
- contentType 指定当前JSP页面的MIME类型和字符编码
- errorPage 指定当JSP页面发生异常时要转向的页面
- isErrorPage 指定当前JSP页面是否可以作为另外页面的错误页面。错误页面中可以直接使用exception隐含变量获取错误信息。
- extends 指定Servlet从哪个类继承
- import 导入要使用的包
- info 定义JSP页面的描述信息
- isThreadSafe 指定JSP页面是否线程安全
- language 指定编程语言,默认为Java
- session 指定JSP页面是否使用session
- isELIgnored 指定是否指定EL表达式。
- isScriptingEnabled 指定脚本元素是否能被使用。如果为false,那么JSP中如果出现<% %>就会发生错误。
include指令用于包含一个文件。语法为<%@ include file="xxx"%>。在编译的时候起作用。
taglib指令用于载入一个自定义标签库。语法为<%@ taglib uri="uri" prefix="xx" %>
动作元素
- <jsp:scriptlet> 和 <% %> 是等价的。
- <jsp:expression> 和 <%= %> 是等价的。
- <jsp:include> 包含文件,在执行的过程中起作用。
- <jsp:useBean> 初始化一个 JavaBean 组件
- <jsp:setProperty> 给 JavaBean 设置属性
- <jsp:getProperty>
- <jsp:forward> 向另外一个 JSP 文件传递请求。
- <jsp:plugin> 在生成的页面中包含 Applet 和 JavaBean 对象。在执行的过程中会被替换成 embed 或者 object 标签。
- <jsp:element> 动态创建 XML 元素。
- <jsp:attribute> 定义动态创建的 XML 元素属性
- <jsp:body> 动态创建 XML 元素的主体。
- <jsp:text> 与 CDATA 连用,显示 CDATA 中的内容,但不执行 CDATA中的标签动作。比如以下代码:
- <jsp:text><![CDATA[
- <hello></hello>
- <jsp:world/>
- ]]></jsp:text>
最后输出的结果是:
- <hello></hello>
- <jsp:world/>
里面的 <jsp:world/> 并没有被执行。
所有的动作元素都包含id和scope属性。id用于通过PageContext获取动作元素,scope用于定义对象的寿命。
useBean、setProperty、getProperty的用法。useBean的作用是引入一个JavaBean,需要提供id和class两个参数。id就是变量的名称,class就是变量的类型。setProperty可以放在useBean的标签里面,表示初始化的时候调用。如果沿用现有的JavaBean,那么标签里面的语句是不会调用的。
- <jsp:useBean id="test" class="test.TestBean">
- <jsp:setProperty name="test" property="name" value="Value"/>
- </jsp>
动态创建元素的代码如下:
- <jsp:element name="employee">
- <jsp:attribute name="name">张三</jsp:attribute>
- <jsp:body>张三是销售部经理</jsp:body>
- </jsp:element>
该代码会产生:
- <employee name="张三">张三是销售部经理</employee>
所谓隐含对象就是已经被系统定义好的一些对象,可以直接使用。JSP中有以下几个隐含对象:
- request
- response
- out 可以使用out.flush来将缓冲区中的数据全都发送到客户端。
- session
- application 与整个应用的上下文有关。
- config
- pageContext 与JSP页面的上下文有关。
- page 在JSP页面中相当于this指针。
- exception 这个对象中包含了从先前页面中包含的异常信息。
- <%
- out.println("Hello world");
- session.put("lastTime", System.currentTimeInMillis());
- %>
request对象常用的方法如下:
EL表达式语言
EL就是Expression Language,目的是简化JSP的语法。来看几个例子就明白了。
- ${test} 会翻译成<%=test%>
- ${test.name} 会翻译成 <%=test.getName()%>
- ${sessionScope.username}} 会翻译成 <%=session.getAttribute("username")%>
只有sessionScope、requestScope等才会翻译成getAttribute("xxx"),而其他的对象,会翻译成getXXX()。
EL中还支持四则运算、逻辑运算,语法和Java中的一样。EL中有隐含对象:pageContext、pageScope、requestScope、sessionScope、applicationScope、param、paramValues、header、headerValues、cookie、initParam。param等价于request.getParameter,paramValues等价于request.getParameterValues,返回的是字符串数组。
Java Bean
- 有默认构造函数
- 成员变量都是私有的,只能通过getXX和setXX来访问
- 可序列化(implements Serializable。可选,在分布式系统中才有意义)
Cookie
- Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT; path=/; domain=example.com
Servlet中的Cookie类有以下方法:
JSP中可以向应答中添加多个Cookie,每个Cookie对象是一个键值对,可以往HTTP应答中写入多个Cookie。以下是一个示例:
- Cookie cookie = new Cookie("key", "value");
- cookie.setMaxAge(86400);
- response.addCookie(cookie);
读取Cookie可以通过request.getCookies获取一个Cookie数组。由于可能存在多个Cookie名字相同的情况,因此不能直接通过名称直接获得相应的Cookie。
删除Cookie可以将maxAge设为0,然后调用response.addCookie加入到应答中。
Session
sessionid可以放在Cookie中,也可以放在post表单中,也可以放在url中,比如http://example.com/page;JSESSIONID=45678943。
Session对象常用的方法如下:
Session的过期时间可以在web.xml文件中配置,单位为分钟,Tomcat中默认的超时时间是30分钟。
- <session-config>
- <session-timeout>15</session-timeout>
- </session-config>
Session和Cookie的区别。分析区别之前还是先弄清楚是什么导致了它们的不同。在HTTP刚发明的时候,还没有Session的概念,因此开发者只能将重要的数据保存在Cookie中。但是Cookie的数据是保存在浏览器中的,用户可以任意修改,非常不安全。因此有人提出了Session的概念,在Cookie中只保存一串随机生成的SessionID,服务器根据SessionID查找对应的数据,这样,重要的数据就保存在了服务器上,用户无法随意更改,因此比较安全。
JSP过滤器
过滤器的作用是给web请求增加额外的逻辑,每个页面可以被多个过滤器进行处理。过滤器需要在web.xml文件中进行定义,语法如下。过滤器的执行顺序与filter-mapping的定义顺序相同。- <filter>
- <filter-name>FilterName</filter-name>
- <filter-class>TestFilter</filter-name>
- <init-param>
- <param-name>test-param</param-name>
- <param-value>test-value</param-name>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>TestFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
文件上传
浏览器上传文件的时候,HTTP请求中的MIME类型必须为multipart/form-data。文件上传的处理需要使用commons-fileupload库和commons-io库。
在服务端,为了获取文件列表,你需要一个ServletFileUpload对象,这样就可以调用它的parseRequest(request)方法来获得文件列表。为了创建ServletFileUpload,你需要一个DiskFileItemFactory,这个类的作用就是将文件保存到内存中,如果保存不下,就保存到磁盘中。因此需要设置内存的使用量和临时文件的存放路径,分别可以通过setSizeThreshold和setRepository方法。下面是完整的例子。
- DiskFileItemFactory factory = new DiskFileItemFactory();
- // 设置内存中存储文件的最大值
- factory.setSizeThreshold(maxMemSize);
- // 本地存储的数据大于 maxMemSize.
- factory.setRepository(new File("c:\\temp"));
- // 创建一个新的文件上传处理程序
- ServletFileUpload upload = new ServletFileUpload(factory);
- // 设置最大上传的文件大小
- upload.setSizeMax( maxFileSize );
- // 解析上传的文件
- List fileItems = upload.parseRequest(request);
JSTL
在使用JSTL之前首先要下载jakarta-taglibs-standard-x.x.x.zip,并将压缩包中的standard.jar和jstl.jar加入到WEB-INF/lib下。JSTL的所有标签见下图:
变量要用$符号括起来,$是EL表达式的写法,通过EL表达式转换成对应的字符串。下面这个例子展示了变量的用法。
- <fmt:formatNumber value="${balance}" type="currency"/>
JSTL函数的用法。下面这个例子中,将函数与if标签结合使用。
- <c:if test="${fn:contains(theString, 'test')}">
- <p>Found test string<p>
- </c:if>
数据库操作
下面的代码实现了JSP中数据库的连接,并且创建了一个名为snapshot的数据源。- <sql:setDataSource var="snapshot" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/test" user="root" password="123456"/>
下面的代码实现了数据库的请求。
- <sql:query dataSource="${snapshot}" var="result">
- SELECT * FROM users;
- </sql:query>
下面的代码展示了参数替换的用法。
- <sql:query dataSource="${snapshot}" var="result">
- SELECT * FROM users WHERE id = ?;
- <sql:param value="${userId}"/>
- </sql:query>
自定义标签
自定义标签需要完成两件事,一件是定义标签的规则,有哪些属性,哪些属性是必填的,格式是怎样的,可以包含哪些子标签。另外一件事就是实现标签的功能。定义标签规则。新建一个tld文件,对于这个例子,文件的内容可以这样写:
- <taglib>
- <tlib-version>1.0</tlib-version>
- <jsp-version>2.0</jsp-version>
- <short-name>Test TLD</short-name>
- <tag>
- <name>hello</name>
- <tag-class>com.pc.HelloTag</tag-class>
- <body-content>empty</body-content>
- </tag>
- </taglib>
实现标签的功能。这个例子里面就是简单地将标签替换成Hello World字符串。代码可以写成这样:
- public class HelloTag extends SimpleTagSupport {
- public void doTag() {
- JspWriter out = getJspContext().getOut();
- out.println("Hello world!");
- }
- }
获取标签里面的内容。首先要修改TLD,使其允许在标签里面存放文本。其次是通过invoke函数获取标签里面的内容。
- <body-content>scriptless</body-content>
- StringWriter writer = new StringWriter();
- getJspBody().invoke(writer);
获取标签上的属性。首先要修改TLD,允许标签设置哪些属性。其次,JSP引擎会调用setXXX函数传递属性值。
- <tag>
- <attribute>
- <name>message</name>
- </attribute>
- </tag>
- // 由系统自动调用。
- public void setMessage(String message) {
- this.message = message;
- }