假如說我們要在一個Servlet裏面動態的迴應一個html界面,我們應該怎麼辦呢?首先應該是
getWriter(),然後是不斷的一行一行的writer.write("html代碼");
jsp其實可以看作是html裏面插入了java代碼,這就是jsp
jsp在第一次被訪問時,會被web容器,翻譯成Servelt,在執行過程:
第一次訪問:--->index.jsp---->index.java---->編譯運行
在tomcat目錄下的work裏面可以找到,如果不懂機制怎麼運行,可以到tomcat裏面找到conf配置,打開web.xml,然後 搜.jsp然後就可以找到哪個文件了,
org.apache.jasper.servlet.JspServlet。
訪問時直接會去tomcat的work裏面找這個文件,如果有,直接用這個運行,如果沒有,把jsp對應翻譯成Servlet,java文件
說了jsp會被web容器翻譯成servlet,那麼這三種,第一種,會在service方法中被執行。
第二種,會在service方法中,被輸出,被out輸出。獲得一個Writer
只要抓住中心思想,就是jsp會被翻譯成Servlet文件,第三種JSP註釋,安全性最高,只能在jsp文件裏看見
第二種java註釋,翻譯到Servlet還能看得見,html裏面就看看不見了
jsp文件打開最上面一條語句是,<%@ page language="java" contentType="text/html; charset=UTF-8"
page 的指令是指導jsp翻譯和運行的命令,jsp包括三大指令,
1)page指令-----屬性最多的指令上面那個就是page指令
pageEncoding:當前jsp文件本身的編碼-----內部可以包含contentType,也就是說如果不寫contentType,自動和pageEncoding一樣
contentType:response.setContentType(text/htmlc;charset=UTF-8)
如果出錯了,但是errorPage有沒有處理好,那麼我們可以來一個默認的errorPage,全局的錯誤界面,也就是在這個工程下,只要出錯,就往這裏跑
找到WebContent目錄下面WEB-INF裏的XML對其增加一段代碼
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
<error-page>
在jsp頁面中引入標籤庫(jstl標籤庫,struct2標籤庫)
格式:<%@ taglib uri = "標籤庫地址" prefix = "前綴"%>
jsp被翻譯成Servlet之後,Service方法中有九個對象定義並初始化完畢,我們在jsp腳本中,可以直接使用這九個對象(jsp腳本是啥,往上翻一翻就到了。)
名稱 |
類型 |
描述 |
out |
javax.servlet.jsp.jspWriter |
用於頁面輸出 |
request |
javax.servlet.http.HttpServeltRequest |
|
response |
javax.servlet.http.HttpServletResponse |
|
config |
||
session |
||
application |
||
page |
||
exception |
如果errorPage纔是這個 |
|
pageContext |
javax.servlet.jsp.pageContext |
jsp的頁面容器 |
九大隱式對象不時很好記憶,那麼我們需要想着,爲什麼這九大對象可以直接拿來使用呢?
因爲咱們JSP是要翻譯成Servlet的,並且<%%>只有%沒有!的,就是在那個Service內部,那麼我們就可以想,人家在Service方法裏都定義好了!自然可以拿來用!
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("\r\n");
out.write("<!DOCTYPE html>\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<meta charset=\"UTF-8\">\r\n");
out.write("<title>Insert title here</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("\t");
int i = 1;
System.out.println(i);
out.write('\r');
out.write('\n');
out.write(' ');
out.print(i );
out.write('\r');
out.write('\n');
out.write(' ');
out.write('\r');
out.write('\n');
out.write(' ');
out.print( str );
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>");
} 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);
}
}
out的作用就是向客戶端輸出內容-------out.write(),管他孃的是什麼類型的writer,反正只要是writer,我就給你write
還記得前面三種指令中的page指令(分別是page,include,taglib),有一個屬性叫做,buffer,這個屬性這裏纔用到
1111111111111111
<%="222222222222222" %>
<%
out.write("333333333333");
response.getWriter().write("44444444444444444444");
%>
1.字符串11111111111的,這個本來就是html的內容,所以可以直接變成out輸出
2.222222222的,這個將會被放到out裏面去,因爲這編譯的時候會到out裏面去
3.33333333的,着個一看直接都out輸出了,沒有疑問肯定是out輸出
會發現,這裏輸出的時候,並不是按照我們想象的11111111 2222222222 3333333333 444444這樣的順序輸出的,而是按照4123這樣的順序
爲什麼?因爲tomcat是從response緩衝區裏面獲得內容的,我們out輸入的東西,都會被放在out的緩衝區裏面,tomcat先從response裏面獲得東西,然後再從out裏面獲取。
這就是page的屬性buffer 的作用,buffer的值代表的就是out緩衝區的大小,如果是緩衝區大小是0的話,out緩衝區沒有了,那只有寫到response裏面去了,所以就是按照順序來的。
page和pageContext對象不是一回事,page 看代碼,是頁面本身。
page域(就是pageContext域,簡稱)<request域<session域<application域
2)pageContext可以獲得其他八大對象,這個感覺好像是沒什麼軟用,但是後來搞框架的時候,就可以,假如method(session,request,,,,)直接傳進去一個pageContext
3)pageContext可以存參數值到任意一個域(四個域中),沒毛病。操作如下:
pageContext.setAttribute("name","zhangsan") //存到了pageContext域中
pageContext.setAttribute("name","wangwu",PageContext.SESSION_SCOPE); //存到了session中
pageContext.setAttribute("name","zhaoliu",PageContext.APPLICATION_SCOPE); //存到了,application中
pageContext.getAttribute("name",PageContext.REQUEST_SCOPE);
pageContext.findAttribute("name");
這個雞肋的技能,是從小到大搜索域的範圍搜索name,如果有的話,就停止搜索。明白?
四大作用域的總結:
page:當前jsp的頁面範圍
request:一次請求(並不是一次會話)
session域:一次會話
application:Web應用,web服務器沒關閉。
jsp標籤(動作)
1)頁面包含(動態包含):<jsp:include page = "被包含的頁面"/>
<jsp:include file = "被包含的界面" /> //這種包含就是靜態的包含,開始的時候就直接給放到一起去了。
2) 請求轉發:<jsp:forward page = "轉發的資源" />
//這個直接,就是相當於跳轉到另外一個界面去了。但是地址欄,還是這個界面的,不要忘記了