JSP
什么是jsp
那么什么是jsp呢,其实Jsp的本质是servlet,为了方便servlet程序返回数据给客户端而产生的,在Jsp产生以前,程序员是通过如下方式返回客户端响应数据的(手动拼写HTMl的方式)
public class HtmlServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException { // 设置返回的数据内容的数据类型和编码
response.setContentType("text/html; charset=utf-8");
// 获取字符输出流 Writer writer = response.getWriter();
//输出页面内容!
writer.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">");
writer.write("<html>"); writer.write("<head>");
writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
writer.write("<title>Insert title here</title>");
writer.write("</head>");
writer.write("<body>");
writer.write("这是由 Servlet 程序输出的 html 页面内容!");
writer.write("</body></html>"); }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
在有了jsp以后就可以通过在其中书写,java 代码的形式,动态的拼装html 文件了
jsp是怎么运行的
上面说到了jsp其实是servlet程序,下面我来看下 jsp 是怎么运行的,首先启动程序,然后到tomcat的work\Catalina\localhost 目录下
可以看到day09 这个项目,点开项目,然后可以看到这样的文件
可见JSP 文件是java 文件,打开 index_jsp.java 文件可见代码如下
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
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,
null, 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("\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(" <form action=\"http://localhost:8080/Servlet01/requestServlet\" method=\"post\">\n");
out.write(" 姓名<input type=\"text\" name=\"name\" value=\"张三\">\n");
out.write(" 爱好<input type=\"checkbox\" name=\"hobby\" value=\"篮球\">\n");
out.write(" <input type=\"checkbox\" name=\"hobby\" value=\"网球\">\n");
out.write(" <input type=\"submit\" name=\"提交\">\n");
out.write(" </form>\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);
}
}
}
首先 它继承了HttpJspBase,然后HttpJspBase 又继承了HttpServlet 所有说明JSP文件实质是servlet 程序
然后 JSP 文件的service()方法将原本html的内容 用输出流输出
以上就是,jsp的运行原理。
二 jsp 的九大内置对象
pageContext 当前jsp这个界面里面的一些变量等的值,可以获取其它的内置对象.
request : 当前请求中的(可以使用request 获取当前请求的的一些参数的内容)
response : 响应,当前响应
session : 用于获取当前会话的一些值
config : servletConfig对象(jsp 也是servlet程序 所以这个对象相当于 Servlet 中的ServletConfig 对象)
application : 相当servletContext对象
exception : 异常对象,只有在jsp 的page标签中设置了isErrorPage="true"时这个对象才生效,
out:输出流
page:表示当前servlet对象,使用它不如使用this
三 jsp的四大域对象
首先说一下,四大域对象和九大内置对象不是独立的关系,九点内置对象包含四大域对象,域对象在之前的servlet中介绍过,简单说就是在不同的范围内存取数据时使用。
1.pageContext : 当前page中可以使用 当有两个jsp文件时,一个jsp就获取不到另一个jsp中的数据了。
2.request 再一次请求中都是有效的,常用于请求的转发。比如两个jsp 一个jsp 通过请求转发另一个jsp 中可以通过request 获取值
3.session: 一次会话中的值都是有效,只要没有超过session 的有效时间 就可以从中获取数据,当会话被关闭时失效 ,比如关闭浏览器
4.application(servletContext): 在工程启动的整个过程都是有效的,都可从application取到值,一旦工程停止,失效。
四.out和Writer的区别是什么
out和writer都能向客户端输出内容 那么我们用什么呢
为什么out 后在后面输出呢,这里需要解释一下
当我们执行out.writer()和writer.writer()时,两个输出流分别会把内容放到各自的冲区内 ,当时out 会在jsp中所有代码都执行完以后 执行一个flush()方法 把out 缓冲区里的内容最加到writer 缓冲区的末尾,然后由writer 一次性将所有内容返回。
接下来我们验证一下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
response.getWriter().write("这是writer第一个</br>");
out.write("这是out第一个</br>");
out.flush();
out.write("这是out第二个</br>");
response.getWriter().write("这是writer第二个</br>");
%>
</body>
</html>
结果:
原理图:
首先out和writer缓冲区各自存自己的数据,然后代码手动将out 缓冲区内容flush()到writer缓冲区中(注意这里是手动flush进去的)
图一
然后结果如图二
图二
图三
再次各自往缓冲区中放值,如图三,然后放完值以后,系统在最后自动将out 缓冲区中的数据flush 到writer 末尾(注意这里是自动),结果如图四
图四
最后 系统将writer 中的数据一次性返回给客户端.就有了上面的结果.
这里就有一个疑问 那么我们到底使用 out 还是writer呢 我们来看jsp 的源码
所以使用out
还有一个问题 out 共有两个方法用于向客户端返回值分别是
out.write("</br>");
out.print("12");
当输出字符串的时候都可以正确输出
当输出数字时,out.write()没有正确输出,所以我们需要使用out.print()输出
原因12 被ASCII码转码了.