收藏alreadyjava

JavaWeb 基础

2022-02-26  本文已影响0人  yjtuuige

一、基本概念

1.1 概述

1.2 Web 应用程序

1.3 静态 Web

1.4 动态 Web

二、Web 服务器

2.1 实现方式

  1. ASP
  1. php
  1. JSP/Servlet

2.2 Web 应用服务器

三、Tomcat

四、HTTP

4.1 HTTP 概述

4.2 两个时代

4.3 Http 请求

Request URL:https://www.baidu.com/  # 请求地址
Request Method:GET  # get方法/post方法
Status Code:200 OK  # 状态码:200
Remote Address:14.215.177.39:443    # 远程地址
Accept:text/html
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9  # 语言
Cache-Control:max-age=0
Connection:keep-alive   # 保持连接
  1. 请求行
  1. 消息头
Accept: # 告诉浏览器,所支持的数据类型
Accept-Encoding:    # 支持编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:    # 告诉浏览器,语言环境
Cache-Control:  # 缓存控制
Connection: # 告诉浏览器,请求完成是断开还是保持连接
HOST:   # 主机..../.

4.4 Http 响应

Cache-Control:private   # 缓存控制
Connection:Keep-Alive   # 保持连接
Content-Encoding:gzip   # 编码
Content-Type:text/html  # 文件类型
  1. 响应体
Accept: # 告诉浏览器,所支持的数据类型
Accept-Encoding:    # 支持编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language:    # 告诉浏览器,语言环境
Cache-Control:  # 缓存控制
Connection:# 告诉浏览器,请求完成是断开还是保持连接
HOST:   # 主机..../.
Refresh:    # 告诉客户端,多久刷新一次
Location:# 网页重新定位
  1. 响应状态码

五、Maven

六、Servlet

6.1 Servlet 简介

6.2 构建 ServLet

  1. 构建 Maven 项目
  1. Maven 环境配置及优化:
  1. 编写 Servlet 程序
public class HelloServlet extends HttpServlet {
    // doGet,doPost只是请求实现的不同方式,逻辑一样,可相互调用
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // ServletOutputStream outputStream = resp.getOutputStream();
        // 响应流
        PrintWriter writer = resp.getWriter();
        writer.println("Hello Servlet!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--注册Servlet-->
<servlet>
    <!--名字自定义,但要与下面映射名字保持一致-->
    <servlet-name>hello</servlet-name>
    <!--对应的Servlet程序-->
    <servlet-class>com.study.servlet.HelloServlet</servlet-class>
</servlet>

<!--Servlet的请求路径-->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <!--路径名自定义,访问:localhost:8080/Tomcat路径映射/路径名-->
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

为什么需要映射:

  1. 配置 Tomcat 测试程序

6.3 Servlet 原理

6.4 映射路径 Mapping

<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

6.5 ServletContext 上下文

  1. 共享数据
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // this.getInitParameter(); // 初始化参数
        // this.getServletConfig(); // Servlet 配置
        // ServletContext:Servlet 上下文
        ServletContext context = this.getServletContext();
        String username = "测试";
        // 保存数据:格式  键,值
        context.setAttribute("username", username);        
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 创建 ServletContext 对象
        ServletContext context = this.getServletContext();
        // 获取数据,转换成String类型
        String username = (String) context.getAttribute("username");
        // 设置编码格式
        resp.setContentType("text/html");
        resp.getWriter().println("名字:" + username);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<servlet>
    <servlet-name>set</servlet-name>
    <servlet-class>com.study.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>set</servlet-name>
    <url-pattern>/set</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>get</servlet-name>
    <servlet-class>com.study.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>get</servlet-name>
    <url-pattern>/get</url-pattern>
</servlet-mapping>
  1. 获取初始化参数
<!--配置Web应用初始化参数-->
<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = this.getServletContext();
    // 获取参数信息 字符串对应配置文件中的参数名
    String url = context.getInitParameter("url");
    resp.getWriter().println(url);
}
  1. 请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = this.getServletContext();
    // 转发的请求路径
    // RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");
    // 调用forward实现请求转发;
    // requestDispatcher.forward(req,resp);
    // 字符串为需要转发的另一个Servlet程序路径
    context.getRequestDispatcher("/url").forward(req,resp);
}
  1. 读取资源文件
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 文件流读取资源文件,第一个路径前必须要有 /
    // getResourceAsStream 将资源转换为流
    InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/study/servlet/aa.properties");
    // 创建属性集合对象
    Properties prop = new Properties();
    prop.load(is);
    String user = prop.getProperty("username");
    String pwd = prop.getProperty("password");
    resp.setContentType("text/html");
    resp.getWriter().println(user + ":" + pwd);
}
<!--在build中配置resources,防止资源导出失败的问题-->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

6.6 HttpServletResponse 响应

  1. 简单分类
// 字节流
ServletOutputStream getOutputStream() throws IOException;
// 字符流 中文
PrintWriter getWriter() throws IOException;
void setCharacterEncoding(String var1); // 编码
void setContentLength(int var1);    // 字符长度
void setContentLengthLong(long var1);
void setContentType(String var1);   // 类型
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;    // 响应成功
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;  // 重定向相关
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404; // 找不到资源
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500; // 服务器错误
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;   // 网关错误
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
方法名 说明
response.sendRedirect(URL url) 重定向
setContentType(String type) 设置输出内容(MIME)类型(text/html)
setContentLength(int length) 设置响应报文的长度
getWriter( ) 获取输出字符流
addHeader( String name, String value) 添加指定的键值到响应头信息中
containsHeader(String name) 判断响应的头部是否被设置
encodeURL(String url) 编码指定的URL
sendError(int sc) 使用指定状态码发送一个错误到客户端
setHeader( String name, String value) 设置指定响应头的值
setStatus(int sc) 给当前响应设置状态
  1. 下载文件
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 1.获取下载文件的路径
    String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/images/01.png");
    System.out.println("下载文件的路径:" + realPath);
    // 2.下载的文件名
    String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
    // 3.设置浏览器的下载支持(Content-Disposition),并将文件名转码,避免乱码
    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.获取 OutputStream 对象
    ServletOutputStream out = resp.getOutputStream();
    // 7.将 FileOutputStream 流写入到 buffer 缓冲区,使用 OutputStream,将缓冲区中的数据,输出到客户端
    while ((len = in.read(buffer)) > 0) {
        out.write(buffer, 0, len);
    }
    // 8.关闭流
    in.close();
    out.close();
}
  1. 验证码功能
public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 让浏览器10秒自动刷新一次;
        resp.setHeader("refresh", "10");
        // 在内存中创建一个图片
        BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        // 得到图片     g 为笔
        Graphics2D g = (Graphics2D) image.getGraphics();
        // 设置图片的背景颜色
        g.setColor(Color.white);
        g.fillRect(0, 0, 80, 20);
        // 给图片写数据
        g.setColor(Color.BLUE);
        g.setFont(new Font(null, Font.BOLD, 20));
        g.drawString(makeNum(), 0, 20);
        // 告诉浏览器,这个请求用图片的方式打开
        resp.setContentType("image/png");
        // 网站存在缓存,不让浏览器缓存
        resp.setDateHeader("expires", -1);
        resp.setHeader("Cache-Control", "no-cache");
        resp.setHeader("Pragma", "no-cache");
        // 把图片写给浏览器
        ImageIO.write(image, "png", resp.getOutputStream());
    }

    // 生成随机数
    private String makeNum() {
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7 - num.length(); i++) {
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  1. 实现重定向
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    /*
        实现过程:
        resp.setHeader("Location","/r/img");
        resp.setStatus(302);
     */
    //  ‘/’ 表示:http://localhost:8080
    resp.sendRedirect("/r/img");
}
  1. 简单实现登录重定向
<div>
    <%--这里提交的路径,需要寻找到项目的路径--%>
    <%--${pageContext.request.contextPath}代表当前的项目--%>
    <form action="${pageContext.request.contextPath}/login" method="get">
        <p>
            <label for="username">用户名:</label>
            <input type="text" id="username" name="username">
        </p>
        <p>
            <label for="password">密码:</label>
            <input type="password" id="password" name="password">
        </p>
        <input type="submit">
    </form>
</div>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 处理请求  getParameter:获取参数
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    System.out.println(username + ":" + password);
    // 注意,路径问题(/r1虚拟映射地址),否则404;
    resp.sendRedirect("/r1/success.jsp");
}
<servlet>
    <servlet-name>request</servlet-name>
    <servlet-class>com.study.servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>request</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>success</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>

6.7 HttpServletRequest 请求

方法名 含义
String getHeader(String name) 获取请求中的报头信息
Enumeration getHeaderNames() 获取请求中所有报头名的集合
String getContextPath() 获取请求上下文路径(webapp的)
String getRequestURI() 获取请求中的 URI
String getMethod( ) 获取 HTTP 请求方法,GET 还是 POST
getRemoteAddr() 远程 IP,即客户端 IP
方法名 含义
String getParameter(String name) 获取请求(表单)中参数名为 name 的参数值
String[] getParameterValues(String name) 获取请求中(表单)中所有参数名为 name 的参数值的集合(数组)
Enumeration getParameterNames( ) 获取请求中所有参数名的集合(枚举 不常用)
方法名 说明
setCharacterEncoding("utf-8") 设置请求的编码方式
getLocalAddr() 获取本地 IP,即服务器 IP
getLocalName() 获取本地名称,即服务器名称
getLocalPort() 获取本地端口号,即 Tomcat 端口号
getLocale() 用户的语言环境
getProtocol() 协议,http协议
getQueryString() 查询字符串
getRemotePort() 远程端口,即客户端端口
getRemoteUser() 远程用户
getRequestedSessionId() 客户端的 Session 的 ID
getRequestURI() 用户请求的 URL
getScheme() 协议头,例如 http
getServerName() 服务器名称
getServerPort() 服务器端口
getServletPath() Servlet 路径

HttpServletRequest 测试:获取表单信息

<form action="${pageContext.request.contextPath}/login" method="post">
    <p>
        <label for="username">用户名:</label>
        <input type="text" id="username" name="username">
    </p>
    <p>
        <label for="password">密码:</label>
        <input type="password" id="password" name="password">
    </p>
    <p>
        <input type="checkbox" name="hobbies" value="运动">运动
        <input type="checkbox" name="hobbies" value="阅读">阅读
        <input type="checkbox" name="hobbies" value="购物">购物
        <input type="checkbox" name="hobbies" value="电影">电影
    </p>
    <input type="submit">
</form>
@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[] hobbies = req.getParameterValues("hobbies");
    // 后台接收中文乱码问题
    System.out.println("username:" + username);
    System.out.println("password:" + password);
    System.out.println("========================");
    System.out.println(Arrays.toString(hobbies));
    System.out.println("========================");

    System.out.println(req.getContextPath());
    // 通过请求转发
    // 这里的 / 代表当前的web应用
    req.getRequestDispatcher("/success.jsp").forward(req, resp);
}
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.study.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

getRequestDispatcher 转发的两种方式:

七、Cookie、Session

7.1 会话

7.2 保存会话的两种技术

7.3 Cookie

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 解决乱码问题
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html");
    // 获取响应流
    PrintWriter out = resp.getWriter();
    // 服务器从客户端请求中获取Cookie,返回数组(Cookie存在多个)
    Cookie[] cookies = req.getCookies();
    // 判断Cookie是否存在
    if (cookies != null) {
        // 如果Cookie存在
        out.write("上一次访问时间:");
        // 遍历 cookies
        for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            // 获取Cookie的名字
            if (cookie.getName().equals("lastLoginTime")) {
                // 获取Cookie的值,并转化成长整型(时间戳)
                Long lastLoginTime = Long.parseLong(cookie.getValue());
                // 将时间戳转换为日期格式
                Date date = new Date(lastLoginTime);
                out.write(date.toLocaleString());
            }
        }
    } else {
        out.write("第一次访问!");
    }
    // 服务器给客户端响应(发送)一个Cookie
    // System.currentTimeMillis()+"":获取时间,并转成字符串
    Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
    // 设置Cookie有效期,1天
    cookie.setMaxAge(24 * 60 * 60);
    resp.addCookie(cookie);
}
// 获得Cookie
Cookie[] cookies = req.getCookies();
// 获得cookie中的key
cookie.getName();
// 获得cookie中的vlaue
cookie.getValue();
 // 新建一个cookie(设置新的cookie)
new Cookie("lastLoginTime", System.currentTimeMillis()+"");
// 设置cookie的有效期1天
cookie.setMaxAge(24*60*60);
// 响应(发送)给客户端一个cookie
resp.addCookie(cookie);
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 创建另一个Cookie,名字与之前的必须相同(键不能重复)
    Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
    // 设置Cookie有效期为0
    cookie.setMaxAge(0);
    resp.addCookie(cookie);
}
// 对中文Value值编码
URLEncoder.encode("中文的Cookie数据","utf-8")
// 解码
URLDecoder.decode(cookie.getValue(),"UTF-8")

7.4 Session(重点)

方法名 说明
getCreationTime():long 返回 Session 的创建时间
getId():String 返回 Session 的唯一 ID
getLastAccessedTime():long 返回 Session 的最后活跃时间
getServletContext():ServletContext 获取 Servlet 上下文(Web 服务)
getMaxInactiveInterval():int 返回 Session 的超时时间,秒
setMaxInactiveInterval(int interval) 设置 Session 的超时时间,秒
getAttribute(String name):Object 返回 Session 属性
setAttribute(String name, Object value) 设置 Session 属性
getAttributeNames():Enumeration 返回 Session 中存在的属性名
removeAttribute(String name) 移除 Session 属性
invalidate() 注销
isNew():boolean 判断 Session 是否是新创建

Session 测试:

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 解决乱码
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html");

    // 获取Session
    HttpSession session = req.getSession();
    // Session中存值
    session.setAttribute("name", "Session测试");
    // Session 中存储对象
    session.setAttribute("name1", new Person("学生1",20));

    // 获取Session的ID
    String id = session.getId();

    //Session创建的时候,把Session ID响应(发送)给了Cookie
    // Cookie cookie = new Cookie("JSESSIONID",sessionId);
    // resp.addCookie(cookie);

    // 判断Session是不是新创建
    if (session.isNew()) {
        resp.getWriter().write("Session 创建成功,ID:" + id);
    } else {
        resp.getWriter().write("Session ID:" + id);
    }
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 解决乱码
    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");
    resp.setContentType("text/html");

    // 获取Session
    HttpSession session = req.getSession();
    // 获取Session的值
    String name = (String) session.getAttribute("name");
    // 获取Session存储的对象
    Person name1 = (Person) session.getAttribute("name1");

    // 把Session的值响应(发送)给客户端
    resp.getWriter().write("name:" + name);
    resp.getWriter().write("<br/>");
    resp.getWriter().write("name1:" + name1);
    // 输出到控制台测试
    System.out.println(name);
    System.out.println("==========================");
    System.out.println(name1);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 获取Session
    HttpSession session = req.getSession();
    // 移除 Session 属性
    session.removeAttribute("name");
    // 手动注销Session:注销后,会重新生成Session ID
    session.invalidate();
}
<!--设置Session默认的失效时间-->
<session-config>
    <!--3分钟后Session自动失效,以分钟为单位-->
    <session-timeout>3</session-timeout>
</session-config>

八、JSP

8.1 什么是 JSP

8.2 JSP原理

分析 JSP 执行的过程:

结论:

// 初始化
public void _jspInit() {
}
// 销毁
public void _jspDestroy() {
}
// JSPService
public void _jspService(HttpServletRequest request, HttpServletResponse response) {
}

JSP 的执行过程

  1. 判断请求:

    • GET;
    • POST;
  2. 内置一些对象:

    // 页面上下文
    final jakarta.servlet.jsp.PageContext pageContext;
    // session
    jakarta.servlet.http.HttpSession session = null;
    // applicationContext    ServletContext改名
    final jakarta.servlet.ServletContext application;
    // 配置
    final jakarta.servlet.ServletConfig config;
    // out:输出
    jakarta.servlet.jsp.JspWriter out = null;
    // page:当前
    final java.lang.Object page = this;
    
    // 请求
    HttpServletRequest request
    // 响应
    HttpServletResponse response
    
  3. 输出页面前,增加的代码:

    // 设置响应的页面类型
    response.setContentType("text/html");
    pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);
    _jspx_page_context = pageContext;
    application = pageContext.getServletContext();
    config = pageContext.getServletConfig();
    session = pageContext.getSession();
    out = pageContext.getOut();
    _jspx_out = out;
    
  4. 以上的对象,可以在 JSP 页面中直接使用;

8.3 JSP 基础语法

8.4 JSP 指令

<%@ 指令名称 属性1="属性值1" 属性2="属性值2" ... 属性n="属性值n" %>
  1. page 指令
<%--设置文件格式和编码格式--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入包--%>
<%@ page import="java.util.Date" %>
<%--自定义错误页面--%>
<%@ page errorPage="error/500.jsp" %>
<error-page>
    <!--错误代码-->
    <error-code>404</error-code>
    <!--设置对应跳转页面-->
    <location>/error/404.jsp</location>
</error-page>
属性 描述
buffer 指定 out 对象使用缓冲区的大小
autoFlush 控制 out 对象的 缓存区
contentType 指定当前 JSP 页面的MIME类型和字符编码
errorPage 指定当 JSP 页面发生异常时需要转向的错误处理页面
isErrorPage 指定当前页面是否可以作为另一个 JSP 页面的错误处理页面
extends 指定 servlet 从哪一个类继承
import 导入要使用的 Java 类
info 定义 JSP 页面的描述信息
isThreadSafe 指定对 JSP 页面的访问是否为线程安全
language 定义 JSP 页面所用的脚本语言,默认是 Java
session 指定 JSP 页面是否使用 session
isELIgnored 指定是否执行 EL 表达式
isScriptingEnabled 确定脚本元素能否被使用
  1. Include 指令
<%@ include file="included.jsp"%>

<%--
    JSP标签方式拼接
    jsp:include:拼接页面,每个页面还是单独的整体
--%>
  1. Taglib 指令
<%--核心标签(c)是最常用的 JSTL标签 --%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

8.5 JSP 内置对象及作用域

<%--内置对象:存入属性值--%>
<%
    // 保存的数据只在一个页面中有效
    pageContext.setAttribute("name1", "pageContext");
    // 保存的数据只在一次请求中有效,请求转发会携带这个数据
    request.setAttribute("name2", "request");
    // 保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    session.setAttribute("name3", "session");
    // 保存的数据只在服务器中有效,从打开服务器到关闭服务器
    application.setAttribute("name4", "application");
%>
<%--取出属性值--%>
<%
    // JSP代码内的java代码,必须保证语法的正确
    // 通过寻找方式取值,从底层到高层(作用域)
    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");
%>
<%--测试转发携带数据--%>
<%
    pageContext.forward("/jsp3.jsp");
    // 作用等同
    // request.getRequestDispatcher("/index.jsp").forward(request,response);
%>

<%--使用EL表达式输出 ${变量}--%>
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>   // 未创建变量,页面不显示
<%--EL表达式会过滤 null值,普通表达式不能--%>
<h3><%= name5 %></h3>   // 未创建变量,页面显示 null
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>

对象作用域及应用场景:

8.6 JSP 标签、JSTL 标签、EL 表达式

<%--包含页面--%>
<jsp:include page="jsp3.jsp"></jsp:include>

<%--
http://localhost:8080/test.jsp?name=liu&age=20
--%>
<%--转发、携带参数转发--%>
<jsp:forward page="/test.jsp">
    <jsp:param name="name" value="liu"></jsp:param>
    <jsp:param name="age" value="20"></jsp:param>
</jsp:forward>

核心标签(掌握):

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

标签库添加依赖说明:Tomcat 版本 10.0.16

  1. pom.xml 文件中,增加依赖,导入标签库依赖;

    <!--标签库依赖-->
    <dependency>
        <groupId>org.apache.taglibs</groupId>
        <artifactId>taglibs-standard-spec</artifactId>
        <version>1.2.5</version>
    </dependency>
    <!--
        如果不够,再补充下面这个依赖
        <dependency>
            <groupId>org.apache.taglibs</groupId>
            <artifactId>taglibs-standard-impl</artifactId>
            <version>1.2.5</version>
        </dependency>
    -->
    
    • 依赖关系图:
  2. 将导入的 jar 包,复制到 Tomcat 服务器的 lib 目录下:(避免 JSTL 解析错误

    • jakarta.servlet.jsp.jstl-api-2.0.0.jar

    • jakarta.servlet.jsp.jstl-2.0.0.jar

    • taglibs-standard-spec-1.2.5.jar

    • Tomcat 的 lib 目录:

<%--表单测试:以get方式,提交给当前页面--%>
<form action="coreif.jsp" method="get">
    <%--
        EL表达式获取表单中的数据:${param.参数名}
    --%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="登录">

    <%--如果用户名=admin,登录成功 var 为布尔值--%>
    <c:if test="${param.username=='admin'}" var="isAdmin">
        <c:out value="管理员登录!"/>
    </c:if>
    <%--输出布尔值,注意自闭合标签--%>
    <c:out value="${isAdmin}"/>
</form>
<%--定义一个变量score,值为85--%>
<c:set var="score" value="85"/>
<c:choose>
    <%--从上往下匹配--%>
    <c:when test="${score>=90}">
        优秀
    </c:when>
    <c:when test="${score>=80}">
        良好
    </c:when>
    <c:when test="${score>=70}">
        一般
    </c:when>
    <c:when test="${score<=60}">
        不及格
    </c:when>
</c:choose>
<%
    // 创建集合,并添加数据,注意:索引从0开始
    ArrayList<String> people = new ArrayList<>();
    people.add(0, "张三");
    people.add(1, "李四");
    people.add(2, "王五");
    people.add(3, "赵六");
    people.add(4, "田七");
    // 把集合添加到request(请求)中
    request.setAttribute("list", people);
%>
<%--
    var:每一次遍历出来的变量
    items:要遍历的对象
    begin:哪里开始
    end:到哪里
    step:步长
--%>
<%--从请求中遍历数据,注意:被取值的变量要包含在 ${} 中}--%>
<c:forEach var="student" items="${list}">
    <c:out value="${student}"/><br/>
</c:forEach>
<hr/>
<c:forEach var="student" items="${list}" begin="1" end="3" step="1">
    <c:out value="${student}"/><br/>
</c:forEach>

可能遇到的问题

九、JavaBean

9.1 实体类

9.2 字段映射

<%
    // People people = new People();
    // people.setId();
    // people.setName();
    // people.setAge();
    // people.setAddress();
%>
<%--创建对象--%>
<jsp:useBean id="people" class="com.study.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="20"/>
<jsp:setProperty name="people" property="address" value="北京"/>
<%--取值--%>
<%--表达式方式:<%=people.getAddress()%>--%>
ID:<jsp:getProperty name="people" property="id"/><br/>
姓名:<jsp:getProperty name="people" property="name"/><br/>
年龄:<jsp:getProperty name="people" property="age"/><br/>
地址:<jsp:getProperty name="people" property="address"/><br/>

十、MVC 三层架构

10.1 以前的架构

10.2 MVC 三层架构

十一、Filter(重点):过滤器

11.1 Filter 概述

11.2 Filter 开发步骤

  1. 导包:

    • 注意:不要导错包,选 Servlet 包;

  2. 编写过滤器:

    • 实现 Filter 接口, 重写对应的方法;
    // 通过注解,设置过滤路径:show下的所有请求都被过滤
    // 也可以通过 web.xml 文件配置
    @WebFilter("/show/*")
    public class CharacterEncodingFilter implements Filter {
        // 初始化:web服务器启动,过滤器就初始化了,随时等待过滤对象出现
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("CharacterEncodingFilter 初始化");
        }
    
        // FilterChain : 链
        /*
            1.过滤中的所有代码,在过滤特定请求的时候,都会执行
            2.必须要让过滤器继续执行
            filterChain.doFilter(request,response);
        */
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("过滤器执行前");
            // 设置过滤执行的内容
            servletRequest.setCharacterEncoding("utf-8");
            servletResponse.setCharacterEncoding("utf-8");
            servletResponse.setContentType("text/html;charset=UTF-8");
    
            // 让请求继续执行,如果不写,程序到这里就被拦截,停止!
            filterChain.doFilter(servletRequest, servletResponse);
            System.out.println("过滤器执行后");
        }
    
        // 销毁:web服务器关闭的时候,过滤器才会销毁
        @Override
        public void destroy() {
            System.out.println("CharacterEncodingFilter 销毁");
        }
    }
    
  3. web.xml 中配置 Filter:

    • 也可以通过注解方式:@WebFilter("/show/*")
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.study.filter.CharacterEncodingFilter</filter�class>
        </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--只要是 /show 下的任何请求,会经过这个过滤器-->
        <url-pattern>/show/*</url-pattern>
        <!--过滤所有内容,不建议使用-->    
        <!--<url-pattern>/*</url-pattern>-->
    </filter-mapping>
    

十二、监听器 Listener(了解)

// 统计网站在线人数:统计session
// 注解方式:注册监听,也可以通过web.xml设置
@WebListener
public class OnlineCountListener implements HttpSessionListener {
    // 创建session监听:监测程序执行
    // 一旦创建Session,就触发一次这个事件
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // 获取上下文:作用域提升到最大
        ServletContext context = se.getSession().getServletContext();
        // 获取在线人数
        Integer onlineCount = (Integer) context.getAttribute("onlineCount");
        // 如果为空,赋值为1
        if (onlineCount == null) {
            onlineCount = 1;
        } else {
            // 不为空,值自增
            onlineCount++;
        }
        // 将属性存储到上下文
        context.setAttribute("onlineCount", onlineCount);
        System.out.println("监听初始化");
    }

    // 销毁session监听
    // 一旦销毁Session,就触发一次这个事件
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        // 过程与创建相反
        ServletContext context = se.getSession().getServletContext();
        Integer onlineCount = (Integer) context.getAttribute("onlineCount");
        // 如果为空,赋值为0
        if (onlineCount == null) {
            onlineCount = 0;
        } else {
            onlineCount--;
        }
        // 将属性存储到上下文
        context.setAttribute("onlineCount", onlineCount);
        System.out.println("监听销毁");
    }
    /*
        Session销毁:
        1.手动销毁:getSession().invalidate();
        2.自动销毁:设置web.xml
    */
}
<%=this.getServletConfig().getServletContext().getAttribute("onlineCount")%>
<listener>
    <listener-class>com.study.listener.OnlineCountListener</listener-class>
</listener>

十三、过滤器、监听器常见应用

13.1 监听器在 GUI 中的应用

public class TestPanel {
    public static void main(String[] args) {
        // 新建一个窗体
        Frame frame = new Frame("GUI 监听测试");
        // 面板
        Panel panel = new Panel(null);
        // 设置窗体的布局
        frame.setLayout(null);
        // 设置背景颜色
        frame.setBounds(300, 300, 500, 500);
        frame.setBackground(new Color(217, 217, 217));
        panel.setBounds(50, 50, 300, 300);
        // 设置背景颜色
        panel.setBackground(new Color(70, 142, 192));
        frame.add(panel);
        frame.setVisible(true);
        // 监听事件:监听关闭事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
    }
}

13.2 Filter 实现权限拦截:

测试:

<%--login.jsp--%>
<form action="<%= request.getContextPath()%>/login" method="post">
    <input type="text" name="username">
    <input type="submit">
</form>

<%--error.jsp--%>
<h3>没有权限,用户名错误</h3>
<p><a href="<%= request.getContextPath()%>/login.jsp">返回登录页面</a></p>

<%--/sys/success.jsp--%>
<h1>登录成功</h1>
<p><a href="<%= request.getContextPath()%>/logout">注销</a></p>
public class Constant {
    public static final String USER_SESSION = "USER_SESSION";
}
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取前端的请求参数
        String username = req.getParameter("username");

        if (username.equals("admin")) {
            // 登录成功:把属性值存入session
            req.getSession().setAttribute(Constant.USER_SESSION, req.getSession().getId());
            // 获取路径后,再拼接地址
            // 注意:如果路径用相对路径表示,”/“表示:http://localhost:8080,与转发的不同
            resp.sendRedirect(req.getContextPath()+"/sys/success.jsp");
        } else {
            // 登录失败
            // 请求转发
            // req.getRequestDispatcher("/error.jsp").forward(req,resp);
            // 重定向
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取session
        Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);
        // 如果不为空,移除 Session 属性
        if (user_session != null) {
            req.getSession().removeAttribute(Constant.USER_SESSION);
        }
        // 重定向
        resp.sendRedirect(req.getContextPath() + "/login.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
// 过滤所有sys下的请求
@WebFilter("/sys/*")
public class SysFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        // 类型转换:获取session,重定向
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        // 过滤:所有session为空,跳转页面
        if (request.getSession().getAttribute(Constant.USER_SESSION) == null) {
            response.sendRedirect(request.getContextPath() + "/error.jsp");
        }
        chain.doFilter(req, resp);
    }

    @Override
    public void destroy() {
    }
}

过滤器实现,不同用户登录不同页面

// 通过对象属性判断
if (request.getSession().getAttribute(Constant.USER_SESSION).Level == VIP1) {
    response.sendRedirect( "vip1/index.jsp");
}
if (request.getSession().getAttribute(Constant.USER_SESSION).Level == VIP2) {
    response.sendRedirect( "vip2/index.jsp");
}
if (request.getSession().getAttribute(Constant.USER_SESSION).Level == VIP3) {
    response.sendRedirect( "vip3/index.jsp");
}

十四、JDBC

14.1 实验环境搭建

<!--MySQL 依赖-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

<!--druid 依赖-->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.2.8</version>
</dependency>

14.2 JDBC 固定步骤

  1. 加载驱动;
  2. 连接数据库,代表数据库;
  3. 向数据库发送 SQL 的对象 Statement : CRUD;
  4. 编写 SQL(根据业务,不同的 SQL);
  5. 执行 SQL;
  6. 关闭连接;

14.3 事务

14.4 Junit 单元测试

上一篇下一篇

猜你喜欢

热点阅读