JavaWeb上

利用ServletContext实现两个web网页之间消息的互通

发送端口:

package com.wang.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //得到servletcontext对象
        String username="小王";
//        context.setRequestCharacterEncoding("utf-8");
        context.setAttribute("username",username);
        //把username这个对象放到context中
    }
}

接收端口:

package com.wang.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
        //把这个路径的文件转换成流
        //这个路径要根据编译生成的target文件查看
        Properties properties = new Properties();
        //获取properties类
        properties.load(is);
        //通过properties类把is这个流下载
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        //下载后,通过properties类查看这个流中的文本信息
        resp.getWriter().print(user+":"+password);

    }

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

在web.xml中写入一些初始化信息后,可以通过方法Context的getInitParameter方法拿到这些信息

//  web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1"
         metadata-complete="true">
 <context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
  </context-param>
// 通过context-param在web.xml中定义一些初始化信息
  <servlet>
    <servlet-name>gp</servlet-name>
    <servlet-class>com.wang.servlet.ServletDemo03</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>gp</servlet-name>
    <url-pattern>/gp</url-pattern>
  </servlet-mapping>
</web-app>
// 获取代码:
package com.wang.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String url = context.getInitParameter("url");
        resp.getWriter().print("url:"+url);
    }

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

转发,通过ServletContext中getRequestDispatcher方法实现转发,

A需要C中的信息,但是A只能连接到B,而B可以连接C,此时,用方法getRequestDispatcher可以通过A转发B中的内容,而B的内容从C中获取

package com.wang.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ServletDemo04 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        System.out.println("进入了ServletDemo04");
        context.getRequestDispatcher("/gp").forward(req,resp);
        //                             转发的路径        传递的参数
        //demo04转发demo03 ,demo03中的内容来自web.xml
        //demo04不直接去web.xml中,通过找demo03实现找web.xml中的内容
    }

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

获取resources中的资源文件中的内容

package com.wang.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties");
        //把这个路径的文件转换成流
        //这个路径要根据编译生成的target文件查看
        Properties properties = new Properties();
        //获取properties类
        properties.load(is);
        //通过properties类把is这个流下载
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        //下载后,通过properties类查看这个流中的文本信息
        resp.getWriter().print(user+":"+password);

    }

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

下载文件

package com.wang.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取下载文件的路径
        //F:\java源代码\Java\javaweb_02_servlet\response\src\main\resources\小王.png  绝对路径
        String realPath = "F:\\java源代码\\Java\\javaweb_02_servlet\\response\\src\\main\\resources\\小王.png";
        // 2. 下载的文件名是啥?
        //substring截取字符串 lastIndex最后一个索引
        //从最后一个\\的后面一个字符开始截取,为下载的文件的文件名字
        //参考:https://blog.csdn.net/billxin0621/article/details/98485271?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167504689016800188538520%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=167504689016800188538520&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-98485271-null-null.142^v71^one_line,201^v4^add_ask&utm_term=substring%E7%9A%84%E7%94%A8%E6%B3%95&spm=1018.2226.3001.4187
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
        // 3. 设置想办法让浏览器能都支持我们下载的东西 文件名是中文的时候,可以设置URLEncoder.encode(fileName, "UTF-8"),否则有可能乱码
        resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
        //设置头文件,不懂
        // 4. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
        // 5. 创建缓冲区
        int len=0;
        byte[] buffer = new byte[1024];
        // 6. 获取OutputStrem对象
        ServletOutputStream out = resp.getOutputStream();
        // 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
        while ((len=in.read(buffer))>0){
            out.write(buffer,0,len);
        }
        out.flush();
        in.close();
        out.close();
    }

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

重定向,重定向的路径需要加/*

package com.wang.servlet;

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

public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //实现重定向
        resp.sendRedirect("/r/img");
        //拆分:
        resp.setHeader("location","/r/img");
        //重定向后的位置
        resp.setStatus(302);
        //状态码设置

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
package com.wang.servlet;

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

public class RequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入了RequestTest请求");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
        resp.sendRedirect("/r/success.jsp");
    }

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

动态验证码

package com.wang.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("refresh","3");
        //设置网页头,实现3秒刷新一次网页
        BufferedImage img = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        //参考:https://blog.csdn.net/weixin_31659095/article/details/114512388?ops_request_misc=&request_id=&biz_id=102&utm_term=BufferedImage.TYPE_INT_RGB&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-114512388.nonecase&spm=1018.2226.3001.4187
        //创建一张图片,长80宽20   BufferedImage.TYPE_INT_RGB    RGB三原色
        Graphics2D i = (Graphics2D) img.getGraphics();//得到一支笔
        //设置笔的颜色
        i.setColor(Color.white);
        //设置  填充矩形 从00点到80,20
        i.fillRect(0,0,80,20);
        //给图片写入字符串数据
        i.setColor(Color.BLACK);
        i.setFont(new Font(null,Font.BOLD,20));
        i.drawString(makeNum(),0,20);
        //设置浏览器打开方式为图片
        resp.setContentType("image/jpeg");
        //设置为不缓存
        resp.setDateHeader("Expires",0);
        resp.addHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        //写          写到哪    ,名字          写什么
        ImageIO.write(img,"jpg", resp.getOutputStream());
    }
    //生成一个随机数
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(99999) + "";
        StringBuffer buffer = new StringBuffer();
        //确保生成的
        for (int i = 0; i < 5-num.length(); i++) {
                buffer.append("0");
        }
        num=buffer.toString()+num;
        return num;
    }

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

转发重定向等三种方法

package com.wang.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置字符编码方式
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        //获取一个数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //获取一些数据,组成一个数组
        String[] hobbys = req.getParameterValues("hobbys");
        System.out.println("-----------------------------");
        System.out.println(username+":"+password);
        System.out.println(Arrays.toString(hobbys));
        System.out.println("-----------------------------");
        /**
         * 重定向的方式:
         * 1、重定向:resp.sendRedirect();
         * 2、转发:this.getServletContext()
         * 3、通过请求转发:req.getRequestDispatcher("/success.jsp").forward(req,resp);
         */
        //resp.sendRedirect();
        //this.getServletContext()
        req.getRequestDispatcher("/success.jsp").forward(req,resp);
        //                          转发到哪里

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1 style="text-align: center">Hello,World</h1>
<form action="${pageContext.request.contextPath}/login" method="post" style="text-align: center">
    账户:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    爱好:<br>
    <input type="checkbox" name="hobbys" value="游戏">游戏
    <input type="checkbox" name="hobbys" value="代码">代码
    <input type="checkbox" name="hobbys" value="唱歌">唱歌
    <input type="checkbox" name="hobbys" value="电影">电影<br>
    <input type="submit">
</form>

</body>
</html>
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登陆成功</h1>
</body>
</html>

---------------------------------------------------------------------------------------------------------

Cookie 小饼干

Cookie,当客户端第一次访问网页时,服务器给这个客户端一个cookie(信件),以后这个客户端再次访问这个网页时,拿着这个cookie就可以了,

cookie是保存在本地的

package com.wang.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

public class CookieDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("GBK");
        resp.setCharacterEncoding("GBK");
        PrintWriter out = resp.getWriter();
        Cookie[] cookies = req.getCookies();
        if (cookies!=null){
            out.write("您上次访问本网站的时间为:");
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie=cookies[i];
                if (cookie.getName().equals("LastLoginTime")){
                    long lastlogintime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastlogintime);
                    out.write(date.toLocaleString());
                }
            }
        }else {
            out.write("这是您第一次访问本网站");
        }
        //把Cookie new出来,放一个key值和一个value值
        Cookie lastLoginTime = new Cookie("LastLoginTime", System.currentTimeMillis() + "");
        //设置Cookie的有效时间
        lastLoginTime.setMaxAge(24*60*60);//按照秒来计算的
        //给客户端响应回去,添加一个Cookie,这个Cokkie用于记录客户端在本次会话(未关闭浏览器)的上次访问时间
        resp.addCookie(lastLoginTime);
    }

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

设置cookie的有效期

package com.wang.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CookieDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie[] cookies = req.getCookies();
        //获取请求过来的cookie
        Cookie cookie = new Cookie("LastLoginTime", System.currentTimeMillis() + "");
        //创建一个新的cookie
        cookie.setMaxAge(0);
        //设置cookie的有效期为0
        resp.addCookie(cookie);
        //给客户端响应回去,添加一个cookie
        //删除cookie的方式:
        /**
         * 创建一个新的web网页,设置一个与要删除的cookie的相同的key值,然后设置有效期为0(cookie.setMaxAge(0);
         * 在使用完上一个网页后,需要删除的时候,进入这个网页,有效期为0,上一个cookie会自动失效
         */
    }

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

Session 会话

Session,当客户端第一次访问网页时,由服务器等级该客户端信息,用户拿到SessionID,下次再次访问这个网页的时候可以通过SessionID去服务器直接找到最硬的用户信息,

Session保存在每个浏览器的Session中,每个浏览器的Session都不一样

SessionID相当于一把钥匙,拿着钥匙就可以去服务器哪里打开相应的房间

Session可以保存一些信息,而Cookie不能

在得到Session时,后台自动创建一个Cookie,并将Session保存在Cookie中

package com.wang.servlet;

import com.wang.pojo.Person;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SessionDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        //得到一个Session
        HttpSession session = req.getSession();
        //在Session中存入信息  一个String类型,一个是Object类型。
        session.setAttribute("name",new Person("小王",18));
        //获取Session的ID
        String sessionId = session.getId();
        if (session.isNew()){
            resp.getWriter().write("Session创建成功,SessionID:"+sessionId);
        }else{
            resp.getWriter().write("Session已经在服务器中创建成功了,SessionID:"+sessionId);
        }
    }

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

Persion:

package com.wang.pojo;

public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

当在服务器中保存Session后,可以在其他的后台Servlet中获取保存的这个Sessiion

package com.wang.servlet;

import com.wang.pojo.Person;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SessionDemo02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        //获取Session
        HttpSession session = req.getSession();
        Person name = (Person) session.getAttribute("name");
        System.out.println(name.toString());
    }

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

手动清除Session节点和清除Session

package com.wang.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SessionDeemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        //获取Sesdsion
        HttpSession session = req.getSession();
        //清楚保存的节点信息
        session.removeAttribute("name");
        //删除Session,当下次再次打开的时候,会立刻自动生成一个新的Session
        session.invalidate();
    }

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

还可以在web.xml中设置Session的有效期

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1"
         metadata-complete="true">
    <servlet>
        <servlet-name>Cookie</servlet-name>
        <servlet-class>com.wang.servlet.CookieDemo01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Cookie</servlet-name>
        <url-pattern>/cookie</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>Cookie02</servlet-name>
        <servlet-class>com.wang.servlet.CookieDemo02</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Cookie02</servlet-name>
        <url-pattern>/c2</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>sessiondemo01</servlet-name>
        <servlet-class>com.wang.servlet.SessionDemo01</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sessiondemo01</servlet-name>
        <url-pattern>/s1</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>sessiondemo02</servlet-name>
        <servlet-class>com.wang.servlet.SessionDemo02</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sessiondemo02</servlet-name>
        <url-pattern>/s2</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>sessiondemo03</servlet-name>
        <servlet-class>com.wang.servlet.SessionDeemo03</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sessiondemo03</servlet-name>
        <url-pattern>/s3</url-pattern>
    </servlet-mapping>
    <session-config>
<!--        可以设置session的属性-->
<!--        设置session的失效时间,设置为1分钟后session失效,会重新创建一个新的session,以分钟为单位-->
        <session-timeout>1</session-timeout>
    </session-config>

</web-app>

---------------------------------------------------------------------------------------------------------

JSP操作

<%@ page import="java.util.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<%--JSP表达式,用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%= new Date()%>
<%--ALT+Enter自动导包--%>

<%--  JSP脚本片段--%>
<%
  int sum=0;
  for (int i = 1; i <=100 ; i++) {
    sum=sum+i;
  }
  out.print("<h1>sum="+sum+"</h1>");
%>
<%
  int x=10;
  out.println(x);
%>
  <h1>hello</h1>
<%
  out.print("<span>x="+x+"</span>");
%>
<%
  for (int i = 0; i < 5; i++) {
%>
  <h1>你好小杨  <%=i%></h1>
<%
  }
%>

<hr>
<%--  上面的都是定义在方法里面的--%>
<hr>
<%--在方法外面定义:--%>
<%!
  //JSP声明
  static {//静态代码块
    System.out.println("Loading Servlet");
  }
  private int globalVar=0;
  public void wang(){
    System.out.println("进入了方法wang");
  }
%>
<hr>
  <h1>EL表达式</h1>
<h1>JSP注释:</h1>
<%--  我是JSP的注释--%>
<h1>JSP的注释不会在客户端的查看源代码中显示,HTML的注释就会显示</h1>
  <h1>HTML注释:</h1>
<!--我是HTML的注释-->

  </body>
</html>

自定义错误页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@page errorPage="error/500.jsp" %>
<%-- 错误页面发生时,自动跳转到这也页面,不会跳转到系统默认的错误页面 --%>
<html>
<%--
在自定义的500页面
--%>

<head>
    <title>Title</title>
</head>
<body>

<%
  int i=1/0;
%>


</body>
</html>

错误页面转发也可以在web.xml中实现

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <error-page>
        <error-code>404</error-code>
        <location>/error/404.jsp</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/error/500.jsp</location>
    </error-page>

</web-app>

网页中,多个网页的公共部分可以不重复写

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--
    用这种方法,@include会将两个页面合二为一
    最后是一个页面
    合成一个页面后,其他页面不能定义相同的变量例如:在两个页面都定义 int i=0,合到一起后就会报500错误
--%>
<%@include file="common/header.jsp"%>
<%--included 包含,可以提取公共的地方,然后直接用include引用--%>
<h1>网页主题</h1>
<%@include file="common/footer.jsp"%>

<hr>
<%--JSP标签
jsp:include这种方法是拼接页面
本质还是三个页面
一般用这种方法,灵活性高
拼接一个页面后,本质其实还是三个页面,其他页面能定义相同的变量例如:在两个页面都定义 int i=0,拼接一起后不会报错
--%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主题</h1>
<jsp:include page="/common/footer.jsp"/>



</body>
</html>

header.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>我是Header</h1>

footer.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>我是Footer</h1>

jsp内置对象

<%@ page import="javafx.application.Application" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%--内置对象--%>
<%
  pageContext.setAttribute("name1","小王1号");//只在本页面有效,其他页面失效
  request.setAttribute("name2","小王2号");//只在一次请求中有效,请求可以转发,但是如果转发失败,则也会失效
  session.setAttribute("name3","小王3号");//在一次会话中有效,从打开浏览器到关闭浏览器都有效
  application.setAttribute("name4","小王4号");//在服务器中有效,从打开服务器到关闭服务器之间有效
%>
<%--<%--%>
<%--  pageContext.getAttribute("name1");--%>
<%--  pageContext.getAttribute("name2");--%>
<%--  pageContext.getAttribute("name3");--%>
<%--  pageContext.getAttribute("name4");--%>
<%--  pageContext.getAttribute("name5");--%>
<%--%>--%>
<%
  String name1 = (String) pageContext.findAttribute("name1");
  String name2 = (String) pageContext.findAttribute("name2");
  String name3 = (String) pageContext.findAttribute("name3");
  String name4 = (String) pageContext.findAttribute("name4");
  String name5 = (String) pageContext.findAttribute("name5");
  //转发,先存入数据后,转发到另一个网页,这是,name2可以在另一个网页拿到了
  pageContext.forward("/pageDemo03.jsp");
%>
<h1>拿到的数据是:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>
<%--
由上述代码可知,并不存在name5这个数据,所以,用EL表达式输出的时候,就没有输出name5
但是,如果用<%=%>输出这些数据时,name5就会输出为NULL
--%>

</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
  String name1 = (String) pageContext.findAttribute("name1");
  String name2 = (String) pageContext.findAttribute("name2");
  String name3 = (String) pageContext.findAttribute("name3");
  String name4 = (String) pageContext.findAttribute("name4");
  String name5 = (String) pageContext.findAttribute("name5");
%>
<h1>拿到的数据是:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>

<%--
  只能拿到name3和name4
  说明只有name3和name4有效
--%>

</body>
</html>
  pageContext.setAttribute("name1","小王1号");//只在本页面有效,其他页面失效
  request.setAttribute("name2","小王2号");//只在一次请求中有效,请求可以转发,但是如果转发失败,则也会失效
  session.setAttribute("name3","小王3号");//在一次会话中有效,从打开浏览器到关闭浏览器都有效
  application.setAttribute("name4","小王4号");//在服务器中有效,从打开服务器到关闭服务器之间有效

四种方法都可以存储一些信息,但是作用域不同


if语句

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--导入这个头文件--%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>if测试</h1>
<form action="/coreif.jsp" method="get">
  <input type="text" name="name" value="${param.name}">
  <input type="submit" value="登陆">
</form>
<%--    比较输入提交过来的是不是Dying,用这个Var接收--%>
<c:if test="${param.name=='Dying'}" var="admin">
    <c:out value="欢迎登陆"/>
</c:if>
<%--输出一下上面的Var--%>
<c:out value="${admin}"/>


</body>
</html>

when语句

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/corewwhen.jsp" method="get">
  请输入您的期末成绩:
  <input type="text" name="grade">
  <input type="submit" value="提交">
</form>
<%--类似于java中的switch--%>
<c:choose>
  <c:when test="${param.grade>=90}">
    您的成绩为优秀
  </c:when>
  <c:when test="${param.grade>=80}">
    您的成绩为良好
  </c:when>
  <c:when test="${param.grade>=60}">
    您的成绩为及格
  </c:when>
  <c:when test="${param.grade<60}">
    您的成绩不及格
  </c:when>
</c:choose>

</body>
</html>

foreach遍历

<%@ 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>
<head>
    <title>Title</title>
</head>
<body>
<%
  ArrayList<String> people = new ArrayList<>();
  people.add(0,"张三");
  people.add(1,"李四");
  people.add(2,"王五");
  people.add(3,"赵六");
  people.add(4,"田七");
  request.setAttribute("user",people);
  for (String user:people) {

  }
%>
<%--
    items :从这里开始一个一个遍历,遍历出来的值放到var中
    然后下面输出var的值
    类似于java中遍历
      for (String user:people) {
  }
      begin: 从哪里开始
      end : 到哪里结束
      step :步长
--%>
<c:forEach var="name" items="${user}">
  <c:out value="${name}"/> <br>
</c:forEach>

</body>
</html>

JavaBean :

<%@ page import="com.wang.pojo.people" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<%--类似于:
<%
    people people = new people();
    people.setName();
    people.setId();
    people.setAddress();
    people.setAge();
%>
--%>
<jsp:useBean id="people" class="com.wang.pojo.people" scope="page"/>
<%--           叫什么          路径                         作用域      --%>
<jsp:setProperty name="people" property="id" value="1"/>
<jsp:setProperty name="people" property="name" value="小王"/>
<jsp:setProperty name="people" property="age" value="18"/>
<jsp:setProperty name="people" property="address" value="河南"/>
<%--在这个类中设置属性的值--%>
id:<jsp:getProperty name="people" property="id"/>
name:<jsp:getProperty name="people" property="name"/>
address:<jsp:getProperty name="people" property="address"/>
age:<jsp:getProperty name="people" property="age"/>
</body>
</html>

people:

创建了三个属性,然后与数据库连接,

在JavaBean中使用

package com.wang.pojo;

public class people {
    private int id;
    private String name;
    private int age;
    private String address;

    public people() {
    }

    public people(int id, String name, int age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "people{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

MVC三层架构

View

  • 展示数据

  • 提供链接发起Servlet请求

Controller

  • 接收用户的请求(req:请求参数 Session信息。。。)

  • 交给业务层处理对应的代码

  • 控制试图的跳转

    登录  
---》  接收用户的登录请求  
---》  处理用户的请求(获取用户登录的参数,username,password)
---》  交给业务处理登录业务(判断用户名密码是否正确:事务)
---》  Dao层查询用户名和密码是否正确
---》  数据库

Model

  • 业务处理:业务逻辑(Service)

  • 数据持久层:CRUD(Dao)


过滤器:

记住导包不要导错

已知,在我们的Servlet中往前台页面输出汉字的时候会出现乱码问题

package com.wang.Servlet;

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

public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//此时,页面显示会出现乱码问题 
//我们通常会使用设置编码属性来调整,但是这样每一次都要写,所以,我们可以使用过滤器来简化操作 
        resp.getWriter().print("你好世界!");
    }

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

过滤器:

package com.wang.Filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    //初始化 ,当服务器启动的时候,过滤器就随着服务器一起启动了,随时监听过滤
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    /**
     * 1、过滤器中所有代码,在过滤特定请求的时候都会执行
     * 2、必须要让过滤器继续执行  也就是   filterChain.doFilter(servletRequest,servletResponse);
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        //我们每请求一次网页,进进行过滤一次
        System.out.println("执行过滤前...");
        //让过滤器继续执行,如果不写这一句,程序到这里就会停止
        //chain :链,因为可能有多个过滤器,必须写这一句让过滤器继续执行
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("执行过滤后");
    }

    //销毁,web服务器关闭的时候,我们的过滤器才会销毁
    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }
}

web.xml中注册要注意:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>ShowServlet</servlet-name>
        <servlet-class>com.wang.Servlet.ShowServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/show</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ShowServlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.wang.Filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
<!--        只要是经过  /servlet下面的所有请求都会进行过滤-->
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>
    
</web-app>

监听器(例子)

监听器实现统计在线人数

package com.wang.listener;


import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

//用监听器统计网站在线人数-统计session个数
//开始时,有三个人在线,可能是访问失败了,但是Session已经存在了
//我们把 服务器重新部署一下就可以了
public class OnlineCountListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext context = se.getSession().getServletContext();
        Integer attribute = (Integer) context.getAttribute("onlinecount");
        if (attribute==null){
            attribute=new Integer(1);
        }else {
            int i = attribute.intValue();
            attribute=new Integer(i+1);
        }
        context.setAttribute("onlinecount",attribute);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext context = se.getSession().getServletContext();
        Integer attribute = (Integer) context.getAttribute("onlinecount");
        if (attribute==null){
            attribute=new Integer(0);
        }else {
            int i = attribute.intValue();
            attribute=new Integer(i-1);
        }
        context.setAttribute("onlinecount",attribute);
    }
}

测试页面:

index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<%--      可以用:this.getServletConfig().getServletContext().getAttribute("onlinecount")--%>
  <h1>当前有 <span><%=request.getServletContext().getAttribute("onlinecount")%></span> 个人在线</h1>
  </body>
</html>

在web.xml中注册:

在web.xml中注册监听器后,服务器启动时,监听器自动启动
<listener>
    <listener-class>com.wang.listener.OnlineCountListener</listener-class>
</listener>

登陆跳转的实现

首页:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

  <form action="/lo" method="post">
    账户:
    <input type="text" name="username">
    <input type="submit" value="登录">
  </form>


  </body>
</html>

登陆成功:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    /**
     * 此处用来判断,如果账户被注销,
     * 里面保存的数据 USER_NAME以及其value值被删除
     * 那么这个username会为空,加一层判断,为空则不允许继续访问该页面,跳转回登陆首页
     * 不建议在这里实现这个功能,建议使用过滤器完成
     */

//    Object username = request.getSession().getAttribute("USER_NAME");
//    if (username==null){
//        response.sendRedirect("/index.jsp");
//    }
%>
<h1>您好,欢迎登陆</h1>
<a href="/delete">注销</a>
<%
out.print(request.getSession().getAttribute("USER_NAME"));
%>
</body>
</html>

登陆失败:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>抱歉,登陆失败!</h1>
</body>
</html>

监听器:注销后不能直接通过地址进入登陆页面

package com.wang.login;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSessionListener;
import java.io.IOException;

public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
            //首先要把这里的ServletRequest和ServletResponse强转为HttpServletRequest和HttpServletResponse
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //强制转换后才能拿到它的Session
        Object userName = request.getSession().getAttribute("USER_NAME");
        if (userName==null){
            response.sendRedirect("/error.jsp");
        }


        //什么都不做,但这一句必须写,让程序可以继续执行下去
        filterChain.doFilter(req,resp);

    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

登陆时请求处理:

package com.wang.login;

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

public class login extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        if (username.equals("admin")){
            req.getSession().setAttribute("USER_NAME",req.getSession().getId());
            resp.sendRedirect("/sys/success.jsp");
        }else {
            resp.sendRedirect("/error.jsp");
        }
    }

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

注销时请求的处理;

package com.wang.login;

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

public class delete extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getSession().removeAttribute("USER_NAME");
        resp.sendRedirect("/index.jsp");
    }

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

web.xml中注册上面的Servlet,Filter,

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>com.wang.login.login</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/lo</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>delete</servlet-name>
        <servlet-class>com.wang.login.delete</servlet-class>
    </servlet>  
    <servlet-mapping>
        <servlet-name>delete</servlet-name>
        <url-pattern>/delete</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>SysFilter</filter-name>
        <filter-class>com.wang.login.SysFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SysFilter</filter-name>
        <url-pattern>/sys/*</url-pattern>
    </filter-mapping>
</web-app>

由此可以实现页面之间的相互跳转,可以把上面的公共变量提取出来,写到一个单独的类中,写成静态常量,这样可以减少修改时产生的一些麻烦

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wang</groupId>
    <artifactId>javawweb-filter-02</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--        Servlet的依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- JSP的依赖 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>

        <!-- JSLTL表达式的依赖 -->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- standard标签库 -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

    </dependencies>

</project>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值