个人笔记JSP

JSP

java Server Pages:Java服务器端页面,也和Servlet应用,用于动态web

1.特点

  • 写JSP就像再写HTML

  • 区别

    • HTML只给用户提供静态的数据

    • JSP页面中可以嵌入Java代码,为用户提供动态数据

2.原理

浏览器像服务器发送请求,不管访问什么资源,其实都是在访问Servlet

JSP最终也会被转换成为一个Java类

JSP本质上就是一个Servlet

在JSP页面中,只要是java代码就会原封不动的输出

HTML代码,就会被转换成:out.write("<html>\r\n");

3.JSP基础语法

<%--JSP表达式
作用将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
​
<%= new java.util.Date()%>

<%--JSP脚本片段--%>
<%
    int sum = 0;
    for (int i = 1; i <100 ; i++) {
        sum+=i;
    }
    out.println(sum);
%>

JSP声明:会被编译到ISP生成Java的类中!其他的,就会被生成到_jspService方法中!

JSP的注释,不会在客户端显示,HTML就会!

4.JSP指令

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
​
<%--@include会将两个页面合二为一--%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>
​
<hr>
​
<%--jsp标签
jsp:include: 拼接页面,本质还是三个
--%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>
​
</body>
</html>

5.九大内置对象

  • PageContext 存东西

  • Request 存东西

  • Response

  • Session 存东西

  • Application 【ServletContext】存东西

  • config 【ServletConfig】

  • out

  • page

  • exception

从pageContext取出,我们通过寻找的方式来 从底层到高层(作用域):page->request-->session-->application

<%-- 内置对象--%>
<%
    pageContext.setAttribute("name1", "秦疆1号"); // 保存的数据只在一个页面中有效
    request.setAttribute("name2", "秦疆2号"); // 保存的数据只在一次请求中有效,请求转发会携带这个数据
    session.setAttribute("name3", "秦疆3号"); // 保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    application.setAttribute("name4", "秦疆4号"); // 保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
​
<%-- 脚本片段中的代码,会被原封不动生成到.JSP.java
要求:这里面的代码:必须保证Java语法的正确性
--%>
<%
    // 从pageContext取出,我们通过寻找的方式来
    // 从底层到高层(作用域):page->request-->session-->application
    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"); // 不存在
%>
​
<%-- 使用EL表达式输出  ${} --%>
​
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3><%=name5%> </h3>

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!

session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;

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

需要导包

    <!--JSTL表达式的依赖-->
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
    <dependency>
      <groupId>javax.servlet.jsp.jstl</groupId>
      <artifactId>jstl-api</artifactId>
      <version>1.2</version>
    </dependency>
    <!--standard标签库-->
    <!-- https://mvnrepository.com/artifact/taglibs/standard -->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>

EL表达式:${}

  • 获取数据

  • 执行运算

  • 获取web开发的常用对象

  • 调用Java方法

JSP标签

<%--jsp:include--%>

<%--
http://localhost:8080/jsptag.jsp?name=kuangshen&age=12
--%>

<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="name" value="kuangshen"></jsp:param>
    <jsp:param name="age" value="12"></jsp:param>
</jsp:forward>

JSTL标签

JSTL标签库的使用就是为了弥补HTML的标签的不足;

它自定义许多标签,可以供我们使用,标签的的功能和Java代码一样

需要导入JSTL标签库

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



<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入JSTL核心标签库,我们才能使用JSTL标签 core--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

</body>
</html>

核心标签

9.JavaBean

实体类

JavaBean有特定的写法:

  • 必须有一个无参构造

  • 属性必须私有化

  • 必须有对应的get/set方法

一般用来和数据库的字段做映射 ORM

ORM:对象关系映射

  • 表--->类

  • 字段--->属性

  • 行记录--->对象

10.MVC三层架构

Model 模型

View 视图

Controller 控制器

用户直接访问控制层,控制层就可以直接操作数据库

servlet--CRUD--数据库
    弊端:程序十分臃肿,不利于维护
    servlet的代码中:处理请求,响应,视图跳转,处理JDBC,处理业务代码,处理逻辑代码
​
    
架构
程序员调用
|
JDBC
|
MySQL Oracle sqlServer

Model

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

  • 数据持久层:CRUD (Dao)

View

  • 展示数据

  • 提供连接发起Service请求(a,form,img)

Controller(Service)

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

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

  • 控制视图的跳转

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

11.Filter

过滤器,用来过滤网站的数据

Filter开发步骤:

1.导包

2.编写过滤器

导包别错了,import jakarta.servlet.*;

实现Filter接口,重写对应的方法

package com.lyj.servlet;
​
import jakarta.servlet.*;
​
import java.io.IOException;
​
public class CharacterEncodingFilter implements Filter {
​
    //初始化,web服务器启动,就已经初始化了,随时等待过滤对象出现
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter init初始化chushihua==========");
    }
​
​
    //chain 链
//
//    1.过滤中的所有代码,在过滤特定请求的时候都会执行
//    2.必须要让过滤器继续同行
    @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("CharacterEncodingFilter执行之前");
        //让我们的请求继续走,如果不写,程序到这里就会被拦截停止
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("CharacterEncodingFilter执行之后");
​
    }
​
    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter destroy销毁xiaohui================");
    }
}
​

3.在web.xml中配置Filter

<?xml version="1.0" encoding="UTF-8"?>
<web-app
        xmlns="https://jakarta.ee/xml/ns/jakartaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
        version="6.0">
  <display-name>Welcome to Tomcat</display-name>
  <description>Welcome to Tomcat</description>
​
  <servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>com.lyj.servlet.ShowServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ShowServlet</servlet-name>
    <url-pattern>/show</url-pattern>
  </servlet-mapping>
​
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.lyj.servlet.CharacterEncodingFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/servlet</url-pattern>
  </filter-mapping>
</web-app>

12.监听器

package listener;

import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
import java.util.concurrent.atomic.AtomicInteger;

// 统计网站在线人数:通过监听Session创建与销毁实现
public class OnlineCountListener implements HttpSessionListener {

    // 使用线程安全的AtomicInteger替代普通Integer,解决并发问题
    private AtomicInteger onlineCount;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();

        // 从ServletContext中获取计数器,若不存在则初始化
        onlineCount = (AtomicInteger) ctx.getAttribute("OnlineCount");
        if (onlineCount == null) {
            onlineCount = new AtomicInteger(1);
        } else {
            // 线程安全的自增操作
            onlineCount.incrementAndGet();
        }

        ctx.setAttribute("OnlineCount", onlineCount);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext ctx = se.getSession().getServletContext();

        onlineCount = (AtomicInteger) ctx.getAttribute("OnlineCount");
        if (onlineCount == null) {
            onlineCount = new AtomicInteger(0);
        } else {
            // 线程安全的自减操作,确保不会出现负数
            onlineCount.decrementAndGet();
            if (onlineCount.get() < 0) {
                onlineCount.set(0);
            }
        }

        ctx.setAttribute("OnlineCount", onlineCount);
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<web-app
        xmlns="https://jakarta.ee/xml/ns/jakartaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
        version="6.0">
  <display-name>Welcome to Tomcat</display-name>
  <description>Welcome to Tomcat</description>

  <servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>com.lyj.servlet.ShowServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ShowServlet</servlet-name>
    <url-pattern>/show</url-pattern>
  </servlet-mapping>

  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.lyj.servlet.CharacterEncodingFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/servlet</url-pattern>
  </filter-mapping>


  
  
  <listener>
    <listener-class>listener.OnlineCountListener</listener-class>
  </listener>
</web-app>

<%@ page import="java.util.concurrent.atomic.AtomicInteger" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2>

<%
    // 从ServletContext中获取在线人数计数器
    AtomicInteger onlineCount = (AtomicInteger) application.getAttribute("OnlineCount");
// 处理空值情况,默认为0
    int count = (onlineCount != null) ? onlineCount.get() : 0;
%>

<h1>当前有<span><%= count %></span>人在线</h1>
</body>
</html>

13.过滤器,监听器应用

用户登录之后才能进入主页,用户注销后就不能进入主页了

1.用户登录之后,向Session中放入用户的数据

2.进入主页的时候要判断用户是否已经登录,要求:在过滤器中实现

LoginServlet

package com.lyj.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class LoginServlet extends HttpServlet {
    // 定义常量,便于维护
    private static final String VALID_USERNAME = "admin";
    private static final String SUCCESS_PAGE = "/sys/success.jsp";
    private static final String ERROR_PAGE = "/error.jsp";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置编码,确保中文正常处理
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        // 获取前端请求的参数
        String username = req.getParameter("username");

        // 登录成功/失败判断,使用常量避免硬编码,先判断非空
        if (username != null && VALID_USERNAME.equals(username)) {
            // 存储用户会话标识
            req.getSession().setAttribute("USER_SESSION", req.getSession().getId());
            resp.sendRedirect(req.getContextPath() + SUCCESS_PAGE);
        } else {
            resp.sendRedirect(req.getContextPath() + ERROR_PAGE);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 支持POST请求,直接调用doGet方法
        doGet(req, resp);
    }
}

LogoutServlet

package com.lyj.servlet;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取用户会话属性(注意:原代码中属性名可能拼写错误,此处统一用正确名称)
        Object userSession = req.getSession().getAttribute("USER_SESSION");

        // 逻辑修正:如果存在用户会话,则销毁会话
        if (userSession != null) {
            // 使整个会话失效(比单独移除属性更彻底)
            req.getSession().removeAttribute("USER_SESSION");
            //req.getSession().invalidate();
            // 跳转到登录页(使用上下文路径,避免硬编码问题)
            resp.sendRedirect(req.getContextPath() + "/login.jsp");
        } else {
            // 若会话不存在,直接跳转到错误页或登录页
            resp.sendRedirect(req.getContextPath() + "/error.jsp");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 支持POST请求,复用doGet逻辑
        doGet(req, resp);
    }
}

SysFilter

package com.lyj.listener;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 系统过滤器:拦截/sys/*路径的请求,验证用户是否已登录
 * 未登录用户将被重定向到错误页,已登录用户允许继续访问
 */
public class SysFilter implements Filter {

    /**
     * 过滤器初始化方法
     * 可用于加载过滤器所需的配置参数等初始化操作
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化逻辑(如无特殊需求可留空)
        Filter.super.init(filterConfig);
    }

    /**
     * 核心过滤方法:验证用户登录状态
     * @param servletRequest  请求对象
     * @param servletResponse 响应对象
     * @param filterChain     过滤器链,用于传递请求到下一个组件
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {

        // 类型转换:将ServletRequest转为HttpServletRequest以使用HTTP相关方法
        HttpServletRequest request = (HttpServletRequest) servletRequest;

        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 从会话中获取用户登录标识(与登录逻辑中的属性名保持一致)
        Object userSession = request.getSession().getAttribute("USER_SESSION");

        // 验证逻辑:如果用户未登录(会话中无USER_NAME)
        if (userSession == null) {
            // 重定向到错误页(使用上下文路径避免路径问题)
            response.sendRedirect(request.getContextPath() + "/error.jsp");
            // 注意:重定向后需return,避免继续执行后续逻辑
            return;
        }

        // 若用户已登录,将请求传递给下一个过滤器或目标资源
        filterChain.doFilter(request, response);
    }

    /**
     * 过滤器销毁方法
     * 可用于释放过滤器占用的资源
     */
    @Override
    public void destroy() {
        // 销毁逻辑(如无特殊需求可留空)
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app
        xmlns="https://jakarta.ee/xml/ns/jakartaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
        version="6.0">
  <display-name>Welcome to Tomcat</display-name>
  <description>Welcome to Tomcat</description>
​
  <servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>com.lyj.servlet.ShowServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ShowServlet</servlet-name>
    <url-pattern>/show</url-pattern>
  </servlet-mapping>
​
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.lyj.servlet.CharacterEncodingFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/servlet</url-pattern>
  </filter-mapping>
  
  <listener>
    <listener-class>com.lyj.listener.OnlineCountListener</listener-class>
  </listener>
  
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.lyj.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>
​
  <servlet>
    <servlet-name>LogoutServlet</servlet-name>
    <servlet-class>com.lyj.servlet.LogoutServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LogoutServlet</servlet-name>
    <url-pattern>/logout</url-pattern>
  </servlet-mapping>
​
​
  <filter>
    <filter-name>SysFilter</filter-name>
    <filter-class>com.lyj.listener.SysFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>SysFilter</filter-name>
    <url-pattern>/sys/*</url-pattern>
  </filter-mapping>
</web-app>

success,.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>success</title>
</head>
<body>
<h1>主页</h1>
<h3></h3>
​
<!-- 动态拼接应用上下文路径,避免路径错误 -->
<p><a href="${pageContext.request.contextPath}/logout">注销</a></p>
</body>
</html>

login.jsp

​
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login</title>
</head>
<body>
<h1>登录!!!!!!!!!</h1>
<form action="${pageContext.request.contextPath}/login"method="post">
  <input type="text" name="username" >
  <input type =submit>
</form>
</body>
</html>
​

error.jsp

​
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>错误错误</h1>
<h3>没有权限,用户名错误</h3>
​
<a href="login.jsp">返回登录页面</a>
</body>
</html>
​
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值