JSP基础

本文详细介绍了JSP技术,包括其组成元素、生命周期、内置对象、JavaBean使用、Cookie及JSP动作,帮助读者掌握JSP在Web开发中的应用。

JSP(Java Servlet Pages)是一个简化的Servlet设计,实现了在服务器端Java中使用HTML标签显示动态网页技术,也是一个JavaEE标准。与PHP相比,JSP具有更好的跨平台性、安全性,适用于开发大型的企业级Web应用程序。

1、JSP页面组成元素

JSP页面由六个元素构成:静态内容、指令、表达式、小脚本、声明和注释

指令

jsp指令包裹在<%@ %>之间。其中page指令常位于jsp页面的顶端,用于对页面的编码等进行指定,如下所示定义页面编码方式为UTF-8,脚本语言为Java,并且导入java.util类下的包

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

include指令用于将一个外部文件嵌入到当前jsp页面中并完成页面jsp语句的解析

taglib指令可以自定义标签并在页面中使用

注释

在jsp中可以使用三种注释:HTML注释、JSP注释和Java注释,只有html注释在客户端的源码中可以看到

  <!-- html注释,在客户端源码中能看到 -->
  <%--  JSP注释,在客户端不可见--%>
  <%
    //java单行注释
    /*Java多行注释*/
  %>

声明

包裹在<%! %>之间,用于定义页面中使用的变量或方法,

<%!
    String s = "你好,欢迎使用JSP!";   //定义字符串

    int add(int x, int y) {    //定义一个相加函数
        return x + y;
    }
%>

脚本

包裹在<% %>之间,用于在jsp页面执行Java代码

<%
    out.println(s);     //浏览器页面输出字符串s
%>

表达式

包裹在<%= %>之间,用于定义在页面执行的表达式,注意结尾没有分号;

<%--    表达式调用之前定义的相加函数--%>
    x+y结果为<%=add(1,2) %>

JSP的生命周期

当有用户第一次请求index.jsp页面时,JSP引擎会把文件转换成为一个servlet,调用jspInt()方法生成一个字节码文件.class保存在Tomcat/work对应的项目目录下。生成的servlet常驻内存,只有jsp页面发生改变后,JSP才会重新编译字节码文件。当有另一个请求index.jsp文件时,这时不必重新生成字节码文件,而是调用jspService()方法创建一个新的线程来处理该请求,返回已经生成的字节码文件。通过多线程的方式执行可以降低对于系统资源的消耗,提高系统并发量与响应时间,但是也带来了多线程的同步问题。

2、JSP内置对象

内置对象是WEB容器创建的一组对象,不使用new创建就可以使用的对象,常用的有九类:out、request、response、session、application、Page、pageContent、exception、config

out对象

out对象通过缓冲区向jsp页面输出内容,常用println向缓冲区输入内容,缓冲区会在满了之后或者页面生成前自动输出到页面,也可以通过flush()手动输出。通过clear()清空缓冲区内容,但是在flush之后调用clear()会保存,而应该用clearBuffer()代替。还可以getXxx()获取缓冲区相关信息。如下使用out进行输出:

    <h1>绝句</h1>
    <%
        out.println("两个黄鹂鸣翠柳,<br/>");
        out.println("一行白鹭上青天。<br/>");
        out.flush();                        //手动刷新缓冲区
        out.println("窗含西岭千秋雪,<br/>");
//        out.clear();                        //清空缓冲区,放这里出错
        out.clearBuffer();
        out.println("门泊东吴万里船。<br/>");
    %>
    缓冲区大小:<%=out.getBufferSize()%>字节<br>
    缓冲区剩余:<%=out.getRemaining()%>字节<br>
    自动刷新缓冲区:<%=out.isAutoFlush()%>

输出结果如下,在前两句之后通过flush()将缓冲区内容手动输出。之后由于使用clearBuffer()清空了缓冲区,导致第三句没有被输出。

Request对象

request对象封装了用于处理浏览器请求的方法。通过setCharacterEncoding()设置页面编码方式,防止页面中文出现乱码,setAttribute()可以将对象以键值对的方式保存在request对象中,之后通过getAttribute()方法可以取出保存的对象。通过getSession()可以获取服务器中保存的session信息,通过getParameter()可以获取客户端发来的请求中的参数,如果传来的是数组则需要使用getParameterValues()来接收。还可以通过其他getXxx()之类的方法来获取请求相关的信息,比如请求的地址、协议类型,服务器端口号、文件地址等。

如下为前端发送一个表单信息,后端接收处理显示的例子:

    <h3>用户注册</h3>
    <form action="regServer.jsp" method="post">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>爱好:</td>
                <td>
                    <input type="checkbox" name="favorite" value="read">看书
                    <input type="checkbox" name="favorite" value="music">听音乐
                    <input type="checkbox" name="favorite" value="movie">看电影
                </td>
            </tr>
            <tr>
                <td><input type="submit" value="提交"></td>
            </tr>
        </table>
    </form>

    <a href="regServer.jsp?username=小李">通过get方式传递参数</a>
<body>
    <h3>request接收请求</h3>
    <%
        request.setCharacterEncoding("utf-8");  //设置编码方式
        request.setAttribute("info","一个字符串");      //通过request保存参数对象
    %>
    用户名:<%=request.getParameter("username")%>   <%--获取单个参数--%>
    <br>
    爱好:
    <%
        String[] hobbies=request.getParameterValues("favorite");    //接收数组参数
        if (hobbies!=null){
            for (int i = 0; i < hobbies.length; i++) {
                out.print(hobbies[i]+"&nbsp;&nbsp;");
            }
        }
    %>
    <br>
    保存的参数对象:<%=request.getAttribute("info")%><br>
    请求的MIME类型:<%=request.getContentType()%><br>
    协议类型:<%=request.getProtocol()%><br>
    服务器主机号:<%=request.getServerName()%><br>
    服务器端口号:<%=request.getServerPort()%><br>
    客户端地址:<%=request.getRemoteAddr()%><br>
    文件的相对路径:<%=request.getContextPath()%><br>
</body>

运行结果如下

   

Response对象

response包含了服务器响应请求的相关信息,通过response来设置服务器给客户端返回的响应的信息。例如通过setContentType()设置响应类型,除了可以通过out对象进行输出,response也提供了PrintWriter对象用于输出内容,而且其输出内容总是先于out对象的输出,除非使用out.flush()强制先输出。

通过response.sendRedirect()重定向请求,其本质相当于客户端重新发送了一次请求,客户端的地址会改变,而且会重新生成请求对象。而请求转发是服务器端的自身行为,客户端不可知,其浏览器的url地址不会发生改变,而且可以在转发中传递request、response对象。

        response.setContentType("text/html;charset=UTF-8");
        out.print("这是out对象输出的信息<br>");
        PrintWriter printWriter=response.getWriter();
        printWriter.println("这是Response对象Print Writer输出的信息<br>");

        response.sendRedirect("regServer.jsp"); //重定向请求
        request.getRequestDispatcher("regServer.jsp").forward(request,response);    //请求转发

Session对象

Session是客户端在第一次访问服务器时创建,并一直保持到浏览器所有与服务器有关页面关闭之前的状态对象,用于在不同浏览器页面之间切换时标识用户。

Session的生命周期有创建、活动、销毁。当客户端第一次访问jsp,服务器会为当前会话创建一个sessionId,之后每次客户端访问服务器都会携带这个sessionId供服务器进行校验。注意除非浏览器与服务器所有的会话都关闭,否则在页面内跳转或者新打开一个页面,都属于本次Session。而当所有页面关闭后,重新打开后服务器会创建一个新的sessionId给客户端,但是之前的session仍然存在,直到超时或者手动结束其生命周期。

    <%
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date date=new Date(session.getCreationTime());              //获取session创建时间
        out.print("session创建时间:"+sdf.format(date));
        session.setAttribute("username","小李");              //设置session参数
        session.setMaxInactiveInterval(100);                //设置session最大生存时间为100秒
    %>
    Session的ID:<%=session.getId()%><br>
    获取Session的attribute属性:<%=session.getAttribute("username")%>
    <%
        session.invalidate();               //销毁当前会话
    %>

也可以在web.xml文件中配置session超时的时间:

    <session-config>
        <session-timeout>30</session-timeout>       <!--三十分钟后销毁-->
    </session-config>

Session钝化:正常情况下session对象会保存到服务器的内存,但是当session数量过大或者服务器关闭时,服务器会把session暂时序列化存储到Tomcat/work/Catalina/服务器名/应用名/session.ser文件中,当服务器再次启动再从文件中反序列化到内存中 

Application对象

application用于存放不同用户之间可以共享的全局变量,开始于服务器启动,终止于服务器关闭。

通过setAttribute()和getAttribute()可以对变量进行设置和获取。

Page对象

page对象是指jsp页面本身,类似于Java对象的this。

通过toString()方法可以打印页面jsp对象名@哈希code,equals()比较两个对象,getClass()返回class对象

pageContent对象

相当于页面各种功能对象的集合体,可以通过getXxx()获取其他对象。例如getOut()获得out对象,getSession(),getPage(),getRequest(),getResponse()。

也可以通过setAttribute()/getAttribute()设置和获取属性

可以通过forward()导航到指定页面,include()包含页面内容

config对象

包含Servlet初始化所要用到参数(键值对)以及服务器有关信息

getServletContext()返回服务器相关信息,getInitParameter()返回初始化信息

exception对象

页面运行中发生异常所产生的对象。如果要在当前页面使用该对象需要设置page指令isErrorPage="true",通过errorPage指定页面发生异常时交给哪个页面处理。

例如在一个页面中使用1/0抛出一个除以0的异常,交给exception.jsp页面处理

<%@page errorPage="exception.jsp" %>
    <%=1/0%>

<--异常处理页面exception.jsp-->
<%@ page isErrorPage="true" %>
    异常描述信息:<%=exception.getMessage()%><br>
    异常的toString:<%=exception.toString()%><br>
    异常栈轨迹:
    <%
        exception.printStackTrace();
    %>

3、使用JavaBean

JavaBean是指符合特定规范的Java类,使用它可以减少代码重复编写、冗余,明确功能分区,提高代码可维护性。其设计原则包括四个,首先该类为public,其次包含无参构造方法,其属性为private,通过get/set方法进行获取和设置。如下所示为一个符合规则的Student类:

public class Student {                  //1、公有类
    private String name;                //2、属性私有
    private int age;

    public Student() {                   //3、无参构造方法
    }

    public String getName() {           //4、get与set方法
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

可以使用Java引入包的方式使用JavaBean,在jsp页面使用page指令import所需的JavaBean即可和普通Java类一样使用

<%@page import="modules.Student" %>     <!--引入所需JavaBean类-->
<%
    Student s=new Student();
    s.setName("小明");
    s.setAge(24);
%>
学生姓名:<%=s.getName()%><br>
年龄:<%=s.getAge()%>

还可以通过JSP的动作元素在JSP页面使用JavaBean,动作元素为符合XML语法规则的标签,用于为请求处理阶段提供信息。例如<jsp:useBean><jsp:setProperty><jsp:getBean>三个是与使用JavaBean有关的。此外还有与Document有关的<jsp:root>、<jsp:text>等,与XML标签有关的<jsp:attribute>、<jsp:body>等,<jsp:include><jsp:forward>

<jsp:useBean>引入JavaBean对象,id属性为JavaBean的对象名,class属性指出引用哪个类,scope定义作用域范围,默认为当前页面page。如果作用域内存在该id的对象,则引入该对象,否则创建一个该id的对象。

<jsp:setProperty>为JavaBean的对象赋值,共有三种使用方式。第一种是和表单关联,表单在提交后会把name值和JavaBean类的变量进行比对,如果一样则调用set方法设置对象的值。比如客户端表单name=age,Student变量也有age,则调用setAge()为age赋值。通过property指定所需要赋值的变量,如果填"*",默认比对所有变量。第二种方式是手动赋值,通过value字段为property字段赋值。第三种方式是request参数赋值,通过param="request参数名"为 property字段赋值。

<jsp:getProperty>获取指定对象的指定property属性值。也可以直接调用该对象的getXxx()方法获取。

<!--客户端提交的表单-->   
     <form action="JavaBean.jsp" method="post">
        <table>
            <tr>
                <td>姓名:</td>
                <td><input type="text" name="name"></td>
            </tr>
            <tr>
                <td>年龄:</td>
                <td><input type="text" name="age"></td>
            </tr>
            <tr>
                <td><input type="submit" value="提交"></td>
            </tr>
        </table>
    </form>

<!--服务器端接收的jsp-->
    <%--引入Student类并创建myStudent对象--%>
    <jsp:useBean id="myStudent" class="modules.Student" scope="page"></jsp:useBean>

    <%--使用表单设置值--%>
    <jsp:setProperty name="myStudent" property="*"></jsp:setProperty>
    <%--手动设置property--%>
    <jsp:setProperty name="myStudent" property="name" value="小明"></jsp:setProperty>
    <%--通过request参数设置property--%>
    <jsp:setProperty name="myStudent" property="age" param="age"></jsp:setProperty>

    学生姓名:<%=myStudent.getName()%><br>               <!--直接调用get方法获取属性-->
    年龄:<jsp:getProperty name="myStudent" property="age"/>       <!--通过jsp动作获取属性-->

JavaBean的作用域范围共有四种,由小到大:Page、Request、Session、Application。Page仅为当前页面可见对象。Request为一个请求内可见,比如页面请求转发时,仍然属于一个请求,此时前一个页面内的JavaBean对象仍然可用。Session为一次会话可见,只要页面没有关闭,在规定时间内打开的页面都属于一个会话。Application为整个应用可见,服务器开始到关闭都属于一个应用。在作用域内可以通过getAttribute()方法获取到可见的对象。例如在一个页面内将对象myStudent保存到session中,在另一个页面通过session获取myStudent对象:

    <%    //通过getAttribute获取作用域内的对象
        Student student=(Student)session.getAttribute("myStudent");         
    %>
    学生姓名:<%=student.getName()%>
    年龄:<jsp:getProperty name="myStudent" property="age"/>       <!--通过jsp动作获取属性-->

在JavaBean出现之前,jsp页面不仅负责页面的展示,而且还包括数据读取、处理和业务逻辑等操作,非常不利于业务扩展和大型程序的开发。JavaBean出现之后,可以使用它来封装业务逻辑和数据模型,使jsp页面功能得到分离,提高了代码可维护性,这个开发模式也被称为模型1(Module1)。

4、Cookie

由于http协议具有无状态性,即浏览器每一次给服务器发送请求时,服务器都会把请求当作一个新的浏览器发来的,不会记住之前是否访问过。为了“记住”浏览器客户端,需要存储一些信息来辨识,除了之前使用session在服务器端存储之外,还可以使用cookie在客户端存储信息。由于cookie保存在本地,容易造成数据泄露,因此常保存一些不重要的用户信息,比如浏览记录、用户设置等,两者区别如下:

Cookie本质是一个字符串,因此有时在设置cookie时会因字符串编码而报错,此时可以存储前先将字符串进行编码,取出cookie时再解码

        String encodeName=URLEncoder.encode("小明","utf-8");     //对字符串进行编码
 
        Cookie nameCookie=new Cookie("username",encodeName);          //创建cookie
        Cookie hobbyCookie=new Cookie("hobby","听音乐");
        nameCookie.setMaxAge(1000);                             //设置cookie生存周期一千秒
        hobbyCookie.setMaxAge(1000);
        response.addCookie(nameCookie);                         //保存cookie
        response.addCookie(hobbyCookie);

        Cookie[] cookies=request.getCookies();                   //获取cookie
        for (Cookie c:cookies){
            if (c.getName().equals("username")) {                 //获取cookie名
                String decodeName=URLDecoder.decode(c.getValue(),"utf-8");    //获取cookie值并进行解码
                out.print("用户名:"+decodeName);                            
            }
            if (c.getName().equals("hobby"))
                out.print("爱好:"+c.getValue());
        }

        nameCookie.setMaxAge(0);                                //设置cookie失效
        hobbyCookie.setMaxAge(0);

5、jsp动作

除了JavaBean使用的动作之外,JSP还有许多其他动作。例如include动作可以引入另一个jsp页面,其效果与include指令相同,但include动作包含的是页面的执行结果,即另一个页面先编译成servlet再包含,而include指令包含的是页面的源代码,因此如果子页面经常改变需要重新编译,则使用include动作单独编译更好,而如果子页面固定不变,使用include指令更快。

使用forward动作完成页面请求转发操作,其效果等同request.getRequestDispatcher("login.jsp").forward(request,response);

并且在转发时可以使用param传递新的参数

    <jsp:forward page="login.jsp">
    <%--转发时传递参数--%>
        <jsp:param name="email" value="test@163.com"/>      
    </jsp:forward>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值