JavaWeb中JSP的一些详细介绍

JavaBean PPT下载

链接:https://pan.baidu.com/s/1NktaMAfUvWh0oEthS_mKFg
提取码:1003

一、简介

1.1.jsp介绍

JSP(全称Java Server Pages)Java服务端页面技术,是JavaEE平台下的技术规范。它允许使用特定的标签在HTML网页中插入Java代码,实现动态页面处理,所以JSP就是HTML与Java代码的复合体。JSP技术可以快速的实现一个页面的开发,相比在Servlet中实现页面开发将变得更加容易。

1.2.常见的视图层技术

HTML、JSP、Thymeleaf等。

1.3.前后端分离开发方式

在前后端分离的项目中真正可以做到“术业有专攻”(开发人员分离) 。前后端分离开发方式中前端页面由专业团队完成页面的开发,并通过请求调用后端的api接口进行数据交互。在开发前端页面的团队中更多关注的技术如:html、CSS、jQuery、Vue、Nodejs等前端技术。前端追求的是:页面表现,速度流畅,兼容性,用户体验等等。而后端团队则更多的是业务的具体实现。在后端开发的团队中更多关注的技术如:设计模式、分布式架构、微服务架构、数据库的操作、Java的性能优化以及数据库优化等技术。前后端分离已成为互联网项目开发的业界标准使用方式,特别是为大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如:浏览器,车载终端,安卓,IOS等等)打下坚实的基础。

二、JSP运行原理

2. 1.JSP技术特点

JSP和Servlet是本质相同的技术。当一个JSP文件第一次被请求时,JSP引擎会将该JSP编译成一个Servlet,并执行这个Servlet。如果JSP文件被修改了,那么JSP引擎会重新编译这个JSP。

JSP引擎对JSP编译时会生成两个文件分别是.java的源文件以及编译后的.class文件,并放到Tomcat的work目录的Catalina对应的虚拟主机目录中的org\apache\jsp目录中。两个文件的名称会使用JSP的名称加”_jsp”表示。如:index_jsp.java、index_jsp.class

2.2 JSP与Servlet区别

JSP以源文件形式部署到容器中。而Servlet需要编译成class文件后部署到容器中。

JSP部署到web项目的根目录下或根目录下的其他子目录和静态同资源位于相同位置。而Servlet需要部署到WEB-INF/classes目录中。

JSP中的HTML代码会被JSP引擎放入到Servlet的out.write()方法中。而在Servlet中我们需要自己通过对字符流输出流的操作生成响应的页面。

JSP更擅长表现于页面显示,Servlet更擅长于逻辑控制。

三、JSP标签的使用

3.1 原始标签

JSP的原始标签在JSP的任何版本中都可以使用。

3.1.1 <%! %> 声明标签

声明标签用于在JSP中定义成员变量与方法的定义。标签中的内容会出现在JSP被编译后的Servlet的class的{}中。通常声明全局变量、常量、方法、类

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  Hello jsp!
  <%! 
	int a = 10; 
    public void add(int a) {
      System.out.println(a);
    } 
    %>
  </body>
</html>

3.1.2 <% %>脚本标签

脚本标签用于在JSP中编写业务逻辑。标签中的内容会出现在JSP被编译后的Servlet的_jspService方法体中。因此在脚本标签中是不允许再声明方法的,只能定义局部变量、循环判断等。其中可包含局部变量、java语句

  <%
    int a = 10;
  %>

3.1.3 <%= %>赋值标签

赋值标签用于在JSP中做内容输出。标签中的内容会出现在_jspService方法的out.print()方法的参数中。注意我们在使用赋值标签时不需要在代码中添加 ”;”。在客户端输出,相当于<%out.println("字符串");%>,在网页中显示某一个变量或某一个表达式的值

<%= a %>

3.1.4原始标签的使用

//使用赋值标签,通过out.print()方法打印
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 <%
    int flag = new Random().nextInt(100);
    String str = "";
    if(flag<=20){
        str = "中奖了";
    }else {
        str = "没中奖";
    }
 %>
<%= str %>
</body>
</html>
//直接在网页显示
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 <%
    int flag = new Random().nextInt(100);
    String str = "";
    if(flag<=20){ %>
     中奖了
<%} else { %>
    没中将
<%}%>
</body>
</html>

实例

第一种写法:

<%--
  Created by IntelliJ IDEA.
  User: oy********
  Date: 2023/11/29
  Time: 20:26
  To change this template use File | Settings | File Templates.
--%>
<%@ page import="com.test.Brand" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<%
    //查询数据库
    List<Brand> brands = new ArrayList<>();
    brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
    brands.add(new Brand(2,"优衣库","优衣库",10,"优衣库,服适人生",2));
    brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
%>

<head lang="en">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="button" value="新增"> <br>
<hr>
<table border="1" cellspacing="0" width="800">
    <tr>
        <th>序号</th>
        <th>品牌名称</th>
        <th>企业名称</th>
        <th>排序</th>
        <th>品牌介绍</th>
        <th>状态</th>
        <th>操作</th>
    </tr>
    <%--@elvariable id="brands" type="java.util.List"--%>
    <c:forEach items="${brands}" var="brand" varStatus="status">
    <tr align="center">
        <td>${brand.id}</td>
        <td>${brand.brandName}</td>
        <td>${brand.enterpriseName}}</td>
        <td>${brand.sort}</td>
        <td>${brand.introduce}</td>
        <td><c:if test="${brand.status} == 1">在售</c:if><c:if test="${brand.status} != 1">售罄</c:if></td>
        <td><a href="#">修改</a> <a href="#">删除</a></td>
    </tr>
    </c:forEach>
</table>
</body>
</html>
package com.test;


public class Brand {
    Integer id;
    String brandName;
    String enterpriseName;
    Integer sort;
    String introduce;
    Integer status;

    public Brand() {
    }

    public Brand(Integer id, String brandName, String enterpriseName, Integer sort, String introduce, Integer status) {
        this.id = id;
        this.brandName = brandName;
        this.enterpriseName = enterpriseName;
        this.sort = sort;
        this.introduce = introduce;
        this.status = status;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }

    public String getEnterpriseName() {
        return enterpriseName;
    }

    public void setEnterpriseName(String enterpriseName) {
        this.enterpriseName = enterpriseName;
    }

    public Integer getSort() {
        return sort;
    }

    public void setSort(Integer sort) {
        this.sort = sort;
    }

    public String getIntroduce() {
        return introduce;
    }

    public void setIntroduce(String introduce) {
        this.introduce = introduce;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }
}
package com.test;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet(urlPatterns = "/demo1" , name = "demo1")
public class ServletDemo1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.准备数据
        List<Brand> brands = new ArrayList<Brand>();
        brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
        brands.add(new Brand(2,"优衣库","优衣库",10,"优衣库,服适人生",2));
        brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));

        //2.存储数据到request域中
        request.setAttribute("brands",brands);

        //3.转发到el-demo.jsp
        request.getRequestDispatcher("/jstl-foreach.jsp").forward(request,response);

    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }
}

第二中写法:

<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %><%--
  Created by IntelliJ IDEA.
  User: oyzh520789
  Date: 2023/11/29
  Time: 19:16
  To change this template use File | Settings | File Templates.
--%>
<%@ page import="com.test.Brand" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
// 脚本标签不允许再声明方法的,只能定义局部变量、循环判断等,因为标签中的内容会出现在JSP被编译后的Servlet的_jspService方法体中,方法体中不能再编写一个方法体,因为他是不被允许的
<%
    //查询数据库
    List<Brand> brands = new ArrayList<>();
    brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
    brands.add(new Brand(2,"优衣库","优衣库",10,"优衣库,服适人生",2));
    brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
%>
//声明标签可以是全局变量、常量、方法、类
<%! public class Brand{
    Integer id;
    String brandName;
    String enterpriseName;
    Integer sort;
    String introduce;
    Integer status;
    public Brand() {
    }

    public Brand(Integer id, String brandName, String enterpriseName, Integer sort, String introduce, Integer status) {
        this.id = id;
        this.brandName = brandName;
        this.enterpriseName = enterpriseName;
        this.sort = sort;
        this.introduce = introduce;
        this.status = status;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrandName() {
        return brandName;
    }

    public void setBrandName(String brandName) {
        this.brandName = brandName;
    }

    public String getEnterpriseName() {
        return enterpriseName;
    }

    public void setEnterpriseName(String enterpriseName) {
        this.enterpriseName = enterpriseName;
    }

    public Integer getSort() {
        return sort;
    }

    public void setSort(Integer sort) {
        this.sort = sort;
    }

    public String getIntroduce() {
        return introduce;
    }

    public void setIntroduce(String introduce) {
        this.introduce = introduce;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }
}%>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="button" value="新增"> <br>
<hr>
    <table border="1" cellspacing="0" width="800">
        <tr>
            <th>序号</th>
            <th>品牌名称</th>
            <th>企业名称</th>
            <th>排序</th>
            <th>品牌介绍</th>
            <th>状态</th>
            <th>操作</th>
        </tr>
        <%
            for (int i = 0; i < brands.size(); i++) {
                //获取集合中的 每一个brand对象
                Brand brand = brands.get(i);

        %>
        <tr align="center">
            <td><%=brand.getId()%></td>
            <td><%=brand.getBrandName()%></td>
            <td><%=brand.getEnterpriseName()%></td>
            <td><%=brand.getSort()%></td>
            <td><%=brand.getIntroduce()%></td>
            <td><%=brand.getStatus() == 1 ? "在售" : "售罄"%></td>
            <td><a href="#">修改</a> <a href="#">删除</a></td>
        </tr>
        <%
            }
        %>
    </table>
</body>
</html>

3.2 JSP的指令标签

JSP指令标签的作用是声明JSP页面的一些属性和动作。

<%@指令名称 属性="值" 属性="值1,值2...."%>

3.2.1 JSP指令标签分类

Page指令标签

page指令用于设置页面的各种属性,如导入包,指明输入内容类型,控制session等,page指令一般位于JSP页面开头,一个JSP页面可以包含多条page指令。

language

设定JSP页面使用的脚本语言。

extends

此jsp页面生成的servlet的父类

import

指定导入的java软件包或类名列表。如果有多个类,中间用逗号隔开

session

设定jsp页面是否用session对象。值为“true|false”,默认为true

bufferr

设定输出的流是否有缓冲区

autoFlush

设定输出流的缓存区是否要自动清除

info

主要表示此jsp网页的相关信息

errorPage

设定jsp页面发生异常时重新指定的页面URL

isErrorPage

指定此JSP页面是否为处理异常错误的页面

contentType

指定MIME类型和JSP页面的编码方式

pageEncoding

指定JSP页面的编码方式

isThreadSafe

设定JSP页面生成的Servlet是否实现SingleThreadModel接口

isELlgnored

指定JSP页面是否忽略EL表达式

<%@ page import="java.util.Random" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8"
         session="true" %>
contentType

设置响应类型和编码,默认使用contentType指定的编码方式。指定响应的 HTTP内容类型。如果未指定 ContentType,默认为TEXT/HTML

contentType属性用来设置JSP页面的MIME类型(MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。)和字符编码,浏览器会根据此显示网页内容。这两种属性都可以用来设置字符编码集类型,同时使用时要保持编码一致。

<%@ page contentType="text/html;charset=UTF-8"%>
pageEncoding

pageEncoding属性用来设置JSP页面字符的编码。

<%@ page pageEncoding="UTF-8"%>
import

import属性可以在当前JSP页面引入JSP脚本代码中需要的其他类在需要引入多个类或包时,可以在中间用逗号隔开或使用多个page指令。

<%@ page import="java.util.Random" %>
<%@ page import="java.io.*,java.util.Date" %>
<%--或者--%>
<%@ page import="java.io.*" %>
<%@ page import="java.util.Date.*" %>
language

当前JSP页面里面可以嵌套的语言。

<%@ page language="java" %>
session

设置JSP页面是否获取session内置对象,默认true。

当访问服务器否个网页的时候,会在服务器端的内存里开辟一块内存,这块内存就叫做session,而这个内存是跟浏览器关联在一起的。这个浏览器指的是浏览器窗口,或者是浏览器的子窗口,意思就是,只允许当前这个session对应的浏览器访问,就算是在同一个机器上新启的浏览器也是无法访问的。而另外一个浏览器也需要记录session的话,就会再启一个属于自己的session。

<%@ page session="true" %>
原理

HTTP协议是非连接性的,取完当前浏览器的内容,然后关闭浏览器后,链接就断开了,而没有任何机制去记录取出后的信息。而当需要访问同一个网站的另外一个页面时(就好比如在第一个页面选择购买的商品后,跳转到第二个页面去进行付款)这个时候取出来的信息,就读不出来了。所以必须要有一种机制让页面知道原来页面的session内容。

问题:如何知道浏览器和这个服务器中的session是一一对应的呢?又如何保证不会去访问其它的session呢?

原理解答:就是当访问一个页面的时候给浏览器创建一个独一无二的号码,也给同时创建的session赋予同样的号码。这样就可以在打开同一个网站的第二个页面时获取到第一个页面中session保留下来的对应信息(理解:当访问第二个页面时将号码同时传递到第二个页面。找到对应的session。)。这个号码也叫sessionID,session的ID号码,session的独一无二号码。

session的两种实现方式(也就是传递方式):第一种通过cookies实现。第二种通过URL重写来实现

第一种方式的理解:就是把session的id 放在cookie里面(为什么是使用cookies存放呢,因为cookie有临时的,也有定时的,临时的就是当前浏览器什么时候关掉即消失,也就是说session本来就是当浏览器关闭即消失的,所以可以用临时的cookie存放。保存再cookie里的sessionID一定不会重复,因为是独一无二的。),当允许浏览器使用cookie的时候,session就会依赖于cookies,当浏览器不支持cookie后,就可以通过第二种方式获取session内存中的数据资源。

第二种方式的理解:在客户端不支持cookie的情况下使用。为了以防万一,也可以同时使用。 如果不支持cookie,必须自己编程使用URL重写的方式实现。 如何重写URL:通过response.encodeURL()方法 。

encodeURL()的两个作用 :

第一个作用:转码(说明:转中文的编码,或者一些其他特殊的编码。就好比如网页的链接中存在中文字符,就会转换成为一些百分号或者其他的符号代替。)

第二个作用:URL后面加入sessionID,当不支持cookie的时候,可以使用encodeURL()方法,encodeUTL()后面跟上sessionID,这样的话,在禁用cookie的浏览器中同时也可以使用session了。但是需要自己编程,只要链接支持,想用session就必须加上encodeURL()。

提示:若想程序中永远支持session,那就必须加上encodeURL(),当别人禁用了cookie,一样可以使用session。

简单的代码例子:在没有使用encodeURL()方法前的代码

<% out.print("<br><a href=" + "/BookServlet/books" + ">书籍管理<a/>");%>

使用Google浏览器

在使用encodeURL()方法后的代码

<% out.print("<br><a href=" + response.encodeURL("/BookServlet/books") + ">书籍管理<a/>");%>

使用Google浏览器

如对比图,当重写URL 的时候,每一次访问的时候都会将sessionID传过来,传过来了,就没有必要再在cookie里读了。

规则:

1.如果浏览器支持cookie,创建session多大的时候,会被sessionID保存再cookie里。只要允许cookie,session就不会改变,如果不允许使用cookie,每刷新一次浏览器就会换一个session(因为浏览器以为这是一个新的链接) 。

2.如果不支持cookie,必须自己编程使用URL重写的方式实现session 。

3. Session不像cookie一样拥有路径访问的问题,同一个application下的servlet/jsp都可以共享同一个session,前提下是同一个客户端窗口。

Session中的一些常用方法说明

isNew():是否是新的Session,一般在第一次访问的时候出现

getid():拿到session,获取ID

getCreationTime():当前session创建的时间

getLastAccessedTime():最近的一次访问这个session的时间。

getRrquestedSessionid: 跟随上个网页cookies或者URL传过来的session

isRequestedSessionIdFromCookie():是否通过Cookies传过来的

isRequestedSessionIdFromURL():是否通过重写URL传过来的

isRequestedSessionIdValid():是不是有效的sessionID

其中下面的结果图对应上面的8个方法

package servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 功能:SessionInfoServlet对session的学习
 * 作者:程序员****
 * 日期:2023/12/17 14:36
 */
@WebServlet(value = "/SessionInfoServlet",name = "SessionInfoServlet")
public class SessionInfoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<br><a href=" + "/SessionInfoServlet" + ">ref<a/><br>");
        out.println("<br><a href=" + response.encodeURL("/SessionInfoServlet") + ">ref<a/><br>");
        //是否是新的Session,一般在第一次访问的时候出现
        out.println("是否是新的Session:"+request.getSession().isNew()+"<br>");
        //拿到session,获取ID
        out.println("拿到session,获取ID:"+request.getSession().getId()+"<br>");
        //当前session创建的时间
        out.println("当前session创建的时间"+request.getSession().getCreationTime()+"<br>");
        //最近的一次访问这个session的时间。
        out.println("最近的一次访问这个session的时间:"+request.getSession().getLastAccessedTime()+"<br>");
        //跟随上个网页cookies或者URL传过来的session
        out.println("跟随上个网页cookies或者URL传过来的session:"+request.getRequestedSessionId()+"<br>");
        //是否通过Cookies传过来的
        out.println("是否通过Cookies传过来的:"+request.isRequestedSessionIdFromCookie()+"<br>");
        //是否通过重写URL传过来的
        out.println("是否通过重写URL传过来的:"+request.isRequestedSessionIdFromURL()+"<br>");
        //是不是有效的sessionID
        out.println("是不是有效的sessionID:"+request.isRequestedSessionIdValid()+"<br>");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

原始页面

点击没有使用encodeURL方法时页面

点击使用encodeURL方法时页面

session有期限:

当一个网站的第一个窗口关掉了,而没有继续接着访问第二个页面,就没有使用到session。那么session会在中断程序后立刻关闭session吗?这个时候session就需要给它保留的时间,当最近一次访问的时候开始计时,每刷新一次重写开始计时。当隔了这么久的时间,没有访问这个session后,对不起,要关闭这个session了。session有过期时间,session什么时候过期,要看配置,

session能干什么:

session就是服务器里面的一块内存,内存里面能放任何东西,只要是名值对就可以了。

session里面的名字永远都是String类型
buffer

设置JSP页面的流的缓冲区的大小。

<%@ page buffer="8kb" %>
autoFlush

是否自动刷新。

<%@ page autoFlush="true" %>
exends

声明当前JSP的页面继承于那个类.必须继承的是httpservlet 及其子类。

<%@ page extends="com.test.testServlet04" %>
isELIgnored

是否忽略el表达式。

<%@ page isELIgnored="true" %>
errorPage

当前JSP页面出现异常的时候要跳转到的JSP页面。

<%@ page errorPage="404.jsp" %>
isErrorPage

当前JSP页面是否是一个错误页面。若值为true,可以使用JSP页面的一个内置对象 exception。

<%@ page isErrorPage="true" %>//设置一个404.jsp为例的为ErrorPage页面
Include指令标签

静态包含,可以将其他页面内容包含进来,一起进行编译运行.生成一个java文件.

<%@include file="被包含JSP的相对路径" %>

include指令用于当前JSP中包含其他文件,被包含文件可以是JSP、HTML或者文本文件

<%@ include file="welCome.jsp"%>
Taglib指令标签

导入标签库。

<%@taglib prefix="前缀名" uri="名称空间" %>

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

四、JSP的内置对象

JSP中一共预先定义了9个这样的对象,分别为:request、response、session、application、out、pagecontext、config、page、exception。

request对象

Request对象是javax.servlet.http.HttpServletRequest类的实例。代表请求对象,主要用于接受客户端通过HTTP协议连接传输到服务器端的数据。比如表单中的数据、网页地址后带的参数等。

该对象派生自HTTPResponse类,是ASP中重要的服务器内置对象,它连接着Web服务器和Web客户端程序。该对象用来获取客户端在请求一个页面或者传送一个Form时提供的所有信息,包括能够标识浏览器和用户的HTTP变量、存储在客户端Cookie信息以及附在URL后面的值、查询字符串或页面中Form段HTML控件内的值、Cookie、客户端证书、查询字符串等 [1]。如浏览器和用户的变量,客户端表单中的数据、变量或者客户端的cookie信息等,Request对象对应的类是System、Web、HttpRequest类。

方法

说明

String getParameter(String name)

获取请求参数 name 的值

Enumeration getParameterNames()

获取所有参数名称

String[] getParameterValues(String name)

获取请求参数 name 的所有值

Object getAttribute(String name)

获取 name 属性的值

Enumeration getAttributeNames()

返回所有属性的名称集合

void setAttribute(String key, Object value)

给 key 对象赋 value 值

void removeAttribute(String name)

删除指定的 name 属性

cookie[] getCookies()

获取所有的 cookie 对象

HttpSession getSession()

返回 request 对应的 session 对象,如果没有则创建一个 session 对象

HttpSession getSession(boolean create)

返回 request 对应的 session 对象,如果没有,且 create 值为 true,则创建一个 session 对象

Enumeration getHeaderNames()

返回 HTTP 头信息的名称集合

String getHeader(String name)

获取 name 指定的 HTTP 头信息

String getMethod()

获取 HTTP 请求方法/客户提交信息方式

response.setContentType("text/html;charset=utf-8");
System.out.println("this is RequestForwardServlet doGet method");
request.setAttribute("company","sun");
RequestDispatcher dispatcher = request.getRequestDispatcher("/ResultServlet");
dispatcher.forward(request,response);

response对象

Response对象是javax.servlet.http.HttpServletResponse类的实例。代表响应对象,主要用于向客户端发送数据。

Response对象用于动态响应客户端请示,控制发送给用户的信息,并将动态生成响应。Response对象只提供了一个数据集合cookie,它用于在客户端写入cookie值。若指定的cookie不存在,则创建它。若存在,则将自动进行更新。结果返回给客户端浏览器

response 对象在ASP中负责将信息传递给用户.Response对象用于动态响应客户端请求,并将动态生成的响应结果返回到客户端浏览器中,使用Response对象可以直接发送信息给浏览器,重定向浏览器到另一个URL或设置cookie的值等.Response对象在asp编程中非常广泛,也是一种非常好用的工具.

方法 说明

void addCookie(Cookie cookie) 添加 Cookie 的方法

void addHeader(String name,String value) 添加 HTTP 文件指定的头信息

String encodeURL(String url) 将 URL 予以编码,回传包含 Session ID 的 URL

void flushBuffer() 强制把当前缓冲区内容发送到客户端

int getBufferSize() 返回响应所使用的实际缓冲区大小,如果没使用缓冲区, 则该方法返回 0

void set BufferSize(int size) 为响应的主体设置首选的缓冲区大小

boolean isCommitted() 一个 boolean,表示响应是否已经提交;提交的响应已经 写入状态码和报头

void reset() 清除缓冲区存在的任何数据,并清除状态码和报头

ServletOutputStream getOutputStream() 返回到客户端的输出流对象

void sendError(int xc[,String msg]) 向客户端发送错误信息

void sengRedirect(java.lang.String location) 把响应发送到另一个位置进行处理

void setCotentType(String type) 设置响应的 MIME 类型

void setHeader(String name,String value) 设置指定名字的 HTTP 文件头信息

void setCotentLength(int len) 设置响应头的长度

response.setContentType("text/html;charset=utf-8");
System.out.println("this is RequestForwardServlet doGet method");
request.setAttribute("company","sun");
RequestDispatcher dispatcher = request.getRequestDispatcher("/ResultServlet");
dispatcher.forward(request,response);

session对象

session 对象是HttpSession类型的对象。只有在包含 session=“true” 的页面中才可以被使用。

Session 对象是javax.servlet.http.HttpSession类的实例。主要用来保持在服务器与一个客户端之间需要保留的数据,比如在会话期间保持用户的登录信息等,会话状态维持是Web应用开发者必须面对的问题。当客户端关闭网站的所有网页或关闭浏览器时,session对象中保存的数据会自动清除。由于Htp协议是一个无状态协议,不保留会话间的数据,因此通过session对象扩展了htp的功能。比如用户登录一个网站之后,登录信息会暂时保存在session对象中,打开不同的页面时,登录信息是可以共享的,一旦用户关闭浏览器或退出登录,就会清除session对象中保存的登录信息。

名称

描述

Contents集合

包含所有通过脚本命令添加到应用程序中的数据项

SessionID属性

用来标识每一个Session对象

TimeOut属性

用来设置Session会话的超时时间(以分钟表示)

Abandon方法

强行删除当前会话的Session对象,释放系统资源

Session_OnStart事件

建立Session对象时所激发的事件

Session_OnEnd事件

结束Session对象时所激发的事件

StaticObjects集合

包含所有通过<OBJECT>标记添加到应用程序中的对象

application对象

Application对象是javax.servlet.ServletContext类的实例。主要用于保存用户信息,代码片段的运行环境;它是一个共享的内置对象,即一个容器中的多个用户共享一个application对象,故其保存的信息被所有用户所共享。

方法名

描述

String getAttribute(String name)

根据属性名称获取属性值。

Enumeration getAttributeNames()

获取所有的属性名称。

void setAttribute(String name, Object object)

设置属性,指定属性名称和属性值。

void removeAttribute(String name)

根据属性名称删除对应的属性。

ServletContext getContext(String uripath)

获取指定URL的ServletContext对象。

String getContextPath()

获取当前Web应用程序的根目录。

String getInitParameter(String name)

根据初始化参数名称,获取初始化参数值。

int getMajorVersion()

获取Servlet API的主版本号。

int getMinorVersion()

获取Servlet API的次版本号。

String getMimeType(String file)

获取指定文件的MIME 类型。

String getServletInfo()

获取当前Web服务器的版本信息。

String getServletContextName()

获取当前Web应用程序的名称。

void log(String message)

将信息写入日志文件中。

<%
    //存储
    pageContext.setAttribute("pageContext", 1);
    request.setAttribute("request", 1);
    session.setAttribute("session", 1);
    application.setAttribute("application", 1);

    //本页获取
    Object obj=pageContext.getAttribute("pageContext");
    Object obj1=request.getAttribute("request");
    Object obj2=session.getAttribute("session");
    Object obj3=application.getAttribute("application");
%>
pageContext:<%=obj%><br>
request:<%=obj1%><br>
session:<%=obj2%><br>
application:<%=obj3%><br>

out 对象

Out对象是javax.servlet.jsp.JspWriter类的实例。主要用于向客户端浏览器输出数据。

<%
out.println("first line<br>");
response.getWriter().println("second line<br>");
%>

config 对象

Config对象是javax.servlet.ServletConfig类的实例。是代码片段配置对象,表示Servlet的配置。

PrintWriter out = response.getWriter();
// 获取道理servletConfig,配置信息
ServletConfig config = this.getServletConfig();
//获取encoding对应的参数值
String param = config.getInitParameter("encoding");
out.println("encoding="+ param) ;
//获取servletName对应的参数值
String servletName = config.getServletName();
out.println("servletName = " + servletName);

pageContext 对象

PageContext对象是javax.servlet.jsp.PageContext类的实例。用来管理网页属性,为JSP页面包装页面的上下文,管理对属于JSP中特殊可见部分中已命名对象的访问,它的创建和初始化都是由JSP容器来完成的。

<%//存储数据
    pageContext.setAttribute("company", "百度有限公司",pageContext.PAGE_SCOPE);
    Object name=pageContext.getAttribute("company",pageContext.PAGE_SCOPE);
    out.println("公司名称为:"+name + "<br/>");
%>
<%//获取对象
    HttpServletRequest req=(HttpServletRequest)pageContext.getRequest();
    String ip=req.getRemoteAddr();
    out.println("本机的ip地址为:"+ip);
%>

page 对象 相当于this对象

Page对象是javax.servlet.jsp.HttpJspPage类的实例。用来处理JSP网页,它指的是JSP页面对象本身,或者说代表编译后的servlet对象,只有在JSP页面范围之内才是合法的。

方 法

说 明

class getClass()

返回当前页面所在类

int hashCode()

返回当前页面的 hash 代码

String toString()

将当前页面所在类转换成字符串

boolean equals(Object obj)

比较对象和指定的对象是否相等

void copy (Object obj)

把对象复制到指定的对象中

Object clone()

复制对象

<%
    Object obj5;
    obj5 = null;
%>
返回当前页面所在类:<%=page.getClass()%>
<br> 返回当前页面的 hash 代码:<%=page.hashCode()%>
<br> 转换成 String 类的对象:<%=page.toString()%>
<br> page和obj比较:<%=page.equals(obj5)%>
<br> page和this比较:<%=page.equals(this)%>

exception 对象

Exception对象是java.lang.Throwable类的实例。处理JSP文件执行时发生的错误和异常只有在JSP页面的page指令中指定isErrorPage=“true”后,才可以在本页面使用exception对象。

需要说明的是,pageContext中的属性默认在当前页面是共享的;session中的属性在当前session中是共享的;application对象中的属性则对所有页面都是共享的。

//出现错误页面才会有值,否则为null
<%
out.println("exception.toString: ");
out.println("<br/>");
out.println(exception.toString() + "<br/>");
out.println("exception.getMessage: ");
out.println("<br/>");
out.println(exception.getMessage());
out.println("<br>");
%>

JSP的内置对象主要有以下特点:

1、由JSP规范提供,不用编写者实例化;

2、通过Web容器实现和管理;

3、所有JSP页面均可使用;

4、只有在脚本元素的表达式或代码段中才可使用(<%=使用内置对象%>或<%使用内置对象%>)。

按照内置对象的功能来划分,可以分为以下四类:

1、输出输入对象:request对象、response对象、out对象;

2、通信控制对象:pageContext对象、session对象、application对象;

3、Servlet对象:page对象、config对象;

4、错误处理对象:exception对象。

(1)application范围:作用范围起始于服务器开始运行,application对象被创建之时;终止于服务器关闭之时。

(2)session范围:有效范围是整个用户会话的生命周期内。每个用户请求访问服务器时一般就会创建一个session对象,用户断开退出时session对象失效。

服务器对session对象有默认的时间限定,如果超过该时间限制,session会自动失效,而不管用户是否已经终止连接,这主要是出于安全性的考虑。

(3)request范围:在一个JSP页面向另一个JSP页面提出请求到请求完成之间,在完成请求后此范围即结束。

(4)page 范围:有效范围是当前页面。

五、请求转发

什么是请求转发

请求转发是服务端的一种请求方式,相当于在服务端中直接请求某个资源。

RequestDispatcher dispatcher = request.getRequestDispatcher("/test.jsp");
dispatcher.forward(request,response);

简写方式:

request.getRequestDispatcher("/test.jsp").forword(request,response);

forward:

当 <jsp:forward> 动作标记被执行后,当前的页面将不再被执行,而是去执行该标记指定的目标页面,但是,用户此时在地址栏中看到的仍然是当前网页的地址,而内容却已经是转向的目标页面了。

<jsp:forward page="relativeURL" | "<%=expression %>" />

如果转向的目标是一个动态文件,还可以向该文件传递参数,使用格式如下:

<jsp:forward page="relativeURL" | "<%=expression %>" />
<jsp:param name="pName1" value="pValue1 | <%=expression1 %>" />
<jsp:param name="pName2" value="pValue2 | <%=expression2 %>" />

说明如下:

1.page 属性用于指定要跳转到的目标文件的相对路径,也可以通过执行一个表达式来获得。如果该值以“/”开头,表示在当前应用的根目录下查找目标文件,否则,就在当前路径下查找目标文件。请求被转向到的目标文件必须是内部的资源,即当前应用中的资源。如果想通过 forward 动作转发到外部的文件中,将出现资源不存在的错误信息。

2.forward 动作执行后,当前页面将不再被执行,而是去执行指定的目标页面。

3.转向到的文件可以是 HTML 文件、JSP 文件、程序段,或者其他能够处理 request 对象的文件。4.forward 动作实现的是请求的转发操作,而不是请求重定向。它们之间的一个区别就是:进行请求转发时,存储在 request 对象中的信息会被保留并被带到目标页面中;而请求重定向是重新生成一个 request 请求,然后将该请求重定向到指定的 URL,所以,事先储存在 request 对象中的信息都不存在了。

请求转发(服务端跳转)与重定向(客户端跳转)的区别

1.请求转发对于客户端浏览器而言是在一次请求与响应中完成,而重定向是在两次请求两次响应中完成。

2.请求转发并不会改变客户端浏览器的地址栏中的内容。而重定向会改变客户端浏览器地址栏中的内容。

3.请求转发可以使用request对象传递数据,而重定向不能使用request对象传递数据。

4.如果是处理的DML操作(增删改),建议使用重定向方式为客户端浏览器产生响应,可以解决表单重复提交现象。

六、JSP四大作用域对象

作用域:“数据共享的范围”,也就是说数据能够在多大的范围内有效。

对象名称

作用范围

application

整个应用都有效

session

在当前会话中有效

request

在当前请求中有效

page

在当前页面有效

七、JavaBean技术

一、什么是JavaBean

JavaBean 是一种 JAVA 语言写成的可重用组件。JavaBean 是一种特殊的 Java 类,通 过封装属性和方法成为具有某种功能或者处理某个业务的对象,简称 Bean。

JavaBean 具有以下特点:

JavaBean 的类必须是具体的和公共的(public)。JavaBean 必须具有一个无参 数的 构造方法 。如果在 JavaBean 中自定义了有参构造方法,就必须再添加一个无参构造 方法,否则将无法设置属性。这个无参构造方法也必须是 public

类中的属性是私有的(private),访问属性的方法都必须是 public。

如果类的属性名是 xxx,那么为了更改或获取属性,在类中可以使用两个 public 的 getXxx 和 setXxx 方法,在这些 get 和 set 方法中,属性名的首字母应为大写。

对于 boolean类型 的成员变量,即 布尔逻辑 类型的属性,允许使用 is 方法代替 上面的 get 方法。

JavaBean 处理表单方便,只要 JavaBean 属性和表单控件名称吻合,采用 jsp:useBean标记就可以直接得到表单提交的参数。

JavaBean 从应用形式或功能上一般可以分为封装数据的 JavaBean 和封装业务的 JavaBean。

1、封装数据的JavaBean

封装数据的 JavaBean 负责数据的存取,需要设置多个属性(类的成员变量)及其值的 存取方法。

如果属性名字是 xxx,则 getXxx 方法用户获取属性值;setXxx 用于设置或更改属性值。类中属性名第一 个字符应当是小写的,其访问属性应当是 private 的,而方法的访问属性都必须是 public 的。

get方法和set方法在设置属性后都可以[自动补全]

<jsp:useBean id="title" class="bean.Title" scope="page"/>

id 属性指定 JavaBean 对象的名称,因为同一个 JSP 页面中可能会引入多个 JavaBean 对象,因此,必须给引入的 JavaBean 对象命名,以便在 JSP 页面中使用该对象。

class 属性指定引入的 JavaBean 对象的带路径类名,Scope 属性设置 JavaBean 对象 的生命期。

2、封装业务的JavaBean

封装业务的 JavaBean 是完成一定运算和操作功能的业务类,主要包含一些特定的方 法,进行业务处理。

在 Java 中提倡面向接口编程,这样的程序将来有很大的灵活性,特别是在多层体系 结构中。当一个类实现了一个接口时,必须实现接口中的所有的方法。

二、在JSP中使用JavaBean

使用 JavaBean的最大好处之一就是可以实现代码的复用,因此,在编写 JSP 文件时,对于一些常用的复杂功能,通常将它们的共同功能抽象出 来,组织为 JavaBean。

在 JSP 页面中,通常使用<jsp:useBean>、<jsp:getProperty>和<jsp:setProperty>这三个 JSP 动作元素使用 JavaBean。

1、<jsp:useBean>

动作用于在 JSP 页面中实例化一个或多个 JavaBean 组件,这些被实例 化的 JavaBean 对象可以在 JSP 页面中被调用。

语法格式:

<jsp:useBean id=“name” class=“classname” scope=“page|request|session|application”/>
<jsp:useBean id="name"(指定该JavaBean实例的变量名) class="className"(指定JavaBean的类名) scope="scope"(指定JavaBean的作用范围)/>
或者
<jsp:useBean id="name" type="className"(指定JavaBean对象的类型,在查找已存在的JavaBean时使用) scope="scope"/>

id:用来声明所创建的 JavaBean 实例的名称,在页面中可以通过 id 的值来引用 JavaBean;

class:指定需要实例化的 JavaBean 的完整路径和类名;

scope:指定 JavaBean 实例对象的生命周期。其值可以是 page、request、session 和 application 之一。

type:type属性的值必须和类名或者父类名或者类所实现的接口名相匹配。记住该属性的值是经由id属性设置的。

beanName:给bean设定名称,据此来实例化相应的bean,允许同时提供type和beanName属性而忽略class属性。

(1)page 范围的 Bean 仅仅在创建它们的页中才能访问。一个 page 范围的 Bean 经 常用于单一实例计算和事务,而不需要进行跨页计算的情况。

(2)request 范围的 JavaBean 在客户端的一次请求响应过程中均有效。在这个请求 过程中,并不一定只能处理一个页面,当一个页面提交以后,响应它的过程可以经过一个 或者一系列页面,也就是说,可以由响应它的页面再 forward 或者 include 其他页面进行 处理,最后所有页面都处理完返回客户端,整个过程都是在一个 request 里进行处理的。 因此,只要是在一个请求过程中的页面,都可以共享 request 范围的 JavaBean。

(3)session 范围的 JavaBean 在客户端的同一个 session 过程中均有效,服务器会 为新访问的用户创建 HttpSession 对象,这也是在其中存储 session 范围的 JavaBean 的 地方。

(4)application 范围内的 JavaBean 一旦建立,除非调用代码将其撤销,或者服务 器重新启动,否则此 JavaBean 的实例将一直驻留在服务器内存中。

2、<jsp:setProperty>.

以使用 JSP 动作指令和来设置和获取 JavaBean 的属性值,特别是在接收表单参数时尤为方便.

语法有三种形式

(1)当表单对象中的参数名称与 Bean 的属性名称一致时,可采用如下简便的形式,将表单对象中的参数值赋给 JavaBean 的同名属性:

<jsp:useBean id="title" class="bean.Title" scope="page"/> 
<jsp:setProperty name="title" property= "*"/>
<jsp:setProtery name="id"(指定JavaBean对象名,与useBean标准动作的id相对应) property="属性名"(表示要设置JavaBean中的那个属性,如果全部都设置,则填写为*) value="值"(可选,用来指定JavaBean属性的值)/>
或
<jsp:setProperty name="id" property="属性名" param="参数名"(可选,用来指定哪个请求参数作为JavaBean的属性值)/>

name="title"的意思是 JavaBean 对象的名称,它指明了将对哪个 JavaBean 对象的属 性设值,因为有时在一个 JSP 页面中可能有多个 JavaBean 存在。JavaBean 对象的名称是 由动作指令的 id 属性确定的。

property = "*"的意思是接收来自表单输入的所有与属性名相同的参数值,它会自动 匹配 Bean 中的属性,要保证 JavaBean 的属性名必须和 Request 对象的参数名一致。如果 Request 对象的参数值中有空值,那么对应的 JavaBean 属性将不会设定任何值。同样, 如果 JavaBean 中有某些属性没有与之对应的 Request 参数值,那么这些属性同样也不会 设定,这种方式简称“一一映射”。

(2))当表单对象中的参数名称与 Bean 的属性名称不一致时,则需要逐个设定属性值, 而且,还要通过 param 指明属性值来自表单的哪个参数:

<jsp:useBean id="title" class="bean.Title" scope="page"/> 
<jsp:setProperty name="title" property= "isbn" param="parameterIsbn"/>

由于表 单参数与 JavaBean 的属性名不一 致,这句话 表示将表单 参 数 “parameterIsbn"的值赋给名称为"title"的 JavaBean 的属性"isbn”。

(3)使用<jsp:setProperty>动作指令,用 value 指定的任意值给 JavaBean 的属性 赋值

<jsp:useBean id="title" class="bean.Title" scope="page"/> 
<jsp:setProperty name=" title" property= "title" value="{string}" /> 
<jsp:setProperty name="title" property="isbn" value="{ <%= expression %>}"/> 

使用 value 指定的属性值可以是字符串,也可以是表达式。如果是字符串,那么它就 会被转换成 Bean 属性的类型。如果它是一个表达式,那么它的类型就必须和它将要设定 的属性值的类型一致。如果参数值为空,那么对应的属性也不会被设定。

3、<jsp:getProperty>

与相对应,用于从 JavaBean 中获取指定的属 性值。

语法结构:

<jsp:getProperty name="beanInstanceName" property="propertyName" /> 

name 即为 在动作指令中定义的表示 JavaBean 对象名称的 id 属性,property 属性指 定了想要获取的 JavaBean 的属性名。

在使用 动作指令之前,要务必保证已经存在指定的 JavaBean 实例,而且要保证该实例对象中存在 property 指定的属性,否则,如果在该 Bean 中不存在 property 指定的属性,则会抛出 NullPointerException 异常。

八、补充

JSP脚本程序

JSP脚本程序指的是在JSP页面中嵌入标签<% %>之间的java代码,脚本程序可以写在JSP页面的任何位置,JSP脚本程序可以包含一行或者多行java代码,也可以实现一个功能或者多个功能。

JSP表达式

JSP中提供了一种可以用来实现输出的标签<%= %>,称为JSP表达式,其使用格式为:<%= 变量或者可以返回值的方法或者java表达式%>,jsp表达式可以嵌入多种HTML标签的属性中,例如:

<input type="text" name="<%=变量或表达式%>" value="<%=变量或表达式%>"/>
<a href="<%=变量名或表达式%>">单击</a>

JSP声明标识

JSP声明标识指的是写在标签<%! %>中的java代码。在声明标识中可以指定变量、常量,还可以用来定义函数,在声明标识中定义的变量的作用范围是当前页面,生存时间是服务器的运行时间。在脚本程序中定义的变量的作用范围是当前页面,生存时间是页面的一次打开和关闭,另外在脚本程序中只能进行函数的调用,不能进行函数的定义。

JSP注释

1.HTML的注释方法
<!-- 注释 -->
2.JSP注释的方法
<%-- 注释 --%>
3.在JSP脚本中使用注释:
<%
//一行
/*多行*/
%>

简单运算

算数运算

${3+4} ${"3"+4} ${3+"a"} 所有参与运算的元素都会转成数字,如果不能转就报错,空元素参与运算当中没参与。

关系运算

关系运算符 说明 范例 结果

== | eq 等于 ${5 == 5} ${5 eq 5} true

!= | ne 不等于 ${5 ~= 5} ${5 nq 5} false

< | lt 小于 ${3<5} ${3 lt 5} true

:> | gt 大于 ${3 > 5} ${3 gt 5} false

<= | le 小于等于 ${3<=5} ${3 le 5} true

:>= | ge 大于等于 ${3>=5} ${3 ge 5} false

逻辑运算

&& and 交 ${a&&b} true/false

|| or 并 ${a||b} true/false

! not 非 ${!A} true/false

Empty运算符

empty/not empty判断对象是否为null,判断集合是否为空,数组长度是否为0,判断字符串是否为空串,判断域中是否没有任何属性。

三元表达式

${name == null ? "张三" : name;}

WEB开发常用对象

EL的内置对象

EL中预先定义了11个内置对象,不需要提前存入域中,可以直接el使用。

隐含对象名称

描 述

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[]数组。注意:如果头里面有"-"例如Accept-Encoding,则要headerValues["Accept-Encoding"]

cookie

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

initParam

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

四大作用域中域属性组成的map

pageScope:代表page域,可以用来获取page域中的属性

requestScope:代表request域,可以用来获取request域中的属性

sessionScope:代表session 域,可以用来获取session域中的属性

applicationScope:代表application域,可以用来代表application域中的属性

请求参数组成的map

param代表请求参数组成的map集合${param.username}

paramValues代表请求参数组成的map集合,但此集合的value是String[],用来获取一名多值的param

请求头组成的map

header 获取请求头组成的map

headerValues 获取请求头组成的map但是value是一个String[],用来获取一个多值的header

所有cookie信息组成的map

cookie:获取cookie组成的map对象,键为cookie的名,值为cookie对象。

${cookie.cookieName.cookieValue}

web应用初始化参数组成的map

initParam以map封装的web.xml中配置的整个web应用的初始化参数。

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值