讲述完了servlet,我们下边来讲述一下JSP。
1.JSP概述
① JSP为何存在?
我们前边讲过的servlet中可以通过response的getWriter().println()来向客户端浏览器显示内容,但是如果是很多的复杂的html的内容,通过这种方式操作起来就会很麻烦,为了解决这个问题,产生了JSP。
JSP是如何解决这个问题呢?它将HTML页面和Java代码结合了起来,即在JSP页面中既可以写动态内容的Java代码,又可以编写静态的HTML模板元素。而且,编译部署后的JSP被JSP引擎编译成了一个Servlet类型的.java类,因为可以看到他继承了HttpJspBase,从而间接继承了HttpServlet,由此证明它是一个Servlet。原来JSP当中的Java代码写在_jspService()方法中,而原来JSP中的模板元素写在了_jspService()方法中的一个个的out.println()中。这样就不用我们手动的一个一个的去out.print()了,因为这些事情WEB服务器中的JSP引擎都帮助我们做完了。
② JSP是什么
JSP == java server page
本质上是一个发布在服务器上之后的Servlet。所以我们对JSP的理解可以去查看他在WEB服务器上部署后对应的Servlet,一切都可以迎刃而解。
它的特点是可以在静态HTML页面上编写动态Java代码。
2.JSP语法
① JSP中的Java代码我们是要遵循一定的格式的,即要编写在<% %>之中,将这些元素称之为脚本元素。
需要注意的是,脚本元素之间是可以互相访问的,因为其生成的Java代码都是在对应的一个Servlet中的_jspService()方法中。
② JSP中还有一种Java代码是写在<%= Java变量和表达式%>中的,它和脚本元素的不同是写在这个格式里的变量和表达式会将其变量值和表达式的计算值直接输出到浏览器客户端上,作用和out.println()几乎一致。需要注意的是:脚本元素句末必须加;,而表达式元素的句末不可加分号。<%= Java变量或表达式%这种结果可以穿插在JSP的模板元素中,如为某个input元素的value属性赋值。
③ JSP声明
这个JSP声明的作用是在其中可以编写Java方法,不同于脚本元素中不可以编写Java方法(因为其生成的Java代码再_jspService()方法中,方法中不能再定义方法),因为住JSP声明中的内容被放到了_jspService()方法的外边。因为在_jspService()方法的外边,所以JSP声明中不可以使用九个隐含对象。
④ JSP注释
不同于HTML注释<!-- -->,JSP注释<%-- --%>可以阻断脚本片段的执行。
⑤ JSP到_jsp.class之后在服务器上运行中可能出现的错误
第一种是JSP语法的编写错误,导致无法翻译成_jsp.java。提示错误在JSP位置。
第二种是JSP语法没问题,但是被翻译成_jsp.java有问题,导致无法编译成_jsp.class。提示错误在JSP位置。
第三种是_jsp.class运行时出问题,和所有的普通Java问题一样。提示错误在.class源文件的位置。
3. JSP中的九个隐含对象
隐含的意思,就是我们在JSP页面中看不到对象的声明,但是却可以引用。但是看不到并不意味之没有声明,那么这九个隐含对象是在什么地方声明的呢?是在当前JSP页面生成的servlet.java中的_jspService()方法中进行声明的。而我们在JSP中写的Java代码脚本元素最终也存在于_jspService()方法中,那么在运行时我们当然可以使用这九个隐含对象。
① pageContext:是PageContext类型,代表着当前JSP页面,他可以获取其他八个隐含对象及有关当前JSP页面的一切信息。
② request:它是HttpServletRequest类型的
③ response:它是HttpServletResponse类型的。在JSP中几乎不用。
④ session:它是HttpSession类型的,代表浏览器与服务器的一次对话。
⑤ application:是ServletContext类型,代表当前整个WEB应用,可获取与当前WEB应用相关的一切信息。
⑥ config:是ServletConfig类型的,代表当前JSP翻译成的Servlet的配置信息。JSP中几乎不用。
⑦ page :是Object类型的,指代当前JSP翻译成的Servlet的this这个对象。JSP中几乎不用。
⑧ out :是JspWriter类型的,可以通过out.println()直接向浏览器客户端输出显示信息。
⑨ exception:这个对象在JSP中使用时必须满足当前JSP是一个错误页面才可以使用,即设置<% page isErrorPage="true" %>
4.四个域对象的属性操作
① 域对象:在九个隐含对象中含有四个域对象,分别是pageContext/request/session/application。这四个域对象对属性的操作范围依次从小到大。
② 域对象的操作各自属性的方法
getAttribute(String name):获取一个name属性的值
getAttributeNames():获取所有属性的name
setAttribute(String name ,Object obj):为name属性设置一个obj的值
removeAttribute(String name):移除name属性
② 四个域对象的作用范围
pageContext:这个域对象中的属性只可以在当前JSP页面中进行操作,出了这个JSP页面就不是同一个pageContext了。
request:这个域对象中的属性只可以在同一次请求中使用。
session:这个域对象的属性可以在浏览器和服务器之间的一次会话中使用。会话就是浏览器从打开到关闭的一次过程。
application:这个域对象中的属性可以在任何JSP或者Servlet中操作,且都是同一个。
5.请求的重定向和转发
① 请求的转发
首先通过HttpServletRequest对象的getRequestDispacher()方法获取到RequestDispacher对象,并且在此方法中传入要转发到的目标的web根目录下的路径。然后通过这个RequestDispacher对象的forward(request,response)方法实现请求的转发。
② 请求的重定向
调用response的sendRedirect(path)即可将请求重定向到目标页面。
③ 请求的转发和重定向的区别
a:本质区别,转发是将第一次过来的请求中转出去,所以是一次请求;重定向是将第一次过来的请求,换一个请求再发出去,所以发了两次请求。
从本质区别可以看出,当转发请求时,地址栏是初次请求的路径;当重定向请求时,地址栏是最终请求到的目标地址。且转发是同一个请求,重定向是两个不同的请求。
b.第二个重大区别是:转发只能转发给当前web应用的资源;重定向可以发送给任何资源。
c:第三个重大的区别是:对于请求的转发,/代表着当前web应用发布后的根目录;请求的重定向,/代表着当前站点的根目录,就是web应用的上一层。
6. Jsp的指令
① Jsp指令指的是为Jsp引擎设计的,它们并不直接产生任何的输出,而只是告诉引擎如何处理Jsp页面中的除了Jsp指令的其余部分。
② Jsp指令的分类:三种 page / include / taglib。
③ Jsp指令的格式:<%@ page/taglib/include attrName="attrValue"%>
7.Page指令
① Page指令是什么
Page指令定义了当前Jsp页面的各个属性,建议Page指令放在页面的其实位置,便于管理,但是也可以将Page指令放到页面的任何位置同时对页面的所有内容起作用。
② 具体属性
import:同普通的Java类一样,使用前也需要导入相应的包。需要注意的是有一些包中的类不必导入也可以使用,因为当前Jsp对应的Servlet已经默默的引入了某些包了。
session="true/false":这个属性描述当前Jsp是否可用session这个隐含的域对象。
errorPage="":这个属性用于指定当前JSp出现异常时要去的错误页面,Jsp引擎可以自动的通过转发到达我们要去的错误页面。(如我们的错误页面常常定义在WEB-INF下,只有通过转发才可以到达WEB-INF下)
isErrorPage="true/false",判断当前Jsp是否是错误页面。若为true,则可以使用exception这个隐含的对象。
contentType="text/html;charset=utf-8":这个属性描述的是当前Jsp页面的响应内容类型,包括响应内容的格式和响应内容的编码方式。可以在当前Jsp对应的Servlet中看到实际上调用了_jspService()方法中的response.setContentType()方法来设定响应的类型和格式的。
pageEncoding="utf-8":描述当前Jsp页面的编码方式。通常和响应内容的编码方式是一样的。
isELIgnored="true/false":是否不可用EL表达式,一般我们都要在Jsp页面中使用EL表达式,所以我们选择false。
8.include指令
① 作用
通常Jsp引擎在翻译当前Jsp页面的时候会将其他文件中的内容合并进当前Jsp页面转换成的Servlet源文件中,这种源文件级别的引入叫做静态引入。最后的结果就是将被引入的内容原封不动的全部放到了Servlet源文件中,且二者生成同一个的Servlet源文件。
② 格式:<%@ file="/path" %>,需要注意的是/指代的的是当前web应用的根目录。
9.Jsp指令--taglib
① 标签的概念
JSP还提供了一种称之为Action的元素,在JSP页面中使用Action元素可以完成各种通用的JSP页面功能,也可以实现一些处理复杂业务逻辑的专用功能。
Action元素采用XML元素的语法格式,即每个Action元素在JSP页面中都以XML标签的形式出现。
JSP规范中定义了一些标准的Action元素,这些元素的标签名称都以jsp作为前缀,且全部采用小写,如:<jsp:include><jsp:forward>
② <jsp:include path="" flush="true/false">
这个标签用于把另外一个资源的输出内容插入到当前JSP页面的输出内容之中,这种在JSP页面执行时的引入称之为动态引入。
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出内容刷新到客户端。
需要注意的是:动态引入生成了两个对应的Servlet源文件,只是在包含文件中调用某个方法将被包含文件的输出内容与包含文件的输出内容同时输出到了浏览器上。
③ <jsp:forward>标签
这个标签的功能是将请求转发非另外一个资源。和<%request.getRequestDispacher(path).forward(request.response)%>是一样的
需要注意的是:使用JSP标签完成功能相比使用Java代码或者JSP指令来说具有明显的有点,除了书写简便之外,还可以为这些标签添加子标签<param></param>指定传递的参数。
10.Jsp页面中的中文乱码的问题
① 在JSP页面上输入中文,浏览器显示不可以有乱码:只需要保证contenType的charset、pageEncoding和浏览器的编码方式基本都为utf-8即可。
② 当浏览器中页面的表单输入中文作为参数传递时,默认参数在传输过程中使用的编码方式为IOS-8859-1。
对于post请求,我们只需要在调用参数之前设定:request.setCharactorEncoding("utf-8")即可
对于get请求,我们可以通过修改Tomcat的server.xml文件中的Connector节点的属性useBodyEncodingURI="true"即可。