JSP的简要概括和简单的使用
一、什么是jsp以及它的底层原理
JSP这三个字母是Java Server Pages的缩写,见名知意java的服务器页面
为什么会出现jsp呢?先看一段servlet的代码:
@WebServlet("/aser")
public class AServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码格式
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write("<html>\n");
writer.write("<head>\n");
writer.write("<title>ser</title>\n");
writer.write("</head>\n");
writer.write("<body>\n");
writer.write("<h1>这是Servlet</h1>\n");
writer.write("</body>\n");
writer.write("</html>\n");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
中间那么大一块就在浏览器输出了一个这是Servlet
,是不是很复杂,各种标签需要我们去包裹起来,要是这样开发,程序员的开发成本也太大了,于是就由此衍生了jsp,让jsp帮我们干这些繁琐的事情,来看jsp的代码如何实现上面的:
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="500.jsp" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>这是Servlet</h1>
</body>
</html>
是不是像是HTML一样的简写写法,那么jsp的底层原理到底是什么?为什么就能如此简单的实现servlet中如此复杂的代码,按说这个只能servlet来完成的,带着这个问题,看下面的源码:
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports
这里是jsp被翻译出来的java类,继承了HttpJspBase
类,这个又继承了HttpServlet
类,于是jsp的这个类间接继承了HttpServlet类。于是,我们可以得出一个结论:
JSP其实就是Servlet程序
可以看下面的源码,_jspService方法中也是用到我们手写方式,这就是底层帮我们干了我们觉得很麻烦的事,这也很好的解释了JSP就是Servlet程序了,底层仍然是Servlet。
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
"500.jsp", true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title>$Title$</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write("<h1>这是主页</h1>\n");
out.write(" </body>\n");
out.write("</html>\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
这就可以解释为什么它可以干Servlet的事了。
二、JSP的三大指令
-
page 用于声明jsp : jsp=html+page指令
page 里面常见的属性:
- contentType=“text/html;charset=UTF-8” 指定jsp文件的mime类型和字符集
- import=“java.util.*” 为jsp的脚本中的Java代码去导包
- errorPage=“500.jsp” 如果当前页面发生异常,就跳转到500.jsp中
- isErrorPage=“true” 承认自己是不是错误处理页面,如果为true就可以使用exception内置对象
-
taglib 用于导入外部资源标签库,jstl
作用:引入外部标签库,通常用于引入jstl标签
-
include 静态包含,一个jsp页面可以包含另一个jsp页面
作用:静态包含 – 两个jsp之间使用静态包含,会被tomcat服务器编译成一个servlet,可以实现脚 本互通
a.jsp: <%@include file="b.jsp"%> <% System.out.println(name); %> b.jsp: <% String name = "wang"; %> 我们访问a.jsp时候,会打印出wang
三、JSP的脚本方式
-
<%! 代码 %> 声明脚本
这种方式,用的还是比较少的,一般用来定义属性和方法,也可以写静态代码块,内部类什么的
-
<%
java代码
%>
这种方式用的比较多,这是代码脚本,因为编译之后,全部都在
_jspService
方法中 -
<%=表达式%>表达式脚本
这用用的比较多,可以看下面的例子:
<% pageContext.setAttribute("key1","pageContext域"); String key1 = (String) pageContext.getAttribute("key1"); out.write(key1); %> pageContext:<%=pageContext.getAttribute("key1")%><br>
上面就可以看出来这种脚本的强大之处了吧,直接可以输出到页面上,非常方便。
四、JSP的九大内置对象
九大对象如下:
request | 请求对象 |
---|---|
response | 响应对象 |
pageContext | jsp的上下文对象 |
session | 会话对象 |
application | ServletContext对象 |
config | ServletConfig对象 |
out | jsp输出流对象 |
page | 指向当前jsp的对象 |
exception | 异常对象 |
这个看一下就行了,知道各个对应什么对象就可以。
五、JSP四大域对象
域对象 | 对应的类 | 作用 |
---|---|---|
pageContext | PageContextImpl类 | 只在当前的jsp界面内起作用 |
request | HttpServletRequest类 | 只在一次请求内起作用 |
session | HttpSession类 | 只在一次会话内有用,关闭浏览器会话结束 |
application | ServletContext类 | 只要web工程没停止,整个范围内都有起作用 |
上面的作用有限顺序从小到大:
pageContext request session application
例子:
a.jsp<%/*pageContext ====>>> request ====>>> session ====>>> application*/ //向着四个域中分别保存数据pageContext.setAttribute("key1","pageContext域");request.setAttribute("key2","request域");session.setAttribute("key3","session域");application.setAttribute("key4","application域");%><%--看这四个域中是否有值--%>pageContext:<%=pageContext.getAttribute("key1")%><br>request:<%=request.getAttribute("key2")%><br>session:<%=session.getAttribute("key3")%><br>application:<%=application.getAttribute("key4")%><br><%--转发到b.jsp--%><jsp:forward page="b.jsp"></jsp:forward>b.jsp<%--看这四个域中是否有值--%>pageContext:<%=pageContext.getAttribute("key1")%><br>request:<%=request.getAttribute("key2")%><br>session:<%=session.getAttribute("key3")%><br>application:<%=application.getAttribute("key4")%><br>
来源:oschina
链接:https://my.oschina.net/u/4364212/blog/4436114