您的位置:首页 > Web前端 > JavaScript

JSP&Servlet6(一) --- 初探JSP

2017-06-12 22:55 274 查看
前面总结完了Servlet相关的基础知识, 现在来学习总结一下JSP.

1. JSP简介

JSP全称Java Server Pages, 是一种动态网页开发技术. JSP与Servlet是一体两面的, 因为JSP网页最终会被容器转译为Servlet源代码, 然后自动编译为.class文件, 再载入.class文件, 最后生成Servlet对象.

下面我们以一个Hello World的例子, 来分析以下JSP和Servlet的关系, 以及JSP的生命周期.

例: 用JSP输出Hello Word, 并分析转译的Servlet代码.

JSP代码如下:

<html>
<head>
<title>Hello JSP</title>
</head>
<boay>
<h1>Hello World!</h1>
</body>
</html>


这就是最简单地JSP的一段代码, 那么, 我们看看它转译成Servlet将会变成什么样子. 转译后的Servlet代码如下(将会略去部分代码, 只保留部分代码):

pubilc final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourseDependent{
//略...

public void _jspInit(){
//略...
}

public void _jspDestroy(){
//略...
}

public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException{
//以下开始为JSP里面的隐式对象
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
//以上为JSP里面的隐式对象
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;

try{
//略...
out.write("<html>\n");
out.write("<head>\n");
out.write("<title>Hello JSP</title>\n");
out.write("</head>\n");
out.write("<body>\n");
out.write("<h1>Hello World!</h1>\n");
out.write("</body>\n");
out.write("</html>\n");
}catch(Throwable t){
//略...
}finally{
//略...
}
}
}


JSP的生命周期

通过上面转译后的Servlet代码可以看到主要有三个重要的方法:_jspInit(), _jspDestroy(), _jspService()这三个方法, 对比Servlet, 我们可以大概猜到这三个方法分别是请求来临时的初始化操作, 请求来临时的善后操作, 请求来临时的处理操作.

那么, 这三个方法时从哪里来的呢? 如果我们想对请求来临的初始化/处理/善后想进行特别的处理是否应该重定义这三个方法?

在上述转译后的Servlet代码中, 我们可以看到, 该转译后的Servlet继承了org.apache.jasper.runtime.HttpJspBase类, 那么我们来大致查看一下HttpJspBase类中都有哪些方法, 他们的关系有时如何, HttpJspBase类代码如下:

public abstract class HttpJspBase extends HttpServlet implements HttpJspPage{
//HttpJspBase是一个抽象类,说明该类的所有方法都应该由其子类来实现.
public final void init(ServletConfig config) throws ServletException{
super.init(config);
jspInit();
_jspInit();
}
//略...

public final void destroy(){
jspDestroy();
_jspDestroy();
}

public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
_jspService(request, response);
}

public void jspInit(){}
public void _jspInit(){}
public void jspDestroy(){}
public void _jspDestroy(){}
public abstract void _jspService(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}


通过上述代码可以看出Servlet的init()/destroy()/service()里面都调用了哪些方法.

init(): 其中调用了jspInit()和_jspInit().

_jspInit()是由转译后的Servlet进行自动重定义.

如果想自己设置初始化的操作, 可以重定义jspInit().

destroy(): 其中调用了jspDestroy()和_jspDestroy().

_jspDestroy()是由转译后的Servlet进行自动重定义.

如果想自己设置善后的操作, 可以重定义jspDestroy().

service(): 其中调用了_jspService(), JSP转译为Servlet后, 其中所定义的核心代码都在_jspService()中.

2. Servlet到JSP的转换

例: 将下面的Servlet代码转换为JSP代码

Servlet代码如下:

@WebServlet("/hello.view")
public class FirstServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();         String name = request.getParameter("name");

out.println("<html>");
out.println("<head>");
out.println("<title>hello Servlet</title>");
out.println("<head>");
out.println("<body>");
out.println("<h1> hello!" + name + "!</h1>");
out.println("</body>");
out.println("</html>");

out.close();
}
}


转译成JSP代码如下:

<%@page contentType = "text/html" pageEncoding = "UTF-8"%>
<html>
<head>
<title>hello servlet</title>
</head>
<body>
<%
String name = request.getParameter("name");
%>
<h1>hello! <%= name%></h1>
</body>
</html>


JSP代码格式总结

JSP的代码格式与HTML基本类似. 如等这些标签都遵循和HTML一样的格式.

JSP中穿插Java代码: 写在<%%>中, 如下:

<% String name = request.getParameter(“name”); %>

JSP中穿插赋值语句: 写在<%=%>中, 如下:

<h1> hello!” + name + “!</h1> 转化为JSP代码为:<h1> hello! <%= name%></h1>

JSP中指示元素的格式: <%@指示元素 [属性=”值”]* %>, 如下:

<%@page contentType = “text/html” pageEncoding = “UTF-8” %>

类成员或方法的声明: 写在<%!%>中, 具体示例使用方法后面会详细谈到.

3. 指示元素

什么是指示元素?

指示元素是在容器将JSP转译成Servlet代码的时候, 声明的一些必须遵守的信息. 在JSP中, 主要由三种常用的指示类型: page, include, taglib.

page: 告知容器如何转译目前的JSP网页.

include: 告知容器将别的JSP包含进来转译.

taglib: 告知容器如何转译这个页面的标签库(后面会谈到).

page指示类型

page指示类型使用示例:

<%@page import = "java.util.Date" %>
<%@page contentType = "text/html pageEncoding = UTF-8" %>

...


上述代码中的import/contentType/pageEncoding都是page指示元素的属性.

page指示元素的属性

import: 告知容器在转译JSP时, 必须在源代码包括的import陈述, 比如需要用到的Java的包等.

contentType: 告知容器在转译JSP时, 使用的HttpServletRequest的setContentType(), 属性值即为setContentType()方法的属性值.

pageEncoding: 告知容器这个JSP网页文字的编码, 以及内容类型附加的charset设置.

还有一些不常用的属性在此暂不列出.

include指示类型

include指示类型使用示例:

假设有如下代码: includeDemo.jsp

<%@ page contentType="text/html" pageEncoding="UTF-8" language="java" %>
<%@include file="header.jspf"%>
<h1>include 示范主体</h1>
<%@include file="foot.jspf" %>


header.jspf代码如下(.jspf文件是被.jsp文件include的文件, 本质上就是.jsp文件):

<html>
<head>
<%@page pageEncoding="UTF-8" %>
<title>include 示范开头</title>
</head>
<body>


foot.jspf代码如下:

<%@page pageEncoding="UTF-8" %>
</body>
</html>


在上述includeDemo.jsp进行转译时, 会将header.jspf和foot.jspf包含进来进行转译, 也就是说将<%@include file = “header.jspf” %>和<%@include file = “foot.jspf” %>分别用header.jspf和foot.jspf文件进行替换.

include指示元素包含进来的JSP们, 最终只会转译生成一个Servlet文件, 而后面提到的的网页则会生成一个个独立的Servlet.

4. 声明元素 Scriptlet元素 表达式元素 注释元素

声明元素

声明元素的语法为: <%! 类成员声明或方法声明%>, 示例如下:

<%!
String name = "dela";
String passwd = "123456";

boolean checkUser(String name, String passwd){
return this.name.equals(name) && this.passwd.equals(passwd);
}
%>


上述代码转译后在Servlet中会生成如下代码:

pubilc final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourseDependent{

String name = "dela";
String passwd = "123456";

boolean checkUser(String name, String passwd){
return this.name.equals(name) && this.passwd.equals(passwd);
}

//略...
}


你可能会想, 这样声明和直接写Java代码(即后面提到的Scriptlet元素)有什么区别, 不都是转译到Servlet中了吗?

当然不是, 声明元素中所写的Java代码将会生成HttpJspBase类中像init()/destroy()/service()这样的方法成员或数据成员. 而直接写的Java代码, 都将转译到_jspService()方法中.

声明元素的作用之一就是前面提到的: 我们想自定义JSP的一些初始和结尾工作时, 可以在声明元素中重定义jspInit()和jspDestroy()方法.

Scriptlet元素

Scriptlet元素就是前面提到的直接在JSP中编写Java代码, 格式为: <% Java语句 %>. 其示例前面都有提到过, 在此不过多赘述.

表达式元素

表达式元素就是前面提到的赋值语句, 格式为<%=Java表达式 %>.其示例前面也都有提到过, 在此不过多赘述.

注释元素

注释元素就是在JSP中的注释, 格式为:< !– 注释 – > .

5. 隐式对象

简单的讲, 就是将Servlet里面一些常用的对象设置为JSP里面的隐式对象. 比如, JSP中的out就是Servlet里面的PrintWriter对象, request就是HttpServletRequest对象. 隐式对象的存在就是为了简化Java代码, 我们不必要再通过getxxxx()来取得这些常用的对象.

JSP隐式对象的说明如下:

- out: 转译后对应JspWriter对象, 其内部关联一个PrintWriter对象.

- request: 转译后对应HttpServletRequest对象.

- response: 转译后对应HttpServletResponse对象.

- config: 转译后对应ServletConfig对象.

- application: 转译后对应ServletContext对象.

- session: 转译后对应HttpSession对象.

- pageContext: 转译后对应pageContext对象, 它提供了JSP页面资源的封装, 并可设置页面范围属性.

- exception: 转译后对应Throwable对象, 代表由其他JSP页面抛出的异常对象, 只会出现于JSP错误页面(isErrorPage属性设置为true的JSP页面).

- page: 转译后对应this.

需要注意的是: 隐式对象只能在<%%>与<%=%>之间使用, 因为隐式对象为_jspService()里面的局部变量, 无法在其他成员方法中使用.

6. 错误处理

在JSP中, 可用page指示元素的errorPage属性来指定错误处理页面来进行错误处理. 如下:

<%@page errorPage = "error.jsp" %>


然后在error.jsp中将page元素的isError属性设置为true. 随后在error.jsp中可通过打印隐式对象exception的错误信息(如异常堆栈信息), 以便后续处理.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: