JSP入门基础知识详细版(通俗易懂)

JSP 第一篇:

概述、原理、周期、指令、行为、内置对象、JavaBean

(一) JSP概述以及简单使用

什么是JSP?

JSP全名为Java Server Pages,java服务器页面。JSP是一种基于文本的程序,其特点就是HTML

和Java代码共同存在!

为什么需要JSP?

JSP是为了简化Servlet的工作出现的替代品,Servlet输出HTML非常困难,JSP就是替代Servlet输出HTML的

JSP还有必要学吗

在MVC中,JSP属于展示层,但是JSP却又可以写一定的业务,甚至跑去做数据层的事情,这样开发中就会变得无比混乱,也增加了开发的困难程度,所以将展示层与业务层分开就成为了主流,也就是我们说的前后端分离,但是事无绝对,确实一些比较老的项目仍然在跑jsp,不管你会不会写,你总得碰到能看懂吧,如果已经接近找工作,确实还是以比较流行的技术学习比较好,但是若作为学生,时间还是比较富裕的,很多本科也必然都会讲,学习一下也是挺好的,况且JSP与Servlet也是息息相关的,我认为,学它就是为了知道为什么以后会用别的技术代替它(狗头保命),废话有点多了,还是有一点需要的朋友可以简单看一看,希望给你能有一点帮助

(二) 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);

(三) 声明周期

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() {
  }

(四) 指令

<%@ 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:当前页面发生异常后,会自动跳转到指定的错误页面

    //主页面
    <%@ 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页面上
    
    <error-page>
        <error-code>404</error-code>
        <location>/error.jsp</location>
    </error-page>
    
    <error-page>
        <exception-type>java.lang.NullPointerException</exception-type>
        <location>/error.jsp</location>
    </error-page>
  • isErrorPage:标识当前也是是否是错误页面

    • true:是,可以使用内置对象exception
    • false:否。默认值。不可以使用内置对象exception

(五) 行为

JSP行为(JSP Actions)是一组JSP内置的标签,只书写少量的标记代码就能够使用JSP提供丰富的功能,JSP行为是对常用的JSP功能的抽象和封装。

JSP内置的标签称之为JSP行为,是为了能够和JSTL标签区分开来。(叫做JSP标签也行)

(1) include 行为

上面已经提及到了,include指令是静态包含,include行为是动态包含。其实include行为就是封装了request.getRequestDispatcher(String url).include(request,response)

include行为语法是这样的:

<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)

当然了,现在有静态包含和动态包含,使用哪一个更好呢?答案是:动态包含。

动态包含可以向被包含的页面传递参数(用处不大),并且是分别处理包含页面的(将被包含页面编译后得出的结果再写进包含页面)

【如果有相同名称的参数,使用静态包含就会报错!】!

(2) Param 行为

当使用<jsp:include>和<jsp:forward>行为引入或将请求转发给其它资源时,可以使用<jsp:param>行为向这个资源传递参数

(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%>

(4) directive 行为

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

· <jsp:directive.include file=""/> 相当于<%@include file="" %>

· jsp:directive.page/ 相当于<%@page %>

· jsp:directive.taglib/ 相当于<%@taglib %>

使用该指令可以让JSP页面更加美观!

使用scriptlet行为<jsp:scriptlet>替代<%%>是同样一个道理

(5) javaBean 行为

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

<jsp:useBean id=""/>
<jsp:setProperty name="" property=""/>
<jsp:getProperty name="" property=""/>

(六) JSP内置对象(直接使用)

JSP引擎在调用JSP对应的jspServlet时,会传递或创建9个与web开发相关的对象供jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用

变量名真实类型作用
pageContextPageContext当前页面共享数据,还可以获取其他八个内置对象
requestHttpServletRequest一次请求访问的多个资源(转发)
sessionHttpSession一次会话的多个请求间
applicationServletContext所有用户间共享数据
responseHttpServletResponse响应对象
pageObject当前页面(Servlet)的对象 this
outJspWriter输出对象,数据输出到页面上
configServletConfigServlet的配置对象
exceptionThrowable内置对象exception是java.lang.Exception类的对象

(七) 四种属性范围

到目前为止,我们已经学了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域中,像聊天数据

(八) JavaBean

avaBean就是一个普通的java类,也称之为简单java对象--POJO(Plain Ordinary Java Object),是Java程序设计中一种设计模式,是一种基于 Java 平台的软件组件思想

JavaBean遵循着特定的写法,通常有以下的规则:

有无参的构造函数

成员属性私有化

封装的属性如果需要被外所操作,必须编写public类型的setter、getter方法

上面的文字看起来好像很高大上,javaBean其实非常简单,常见的学生类,书籍类就是按照特定写法、规则编写的一个JavaBean对象

为什么需要使用Javabean

使用javaBean的好处:封装,重用,可读!

JaveBean你可以理解为一辆货车,在你的java端和web页面进行数据传递的载体,你当然可以每个变量单独传递,或者使用集合传递,但是javabean可以使你的数据更有可读性,方便开发时明确变量的意义,也使其他阅读你代码的人能直接你的意图

如果bean类与数据库联合使用,一张表使用bean类,可以使你的代码更加简洁高效,易于理解,现在大多数框架都会使用这种机制。

JSP行为--JavaBean

JSP技术提供了三个关于JavaBean组件的动作元素,即JSP行为(标签),它们分别为:

jsp:useBean【在JSP页面中查找javaBean对象或者实例化javaBean对象】

jsp:setProperty【设置javaBean的属性】

jsp:getProperty【获取javaBean的属性】

※ JSP:useBean

<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"/>

JSP 第二篇:

EL运算符:概述、内置对象、数据回显、自定义函数、EL函数库

(一) 概述

EL:Expression Language 表达式语言

它的作用就是替换和简化jsp页面中java代码的编写

EL表达式支持简单的运算符:加减乘除取摸,逻辑运算符。empty运算符(判断是否为null),三目运算符

1693413-20190906170727572-205119902.png
1693413-20190906170737173-691676821.png

empty运算符可以判断对象是否为null,用作于流程控制!

三目运算符简化了if和else语句,简化代码书写

<%
    List<Person> list = null;
%>
${list==null?"list集合为空":"list集合不为空"}

(二) 内置对象

EL表达式主要是来对内容的显示,为了显示的方便,EL表达式提供了11个内置对象

pageContext 对应于JSP页面中的pageContext对象(注意:取的是pageContext对象)

pageScope 代表page域中用于保存属性的Map对象

requestScope 代表request域中用于保存属性的Map对象
 sessionScope 代表session域中用于保存属性的Map对象

applicationScope 代表application域中用于保存属性的Map对象

param 表示一个保存了所有请求参数的Map对象

paramValues 表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个string[]

header 表示一个保存了所有http请求头字段的Map对象

headerValues 同上,返回string[]数组。

cookie 表示一个保存了所有cookie的Map对象

initParam 表示一个保存了所有web应用初始化参数的map对象

(三) 数据回显

<%--模拟数据回显场景--%>
<%
    User user = new User();
    user.setGender("male");

    //数据回显
    request.setAttribute("user",user);
%>


<input type="radio" name="gender" value="male" ${user.gender=='male'?'checked':'' }>男
<input type="radio" name="gender" value="female" ${user.gender=='female'?'checked':'' }>女

(四) 自定义函数

EL自定义函数用于扩展EL表达式的功能,可以让EL表达式完成普通Java程序代码所能完成的功能

开发HTML转义的EL函数

我们有时候想在JSP页面中输出JSP代码,但是JSP引擎会自动把HTML代码解析, 输出给浏览器。此时我们就要对HTML代码转义。

步骤:

编写一个包含静态方法的类(EL表达式只能调用静态方法),该方法很常用,Tomcat都有此方法,可在webappsexamplesWEB-INFclassesutil中找到

public static String filter(String message) {

        if (message == null)
            return (null);

        char content[] = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuilder result = new StringBuilder(content.length + 50);
        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
            case '<':
                result.append("&lt;");
                break;
            case '>':
                result.append("&gt;");
                break;
            case '&':
                result.append("&amp;");
                break;
            case '"':
                result.append("&quot;");
                break;
            default:
                result.append(content[i]);
            }
    }
    return (result.toString());

在WEB/INF下创建tld(taglib description)文件,在tld文件中描述自定义函数

<?xml version="1.0" encoding="ISO-8859-1"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1">

    <tlib-version>1.0</tlib-version>
    <short-name>myshortname</short-name>
    <uri>/zhongfucheng</uri>

    <!--函数的描述-->
    <function>

        <!--函数的名字-->
        <name>filter</name>

        <!--函数位置-->
        <function-class>utils.HTMLFilter</function-class>

        <!--函数的方法声明-->
        <function-signature>java.lang.String filter(java.lang.String)</function-signature>
    </function>

</taglib>

在JSP页面中导入和使用自定义函数,EL自定义的函数一般前缀为"fn",uri是"/WEB-INF/tld文件名称"

<%@ page language="java" contentType="text/html" pageEncoding="UTF-8" %>
<%@taglib prefix="fn" uri="/WEB-INF/ideal.tld" %>

<html>
<head>
    <title></title>
</head>
<body>

//完成了HTML转义的功能
${fn:filter("<a href='#'>点这里</a>")}

</body>
</html>

(五) EL函数库(fn方法库)

  • 由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用。
  • 其实EL函数库就是fn方法库,是JSTL标签库中的一个库,也有人称之为fn标签库,但是该库长得不像是标签,所以称之为fn方法库
  • 既然作为JSTL标签库中的一个库,要使用fn方法库就需要导入JSTL标签!要想使用JSTL标签库就要导入jstl.jar和standard.jar包!
  • 所以,要对fn方法库做测试,首先导入开发包(jstl.jar、standard.jar)

在JSP页面中指明使用标签库

<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

JSP 第三篇:

JSTLd的简单认识、三个常用对象

JSTL全称为 JSP Standard Tag Library 即JSP标准标签库

JSTL作为最基本的标签库,提供了一系列的JSP标签,实现了基本的功能:集合的遍历、数据的输出、字符串的处理、数据的格式化等等!

为什么使用

EL表达式可以很方便地引用一些JavaBean以及其属性但是仍然不够完美,它不能遍历集合,做逻辑的控制。

Scriptlet的可读性,维护性,重用性都十分差!JSTL与HTML代码十分类似,遵循着XML标签语法,使用JSTL让JSP页面显得整洁,可读性非常好,重用性非常高,可以完成复杂的功能!

在JSP中不推荐使用scriptlet输出,推荐使用JSP标签

使用JSTL标签库步骤

  • 导入jstl相关jar包
  • 引入标签库:taglib指令:<%@ taglib %>
  • 使用标签

Core标签库

core标签库是JSTL的核心标签库,实现了最基本的功能:流程控制、迭代输出等操作

core标签库的前缀一般是c

常用的三个JSTL标签

(一) c:if

属性:

test 必须属性,接受boolean表达式

如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容

  • 注意:c:if 标签没有else情况,想要else情况,则可以在定义一个c:if标签
<%--如果带过来的名字是admin,那么可以登陆--%>
    <c:if test="${param.name=='admin'}">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="登陆">
    </c:if>
    
    <%--如果带过来的名字是admin888,那么就是注册--%>
    <c:if test="${param.name=='admin888'}">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="注册">
    </c:if>

(二) c:choose

它相当于java代码的switch语句

使用choose标签声明,相当于switch声明
使用when标签做判断,相当于case
使用otherwise标签做其他情况的声明,相当于default

<c:choose>
        <c:when test="${param.name=='admin'}">
            欢迎管理员
        </c:when>
        <c:when test="${param.name=='user'}">
            欢迎用户
        </c:when>
        <c:otherwise>
            识别不出你是谁
        </c:otherwise>
</c:choose>

(三) c:forEach

forEach为循环标签,相当于Java中的while和for

之前我们在使用EL表达式获取到集合的数据,遍历集合都是用scriptlet代码循环,现在我们学了forEach标签就可以舍弃scriptlet代码

向Session中设置属性,属性的类型是List集合

向Session中设置属性,属性的类型是List集合

遍历session属性中的List集合,items:即将要迭代的集合。var:当前迭代到的元素

 <%
    List list = new ArrayList<>();
    list.add("admin");
    list.add("zhangsan");
    list.add("lisi");
    
    session.setAttribute("list", list);
%>

=====================================================
 <c:forEach  var="list" items="${list}" >
    ${list}<br>
</c:forEach>

Map对象有稍微地不一样保存的不是每个迭代的对象,而是Map.Entry

 <%
    Map map = new HashMap();
    map.put("1", "tom");
    map.put("2", "jack");
    map.put("3", "jack”);
    
    session.setAttribute("map",map);
%>
    
<c:forEach  var="me" items="${map}" >   
    ${me.key}  ${me.value}<br>
</c:forEach>

特别说明:本篇中 第二 第三篇部分内容转载来自 java3y 所写jsp第四篇内容,在作者基础上摘出片段,附上链接

https://juejin.im/post/5a7919045188257a76630a23

结尾:

如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !^_^

如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)

在这里的我们素不相识,却都在为了自己的梦而努力 ❤

一个坚持推送原创Java技术的公众号:理想二旬不止

16bc64e5e727d294?w=258&h=258&f=jpeg&s=27413

转载于:https://www.cnblogs.com/ideal-20/p/11475803.html

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值