1. JSP 概述以及简单使用
1.1 什么是JSP?
JSP全名为Java Server Pages,java服务器页面。JSP是一种基于文本的程序,其特点就是 HTML 和 Java 代码共同存在!
1.2 为什么需要JSP?
JSP是为了简化Servlet的工作出现的替代品,Servlet输出HTML非常困难,JSP就是替代Servlet输出HTML的
1.3 JSP还有必要学吗?
在MVC中,JSP属于展示层,但是JSP却又可以写一定的业务,甚至跑去做数据层的事情,这样开发中就会变得无比混乱,也增加了开发的困难程度,所以将展示层与业务层分开就成为了主流,也就是我们说的前后端分离,但是事无绝对,确实一些比较老的项目仍然在跑jsp,不管你会不会写,你总得碰到能看懂吧,如果已经接近找工作,确实还是以比较流行的技术学习比较好,但是若作为学生,时间还是比较富裕的,很多本科也必然都会讲,学习一下也是挺好的,况且JSP与Servlet也是息息相关的,我认为,学它就是为了知道为什么以后会用别的技术代替它(狗头保命),废话有点多了,还是有一点需要的朋友可以简单看一看,希望给你能有一点点帮助
2. JSP的工作原理
Tomcat 访问任何的资源都是在访问 Servlet!,当然了,JSP也不例外!JSP本身就是一种Servlet。为什么说JSP本身就是一种Servlet呢?
其实JSP在第一次被访问的时候会被编译为HttpJspPage类(该类是HttpServlet的一个子类)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>简单使用JSP</title>
</head>
<body>
<%
String s = "HelloWorld";
out.println(s);
%>
编译过程是这样子的:
浏览器第一次请求1.jsp时,Tomcat会将1.jsp转化成1_jsp.java这么一个类,并将该文件编译成class文件。编译完毕后再运行class文件来响应浏览器的请求。
以后访问1.jsp就不再重新编译jsp文件了,直接调用class文件来响应浏览器。当然了,如果Tomcat检测到JSP页面改动了的话,会重新编译的。
既然JSP是一个Servlet,那JSP页面中的HTML排版标签是怎么样被发送到浏览器的?我们来看下上面1_jsp.java的源码就知道了。原来就是用write()出去的罢了。说到底,JSP就是封装了Servlet的java程序罢了
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<title>简单使用JSP</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n")
有人可能也会问:JSP页面的代码服务器是怎么执行的?再看回1_jsp.java文件,java代码就直接在类中的service()中
String s = "HelloWorld";
out.println(s);
3. 声明周期
JSP也是Servlet,运行时只有一个实例,JSP初始化和销毁时也会调用Servlet的init()和destroy()方法。另外,JSP还有自己初始化和销毁的方法
public void _jspInit() {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
public void _jspDestroy() {
}
4. 指令
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
作用:用于配置JSP页面,导入资源文件
格式: <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %>
contentType:相当于response.setContentType()
- 设置响应体的mime类型以及字符集
- 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
pageEncoding="characterSet | ISO-8859-1"
import:导包
import="{package.class | package.*}, ..."
errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
```html //主页面 <%@ page contentType=”text/html;charset=UTF-8” language=”java” errorPage=”error.jsp” %>
//错误后转到的页面 <%@ page contentType=”text/html;charset=UTF-8” language=”java” isErrorPage=”true” %>
我们发现地址栏是没有变化的,所以属于是服务器跳转。以上的做法是单个页面设置的,如果我会有很多错误(JSP多的情况下,错误就会多),单个设置太麻烦了!
我们可以在web.xml文件中全局设置错误页,只要发生了404错误或者空指针异常的错误都会跳转到error.jsp页面上
- isErrorPage:标识当前也是是否是错误页面
- true:是,可以使用内置对象exception
- false:否。默认值。不可以使用内置对象exception
<a name="YOsfF"></a>
# 5. 行为
JSP行为(JSP Actions)是一组JSP内置的标签,只书写少量的标记代码就能够使用JSP提供丰富的功能,JSP行为是对常用的JSP功能的抽象和封装。<br />JSP内置的标签称之为JSP行为,是为了能够和JSTL标签区分开来。(叫做JSP标签也行)
<a name="C4J33"></a>
## 5.1 include 行为
上面已经提及到了,include指令是静态包含,include行为是动态包含。其实include行为就是封装了request.getRequestDispatcher(String url).include(request,response)<br />include行为语法是这样的:
```html
<jsp:include page=""/>
静态包含:<%@ include file="被包含页面"%>
动态包含:<jsp:include page="被包含页面" flush="true">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>包含页头和页尾进来</title>
</head>
<body>
<jsp:include page="head.jsp"/>
<jsp:include page="foot.jsp"/>
</body>
jsp行为包含文件就是先编译被包含的页面,再将页面的结果写入到包含的页面中(1.jsp)
当然了,现在有静态包含和动态包含,使用哪一个更好呢?答案是:动态包含。
动态包含可以向被包含的页面传递参数(用处不大),并且是分别处理包含页面的(将被包含页面编译后得出的结果再写进包含页面)
【如果有相同名称的参数,使用静态包含就会报错!】!
5.2 Param 行为
当使用<jsp:include>和<jsp:forward>
行为引入或将请求转发给其它资源时,可以使用<jsp:param>
行为向这个资源传递参数
5.3 forward 行为
在Servlet中我们使用request.getRequestDispatcher(String url).forward(request,response)进行跳转。其实forward行为就是对其封装!
我们来看一下forward的语法
<jsp:forward page=""/>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>访问1.jsp就跳转到head.jsp</title>
</head>
<body>
<jsp:forward page="head.jsp"/>
</body>
</html>
如果我要传递参数,就要在forward行为嵌套param行为
在跳转到head.jsp时传入参数username值为aaa
<jsp:forward page="head.jsp">
<jsp:param name="username" value="aaa"/>
</jsp:forward>
<%
String ss = request.getParameter("username");
%>
获取到的参数是:
<%=ss%>
5.4 directive 行为
directive的中文意思就是指令。该行为就是替代指令<%@%>
的语法的
<jsp:directive.include file=""/> 相当于<%@include file="" %>
jsp:directive.page/ 相当于<%@page %>
jsp:directive.taglib/ 相当于<%@taglib %>
使用该指令可以让JSP页面更加美观!
使用scriptlet行为<jsp:scriptlet>
替代<%%>是同样一个道理
5.5 javaBean 行为
JSP还提供了操作javaBean对象的行为,暂时记住JSP提供了javaBean行为来操作简单类即可!后面详细解释:
<jsp:useBean id=""/>
<jsp:setProperty name="" property=""/>
<jsp:getProperty name="" property=""/>
6. JSP内置对象(直接使用)
JSP引擎在调用JSP对应的jspServlet时,会传递或创建9个与web开发相关的对象供jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用
变量名 | 真实类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据,还可以获取其他八个内置对象 |
request | HttpServletRequest | 一次请求访问的多个资源(转发) |
session | HttpSession | 一次会话的多个请求间 |
application | ServletContext | 所有用户间共享数据 |
response | HttpServletResponse | 响应对象 |
page | Object | 当前页面(Servlet)的对象 this |
out | JspWriter | 输出对象,数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | 内置对象exception是java.lang.Exception类的对象 |
7. 四种属性范围
到目前为止,我们已经学了4种属性范围了。
page【只在一个页面中保存属性,跳转页面无效】
requet【只在一次请求中保存属性,服务器跳转有效,浏览器跳转无效】
session【在一个会话范围中保存属性,无论何种跳转均有效,关闭浏览器后无效】
application【在整个服务器中保存,所有用户都可以使用】
4个内置对象都支持以下的方法:
- request:如果客户向服务器发请求,产生的数据,用户看完就没用了,像这样的数据就存在request域,像新闻数据,属于用户看完就没用的
- session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐
- servletContext:如果客户向服务器发请求,产生的数据,用户用完了,还要给其它用户用,像这样的数据就存在servletContext域中,像聊天数据
8. JavaBean
JavaBean就是一个普通的java类,也称之为简单java对象—POJO(Plain Ordinary Java Object),是Java程序设计中一种设计模式,是一种基于 Java 平台的软件组件思想
JavaBean遵循着特定的写法,通常有以下的规则:
有无参的构造函数
成员属性私有化
封装的属性如果需要被外所操作,必须编写public类型的setter、getter方法
上面的文字看起来好像很高大上,javaBean其实非常简单,常见的学生类,书籍类就是按照特定写法、规则编写的一个JavaBean对象8.1 为什么需要使用Javabean
使用javaBean的好处:封装,重用,可读!
JaveBean你可以理解为一辆货车,在你的java端和web页面进行数据传递的载体,你当然可以每个变量单独传递,或者使用集合传递,但是javabean可以使你的数据更有可读性,方便开发时明确变量的意义,也使其他阅读你代码的人能直接你的意图
如果bean类与数据库联合使用,一张表使用bean类,可以使你的代码更加简洁高效,易于理解,现在大多数框架都会使用这种机制。8.2 JSP行为—JavaBean
JSP技术提供了三个关于JavaBean组件的动作元素,即JSP行为(标签),它们分别为: ```html jsp:useBean【在JSP页面中查找javaBean对象或者实例化javaBean对象】
jsp:setProperty【设置javaBean的属性】
jsp:getProperty【获取javaBean的属性】
**※ JSP:useBean**
```html
<jsp:useBean>
标签用于在指定的域范围内查找指定名称的JavaBean对象:
存在则直接返回该JavaBean对象的引用。
不存在则实例化一个新的JavaBean对象并将它以指定的名称存储到指定的域范围中。
语法:
jsp:useBean id="实例化对象的名称" class="类的全名" scope="保存范围"/>
果JSP不支持<jsp:useBean>
这个行为,我们要使用Person类是这样使用的
<%--这里需要导入Person类--%>
<%@ page import="domain.Person" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<%
// new出对象
Person person = new Person();
person.setName("admin");
System.out.println(person.getName());
%>
</body>
但是我们使用<jsp:useBean>
就非常整洁,不用导包,不用new对象
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<jsp:useBean id="person" class="domain.Person" scope="page"/>
<%
person.setName("zhongfucheng");
System.out.println(person.getName());
%>
</body>
</html>
JavaBean中无参的构造函数改成有参的,会出现异常,这是因为<jsp:useBean>
的内部原理是 new了一个无参的构造函数
※ JSP:setProperty
<jsp:setProerty name="对象名称" property="属性名" param="参数名" value="值">
四种模式
<jsp:setProperty name="对象名称" property="*"/>自动匹配
<jsp:setProperty name="对象名称" property="属性名称"/>指定属性
<jsp:setProperty name="对象名称" property="属性名称" param="参数名称"/>指定参 数【很少用】
<jsp:setProperty name="对象名称" property="属性名称" value="内容"/>指定内容【很 少用】
当我们没有学习到<jsp:setProperty>
时,我们获取表单的信息,然后导入到javaBean对象中是这样的一种情况:
<jsp:useBean id="person" class="domain.Person" scope="page"/>
<%
int age = Integer.parseInt(request.getParameter("age"));
person.setAge(age);
System.out.println(person.getAge());
%>
而我们使用<jsp:setProperty>
后,代码更少,功能更强大
<jsp:useBean id="person" class="domain.Person" scope="page"/>
<%--指定属性名称为age--%>
<jsp:setProperty name="person" property="age"/>
<%
System.out.println(person.getAge());
%>
代码少很直观的可以看出来,但是强大在什么地方呢?
表单提交过来的数据都是字符串,在我们没有用<jsp:setProperty>
前,我们存储设置int类型或其他非字符串类型的数据是需要强转的!但是<jsp:setProperty>
不需要我们强转,它内部自动帮我们转换了!
下面再通过自动匹配来感受它的强大
<jsp:useBean id="person" class="domain.Person" scope="page"/>
<%--property的值设置为*就代表自动匹配--%>
<jsp:setProperty name="person" property="*"/>
<%
System.out.println(person.getAge());
System.out.println(person.getName());
%>
为什么Property的值可以将表单传递过来的数据封装到JavaBean对象中?
JavaBean属性名要和表单的name的名称一致
是通过反射来做的,调用了内省的方法!
※ JSP:getProperty
<jsp:getProperty name="对象名" property="属性名"/>
<%--使用<jsp:getProperty>输出--%>
<jsp:getProperty name="person" property="username"/>
<jsp:getProperty name="person" property="age"/>