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的一个子类)

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>简单使用JSP</title>
  5. </head>
  6. <body>
  7. <%
  8. String s = "HelloWorld";
  9. out.println(s);
  10. %>

编译过程是这样子的:
浏览器第一次请求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程序罢了

  1. out.write("\r\n");
  2. out.write("\r\n");
  3. out.write("<html>\r\n");
  4. out.write("<head>\r\n");
  5. out.write("<title>简单使用JSP</title>\r\n");
  6. out.write("</head>\r\n");
  7. out.write("<body>\r\n")

有人可能也会问:JSP页面的代码服务器是怎么执行的?再看回1_jsp.java文件,java代码就直接在类中的service()中

  1. String s = "HelloWorld";
  2. out.println(s);

3. 声明周期

JSP也是Servlet,运行时只有一个实例,JSP初始化和销毁时也会调用Servlet的init()和destroy()方法。另外,JSP还有自己初始化和销毁的方法

  1. public void _jspInit() {
  2. _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
  3. _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
  4. }
  5. public void _jspDestroy() {
  6. }

4. 指令

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>

作用:用于配置JSP页面,导入资源文件
格式: <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %>

  • contentType:相当于response.setContentType()

    • 设置响应体的mime类型以及字符集
    • 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
      1. pageEncoding="characterSet | ISO-8859-1"
  • import:导包

    1. 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页面上

404 /error.jsp

java.lang.NullPointerException /error.jsp

  1. - isErrorPage:标识当前也是是否是错误页面
  2. - true:是,可以使用内置对象exception
  3. - false:否。默认值。不可以使用内置对象exception
  4. <a name="YOsfF"></a>
  5. # 5. 行为
  6. JSP行为(JSP Actions)是一组JSP内置的标签,只书写少量的标记代码就能够使用JSP提供丰富的功能,JSP行为是对常用的JSP功能的抽象和封装。<br />JSP内置的标签称之为JSP行为,是为了能够和JSTL标签区分开来。(叫做JSP标签也行)
  7. <a name="C4J33"></a>
  8. ## 5.1 include 行为
  9. 上面已经提及到了,include指令是静态包含,include行为是动态包含。其实include行为就是封装了request.getRequestDispatcher(String url).include(request,response)<br />include行为语法是这样的:
  10. ```html
  11. <jsp:include page=""/>
  12. 静态包含:<%@ include file="被包含页面"%>
  13. 动态包含:<jsp:include page="被包含页面" flush="true">
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>包含页头和页尾进来</title>
  5. </head>
  6. <body>
  7. <jsp:include page="head.jsp"/>
  8. <jsp:include page="foot.jsp"/>
  9. </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的语法

  1. <jsp:forward page=""/>
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title>访问1.jsp就跳转到head.jsp</title>
  5. </head>
  6. <body>
  7. <jsp:forward page="head.jsp"/>
  8. </body>
  9. </html>

如果我要传递参数,就要在forward行为嵌套param行为
在跳转到head.jsp时传入参数username值为aaa

  1. <jsp:forward page="head.jsp">
  2. <jsp:param name="username" value="aaa"/>
  3. </jsp:forward>
  1. <%
  2. String ss = request.getParameter("username");
  3. %>
  4. 获取到的参数是:
  5. <%=ss%>

5.4 directive 行为

directive的中文意思就是指令。该行为就是替代指令<%@%>的语法的

  1. <jsp:directive.include file=""/> 相当于<%@include file="" %>
  2. jsp:directive.page/ 相当于<%@page %>
  3. jsp:directive.taglib/ 相当于<%@taglib %>

使用该指令可以让JSP页面更加美观!
使用scriptlet行为<jsp:scriptlet>替代<%%>是同样一个道理

5.5 javaBean 行为

JSP还提供了操作javaBean对象的行为,暂时记住JSP提供了javaBean行为来操作简单类即可!后面详细解释:

  1. <jsp:useBean id=""/>
  2. <jsp:setProperty name="" property=""/>
  3. <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个内置对象都支持以下的方法:

  • setAttribute(String name, Object o )
  • getAttribute(String name)
  • removeAttribute(String name)

    ※ 应用场景

  1. request:如果客户向服务器发请求,产生的数据,用户看完就没用了,像这样的数据就存在request域,像新闻数据,属于用户看完就没用的
  2. session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐
  3. 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的属性】

  1. **※ JSPuseBean**
  2. ```html
  3. <jsp:useBean>

标签用于在指定的域范围内查找指定名称的JavaBean对象:
存在则直接返回该JavaBean对象的引用。
不存在则实例化一个新的JavaBean对象并将它以指定的名称存储到指定的域范围中。
语法:

  1. jsp:useBean id="实例化对象的名称" class="类的全名" scope="保存范围"/>

果JSP不支持<jsp:useBean>这个行为,我们要使用Person类是这样使用的

  1. <%--这里需要导入Person类--%>
  2. <%@ page import="domain.Person" %>
  3. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  4. <html>
  5. <head>
  6. <title></title>
  7. </head>
  8. <body>
  9. <%
  10. // new出对象
  11. Person person = new Person();
  12. person.setName("admin");
  13. System.out.println(person.getName());
  14. %>
  15. </body>

但是我们使用<jsp:useBean>就非常整洁,不用导包,不用new对象

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4. <title></title>
  5. </head>
  6. <body>
  7. <jsp:useBean id="person" class="domain.Person" scope="page"/>
  8. <%
  9. person.setName("zhongfucheng");
  10. System.out.println(person.getName());
  11. %>
  12. </body>
  13. </html>

JavaBean中无参的构造函数改成有参的,会出现异常,这是因为<jsp:useBean>
的内部原理是 new了一个无参的构造函数
※ JSP:setProperty

  1. <jsp:setProerty name="对象名称" property="属性名" param="参数名" value="值">

四种模式

  1. <jsp:setProperty name="对象名称" property="*"/>自动匹配
  2. <jsp:setProperty name="对象名称" property="属性名称"/>指定属性
  3. <jsp:setProperty name="对象名称" property="属性名称" param="参数名称"/>指定参 数【很少用】
  4. <jsp:setProperty name="对象名称" property="属性名称" value="内容"/>指定内容【很 少用】

当我们没有学习到<jsp:setProperty>时,我们获取表单的信息,然后导入到javaBean对象中是这样的一种情况:

  1. <jsp:useBean id="person" class="domain.Person" scope="page"/>
  2. <%
  3. int age = Integer.parseInt(request.getParameter("age"));
  4. person.setAge(age);
  5. System.out.println(person.getAge());
  6. %>

而我们使用<jsp:setProperty>后,代码更少,功能更强大

  1. <jsp:useBean id="person" class="domain.Person" scope="page"/>
  2. <%--指定属性名称为age--%>
  3. <jsp:setProperty name="person" property="age"/>
  4. <%
  5. System.out.println(person.getAge());
  6. %>

代码少很直观的可以看出来,但是强大在什么地方呢?
表单提交过来的数据都是字符串,在我们没有用<jsp:setProperty>前,我们存储设置int类型或其他非字符串类型的数据是需要强转的!但是<jsp:setProperty>不需要我们强转,它内部自动帮我们转换了!
下面再通过自动匹配来感受它的强大

  1. <jsp:useBean id="person" class="domain.Person" scope="page"/>
  2. <%--property的值设置为*就代表自动匹配--%>
  3. <jsp:setProperty name="person" property="*"/>
  4. <%
  5. System.out.println(person.getAge());
  6. System.out.println(person.getName());
  7. %>

为什么Property的值可以将表单传递过来的数据封装到JavaBean对象中?
JavaBean属性名要和表单的name的名称一致
是通过反射来做的,调用了内省的方法!
※ JSP:getProperty

  1. <jsp:getProperty name="对象名" property="属性名"/>
  1. <%--使用<jsp:getProperty>输出--%>
  2. <jsp:getProperty name="person" property="username"/>
  3. <jsp:getProperty name="person" property="age"/>