java web 学习笔记


title: java web 学习笔记
date: 2023-03-07 09:33:31.997
updated: 2023-03-21 10:59:19.966
url: https://hexo.start237.top/archives/javaweb-xue-xi-bi-ji
categories:

  • IT技术
    tags:
  • java

前言

今天是2023年3月7日,前面学习完成了java的基础语法和概念后,开始学习java web相关的知识。
因为看到都是比较老旧的技术,有点相跳过去,但是想了想。跳过去学习的话,可能也学不好,所以还是按着现有的老师规划的学习路径来按步就班的学习。
了解这门技术的过去,才能应用好现在的,在展望未来的。

使用Tomcat部署Java Web应用

Tomcat下载并安装

下载链接

选择Tomcat版本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D6ikr6wx-1685521480497)(null)]

下载安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8M40vamg-1685521480948)(null)]

文件目录说明

bin:存放各个平台下启动和停止Tomcat服务的脚本文件

conf:存放各种Tomcat服务器的配置文件

lib:存放Tomcat服务器所需要的jar文件

logs:存放的日志信息

temp:Tomcat运行时的临时文件

webapps:存放允许客户端访问的资源

work:存放 Tomcat将JSP转换之后的Servlet文件

在idea中创建一个Tomact java web程序

新建一个项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t9h8yGQ5-1685521481097)(null)]

选择 java Enterprise

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZThOJncN-1685521480465)(null)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CZRKPmeY-1685521480651)(null)]

给项目命名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ARUg8R6C-1685521480855)(null)]

配置编译器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L4GADnEv-1685521480586)(null)]

选择+号,选择 local

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IGcp2Bfd-1685521480800)(null)]

这个地方可以配置Tomcat的版本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DqYuDMSL-1685521480554)(null)]

配置Tomcat的项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eZIxhddA-1685521480887)(null)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oZ61S2Wd-1685521481152)(null)]

在项目上右键选择 open module settings

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JEZXNzxh-1685521480618)(null)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VHfdOekJ-1685521481002)(null)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n0AZFkJr-1685521480705)(null)]

选择这两个jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bDiQlugR-1685521480737)(null)]

Servlet

什么是Servlet?

Servlet是 java Web开发的基石,与平台无关的服务器组件,它是运行在Servlet容器/web应用服务器/Tomcat,负责一客户端进行通信。

Servlet的功能

  1. 创建并返回基于客户请求的动态HTML页面。
  2. 与数据库进行通信。

如何使用Servlet?

Servlet 本身是一组接口,自定义一个类,并且实现Servlet接口,这个类就具备了客户端请求以及做出响应的功能。


@WebServlet("/my")
public class MyServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("my");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

浏览器不能直接访问Servlet文件,只能通过映射的方式来间接访问Servlet,映射需要开发者手动配置,有两种配置方式。

  1. 使用xml方式
  2. 基于注解的方式

Servlet的生命周期

  1. 当浏览器访问Servlet的时候,Tomcat会查询当前Servlet的实例化对象是否存在,如果不存在,则通过反射机制创建对象。如果存在,直接执行第3步。
  2. 调用 init方法完成初始化操作。
  3. 调用 service方法完成业务逻辑操作。
  4. 关闭tomcat时,会调用destory方法。

Servlet的生命周期方法:无参构造、init、service、destory。

  1. 无参构造函数只调用一次,创建对象。
  2. service调用N次,执行业务方法
  3. destory只调用一次,卸载对象。

ServleConfig

该接口是用来描述Servlet的基本信息的。
getServletName() 返回 Servlet的名称,全类名(带着包名的类)
getInitParameter(String key) 获取init参数的值(web.xml)
getInitParameterNames() 返回所有的initParamter的name值,一般用作遍历初始化参数。
getServletContext() 返回ServletContext对象,它是Servlet的上下文,整个Servlet的管理者。
ServletConfig和ServletContext的区别:
ServletConfig作用于某个Servlet实例,每个Servlet都有对应的ServletConfig,ServletContext作用于整个Web应用,一个Web应用对应一个ServletContext,多个Selvlet实例对应一个ServletContext。

Servlet的层次结构

Servlet——>GenericServlet——>HttpServlet
HTTP请求有很多种类型,常用的有四种:
GET 读取
POST 保存
PUT 修改
DELETE 删除

GenericServlet实现Servlet接口,同时为它的子类屏蔽了不常用的方法,子类只需要重写service方法即可。
HttpServlet继承GenericServlet,根据请求类型进行分发处理,GET进入doGet方法,POST进入doPost方法。
开发者自定义的Servlet类只需要继承HttpServlet即可,重新doGet和doPost。

重写一个HttpServlet的类


package com.example.myservlet;

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

public class MyGenericServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}


package com.example.myservlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyHttpServlet extends MyGenericServlet{
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String method = request.getMethod();

        switch (method){
            case "GET":
                this.doGet(request,response);
                break;
            case "POST":
                this.doPost(request,response);
                break;
        }
    }

    public void doGet(HttpServletRequest res, HttpServletResponse req){
    }
    public void doPost(HttpServletRequest res, HttpServletResponse req){
    }
}




实现层

package com.example.myservlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/con")
public class Controller extends MyHttpServlet{
    @Override
    public void doPost(HttpServletRequest res, HttpServletResponse req) {
        req.setContentType("text/html;charset=UTF-8");
        try {
            req.getWriter().write("POST方法");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doGet(HttpServletRequest res, HttpServletResponse req) {
        req.setContentType("text/html;charset=UTF-8");
        try {
            req.getWriter().write("GET方法");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

JSP

JSP本质上就是一个Servlet,JSP主要负责与用户交互,将最终的界面呈现给用户,HTML+JS+CSS+java的混合文件。

当服务器接收到一个后缀是jsp的请求时,将该请求交给JSP引擎去处理,每一个JSP页面第一次被访问的时候,JSP引擎会将它翻译成一个Servlet文件,再由Web容器调用Servlet完成响应。

JSP脚本的嵌入

单纯从开发的角度看,JSP就是在HTML中嵌入java程序。

具体的嵌入方式有3种:

  1. JSP脚本、执行java逻辑代码
<% Java代码 %>
  1. JSP声明:定义java方法
<%!  声明Java方法 %>
  1. JSP 表达式:把java对象直接输出到HTML页面中
<%= Java变量 %>

<%--声明方法--%>
<%!
    public String a(){
        return "123";
    }
%>
<%--执行java脚本--%>
<% a(); %>
<%--输出java变量到HTML中--%>
<%= a()%>

JSP内置对象的9个

request

表示一次请求,HttpServletRequest

常用方法

request.getParameter("a");  // 获取客户端传来的参数
request.setAttribute("a",1);  // 通过键值对的形式保存数据
Integer i = (Integer)request.getAttribute("a");  // 通过key来取出 value
request.getRequestDispatcher("hello-servlet").forward(request,response); // 重新分发类似于重定向,但又和重定向有区别

response

表示请求一次响应 , HttpServletResponse

pageContext

页面的上下文,获取页面信息,来自于 PageContext。

session

表示一次会话。

application

表示当前Web应用,全局对象,保存所有用户的共享信息,ServletContext

config

当前JSP对应的Servlet的 ServletConfig对象,获取当前Servlet的信息。

out

向浏览器输出数据,JspWriter

page

当前JSP对象应的Servlet对象,Servlet

excerption

表示JSP页面发生的异常,Exception

常用的对象

request、response 、session、application、pageContext

request常用方法:

  1. String getParametes(String key) 获取客户端传来的参数。
  2. void setAttribute(String key ,Object value) 通过键值对的形式保存数据。
  3. Object gertAttribute(String key 通过key取出value。
  4. RequestDispatcher getRequestDispatcher(String path) 返回一个RequestDispatcher对象,该对象的forward方法用于请求转发。
  5. String[] getParameterValues() 获取客户端传来的多个同名参数。
  6. void setCharacterEncoding(String charset) 指定每个请求的编码。

HTTP请求状态码

200 正常
403 没有权限
404 资源找不到
400 请求类型不匹配
500 java程序抛出异常

response

  1. sendRedirect(String path)
    重定向,页面之间的跳转。

转发 getRequestDispatcher 和 重定向 sendRedirect 的区别:
转发是将同一个请求传给下一个页面,重定向是创建一个新的请求传给下一个页面,之前的请求结束生命周期。
转发:同一个请求在服务器之间传递,地址栏不变,也叫服务器跳转。
重定向:由客户端发送一次新的请求来访问跳转后的目标资源,地址栏改变,也叫客户端跳转。

如果两个页面之间要通过request来传值,则必须使用转发,不能使用重定向。

request.setAttribute("hello","my form index.jsp");
//request.getRequestDispatcher("hello-servlet").forward(request,response);
response.sendRedirect("hello-servlet");

用户登录 ,如果用户名和密码正确,则跳转到首页(转发),并且展示用户名,否则重新跳转到登录页。

Session

用户会话

服务器无法识别一次 HTTP 请求的出处(不知道来自于那个终端),它只会接受到一个请求信号,所以就存在一个问题:将用户的响应发送给其他人,必须有一种技术来让服务器知道请求来自哪,这就是会话技术。
会话:就是客户端和服务器之间发生的一系列连续的请求和响应的过程,打开浏览器进行操作到关闭浏览器的过程。
会话状态:指服务器和浏览器在会话过程中产生的状态信息,借助于会话状态,服务器能够把属于同一次会话的一系列请求和响应关联起来。

实现会话有两种方式:

  • session
  • cookie

属于同一次会话的请求都有一个相同的标识符,seessionID

session 常用的方法:

String getId() 获取 sessionID
void setMaxInactiveInterval() 设置失效时间,单位是秒
int getMaxInactiveInterval() 获取最大失效时间,单位是秒
void invalidate() 设置 session 立即失效
void setAttribute(String str,Object value) 通过键值对的形式来存储数据
Object getAttribute(String key) 获取键值的对应数据
void removeAttribute(String key) 删除对应键值对应数据

session实际登录注销例子

在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>login</servlet-name>
            <servlet-class>com.example.user.Login</servlet-class>
            <init-param>
                <param-name>username</param-name>
                <param-value>admin</param-value>
            </init-param>
            <init-param>
                <param-name>password</param-name>
                <param-value>123456</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>login</servlet-name>
            <url-pattern>/login</url-pattern>
        </servlet-mapping>
</web-app>

登录逻辑


package com.example.user;

import javax.servlet.ServletConfig;
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 Login extends HttpServlet {
    private String _username;
    private String _password;
    @Override
    public void init(ServletConfig config) throws ServletException {
        this._username = config.getInitParameter("username");
        this._password = config.getInitParameter("password");
    }

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

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username.equals(_username) && password.equals(_password)){
            HttpSession session = req.getSession();
            session.setAttribute("username",username);
            session.setAttribute("password",password);
            resp.sendRedirect("/welcome.jsp");
        }else{
            resp.sendRedirect("/login.jsp");
        }
    }
}



注销登录逻辑


package com.example.user;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/logout")
public class Logout extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {

    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.invalidate();
        resp.sendRedirect("/login.jsp");
    }

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

    }

}



登录界面


<%--
  Created by IntelliJ IDEA.
  User: EDY
  Date: 2023/3/14
  Time: 9:25
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>
<form action="/login" method="post">
    <label for="username">用户名:
        <input id="username" name="username" type="text" />
    </label>
    <br/>
    <label for="password">密码:
        <input id="password" name="password" type="text" />
    </label> <br/>
    <input type="submit" value="登录">
    <br>
    <input type="reset" value="重置">
</form>
</body>
</html>

欢迎界面


<%--
  Created by IntelliJ IDEA.
  User: EDY
  Date: 2023/3/14
  Time: 9:39
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>欢迎</title>
</head>
<body>
<%
if(session.getAttribute("username") == null){
    response.sendRedirect("/login.jsp");
}
%>
<h2>welcome</h2>
<%=session.getAttribute("username")%>
<br>
<a href="/logout">重新登录</a>
</body>
</html>

Cookie

Cookie是服务端在HTTP响应中附带传给浏览器的一个小文本文件,一旦浏览器保存了某个Cookie,在之后的请求和响应过程中,会将此Cookie来回传递,这样就可以通过Cookie这个载体完成客户端和服务端的数据交互。

Cookie

  • 创建Cookie

Cookie cookie = new Cookie("name","zhangsan");
response.addCookie(cookie);

  • 读取Cookie
	Cookie[] cookies = request.getCookies();
    for(Cookie cookie1:cookies){
          out.write(
                  cookie1.getName() +":"+ cookie1.getValue() + "					<br/>"
          );
    }

  • Cookie 常用的方法

void setMaxAge() // 设置Cookie有效时长

int getMaxAge() // 获取有效时长

String getName() // 获取Cookie的名称

String getValue() // 获取Cookie的值

Session和Cookie的区别

session:
保存在服务器
保存的数据是Object
会随着会话的结束而销毁
保存重要信息
cookie:
保存在浏览器
保存的数据是String
可以长期保存在浏览器中,与会话无关
保存不重要信息

存储用户信息:

session:

setAttribute("name","admin") 
getAttribute("name") 

生命周期:
服务端:只要WEB应用重启就销毁
客户端:只要浏览器关闭就销毁
退出登录:
session.invalidate()
cookie:

response.addCookie(new Cookie(name,"admin")) 

Cookie [] cookies = request.getCookies();
for(Cookie cookie:cookies){

	if(cookie.getName().equals("name")){
    	
        out.write("欢迎回来"+cookie.getValue());
    
    }

}

生命周期:
服务端:不随服务端的重启而销毁
客户端:默认是只要关闭浏览器就销毁,我们通过setMaxAge()方法设置有效期,一旦设置了有效期,则不随浏览器的关闭而销毁,而是由设置的时间来决定。

退出登录:setMaxAge(0)

JSP内置对象作用域

4个

page/request/session/application

这四个对象都是
setAttribute/getAttribute 的方法

page作用域:对应的内置对象是pageContext。
request作用域:对应的内置对象是request。
session作用域:对应的内置对象是session。
application作用域:对应的内置对象是application。

作用域的范围从小到在的排列顺序

page < request < session < application

page只在当前页面有效。

request 在一次请求内有效。

session 在一次会话内有效。

application 对应整个WEB应用的。

网站访客统计代码


<%
    Integer count = (Integer) application.getAttribute("count");
    System.out.println(new StringBuffer("count:").append(count));
    if(count == null){
        count = 1;
    } else {
        count++;
    }
    application.setAttribute("count",count);
    System.out.println(new StringBuffer("count:").append(count));
%>
<%=count%>


EL表达式

Expression Language 表达式语言,替代JSP页面中数据访问时的复杂编码,可以非常便捷地取出域对象(pageContext/request/session/application)中保存的数据,前提是一定要先 setAttribute,EL就相当于在简化 getAttribute

${变量名} 变量名就是 setAttribute 对应的key值 。

EL对于4种域对象的默认查找顺序:

pageContext->request->session->application

按照上述的顺序进行查找,找到立即返回,在application中无法找到,则返回null

指定作用域进行查找

pageContext:${pageScope.name}

request:${requestScope.name}

session: ${sessionScope.name}

application:${applicationScope.name}



<%
    User user = new User(1,"张三",30,new Address(1,"科技路"));
    request.setAttribute("user",user);
%>
${user.id} <br>
${user.name} <br>
${user.age} <br>
${user.address.value}



package com.example.user;

public class User {
   private Integer id;
   private String name;
   private Integer age;
   private Address address;


    public User(Integer id, String name, Integer age, Address address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }


    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Address getAddress() {
        return address;
    }

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


package com.example.user;

public class Address {
    private Integer id;
    private String value;

    public Address(Integer id, String value) {
        this.id = id;
        this.value = value;
    }

    public Integer getId() {
        return id;
    }

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

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}


EL执行表达式


&& || ! <> <= >= ==

&& and

|| or

! not

== eq

!= ne

< lt

> gt

<= le

>= ge

empty 变量为 null,长度为0String,size为0的list

JSTL

JSP Standard Tag Library JSP 标准标签库,JSP为开发者提供的一系列的标签,使用这些标签可以完成一些逻辑处理,比如循环遍历集合,让代码更加简洁,不再出现JSP脚本穿插的情况。

实际开发中EL和JSTL结合来使用,JSTL负责数据,EL负责展示数据。

JSTL的使用
  1. 需要导入jar包。(两个jstl.jar和standard.jar)

在pom.xml中加入以下两个依赖

 <dependency>
   <groupId>jstl</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
</dependency>
<dependency>
  <groupId>taglibs</groupId>
  <artifactId>standard</artifactId>
  <version>1.1.2</version>
</dependency>

另一种方法是在官网下载jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jLjCtXhW-1685521480769)(null)]
下载这两个jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-501NikDc-1685521481067)(null)]

将jar包放到webapp下的WEB-INF下的lib目录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0GCgrf6P-1685521480918)(null)]

使用idea引入这两个包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aEV3zlYS-1685521480424)(null)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wH1EXnX5-1685521481034)(null)]

  1. 在JSP页面开始的地方导入JSTL标签库

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

3.JSP代码


<%
    User user = new User(0,"张三",30,new Address(1,"科技路"));
    User user1 = new User(1,"李四",20,new Address(1,"高光路"));
    User user2 = new User(2,"王五",31,new Address(1,"复兴路"));
    ArrayList<User> userList = new ArrayList<User>();
    userList.add(user);
    userList.add(user1);
    userList.add(user2);
    request.setAttribute("user",user);
    request.setAttribute("list",userList);
%>

<table>
    <thead>
        <tr>
            <th>姓名</th>
            <th>年龄</th>
            <th>地址</th>
        </tr>
    </thead>
    <tbody>
    <c:forEach items="${list}" var="user">
        <tr>
            <td>${user.name}</td>
            <td>${user.age}</td>
            <td>${user.address.value}</td>
        </tr>
    </c:forEach>
    </tbody>
</table>

JSTL优点
  1. 提供了统一的标签
  2. 可以用于编写各种动态功能

常用标签:
set、out、remove、catch

set:向域对象中添加数据

<c:set value="tom" var="name" ></c:set>
${name}

使用set标签操作对象

<%
    User user3 = new User(3,"赵六",12,new Address(3,"大望路"));
    request.setAttribute("user3",user3);
%>
<hr/>
${user3.name}
<hr/>
<c:set target="${user3}" property="name" value="赵七"></c:set>
${user3.name}

out: 输入域对象中的数据

<c:out value="${user3.name}" default="没有这个变量"></c:out>
<c:out value="${b}" default="未定义"></c:out>

remove:删除域对象中的数据

<c:set var="b" value="123"></c:set>
<c:remove var="b"></c:remove>
<c:out value="${b}" default="没有找到b"></c:out>

catch:捕获异常

<c:catch var="error">
    <%
        int a = 10/0;
    %>
</c:catch>
<c:out value="${error}"></c:out>

条件标签: if choose


<c:set var="name1" value="tom1" ></c:set>
<c:set var="name2" value="tom2"></c:set>
<c:if test="${name1 == 'tom11'}">tome</c:if>
<c:choose>
    <c:when test="${name1 != name2}">1</c:when>
    <c:otherwise>fail</c:otherwise>
</c:choose>

循环标签:forEach


<c:forEach items="${list}" var="item" varStatus="status">
    <li>${status.index}----${item}</li>
</c:forEach>

格式化常用标签:

<fmt:formatDate value="${date}" pattern="yyyy-MM-dd HH:ss:mm"></fmt:formatDate>

函数标签库常用标签,不在续写,因为大多数情况都是在servlet中去操作数据,前端只用来展示数据即可,不太重要。

一个基于JSEL和EL的增删改查练习


<%@ page import="com.example.jstl_test.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
    <title>JSP - Hello World</title>
</head>
<body>
<h1>首页</h1>
<hr/>
<a href="/test?method=save">增加</a>
<table>
    <thead>
        <tr>
            <th>编号</th>
            <th>姓名</th>
            <th>年龄</th>
        </tr>
    </thead>
    <tbody>
        <c:forEach var="item" varStatus="sta" items="${list}">
            <tr>
                <td>${item.id}</td>
                <td>${item.name}</td>
                <td>${item.age}</td>
                <td>
                    <a href="/test?method=edit&id=${item.id}">编辑</a>
                </td>
                <td>
                    <a href="/test?method=del&id=${item.id}">删除</a>
                </td>
            </tr>
        </c:forEach>
    </tbody>
</table>

</body>
</html>


<%--
  Created by IntelliJ IDEA.
  User: EDY
  Date: 2023/3/20
  Time: 14:02
  To change this template use File | Settings | File Templates.
--%>
<%@ 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="/test" method="post">
    <label for="name">编号</label>
    <input type="text" id="id" name="id" value="${user.id}">
    <br>
    <label for="name">姓名</label>
    <input type="text" id="name" name="name" value="${user.name}">
    <br>
    <label for="age">年龄</label>
    <input type="text" id="age" name="age" value="${user.age}">
    <br>
    <input type="submit" value="提交" />
</form>
</body>
</html>




package com.example.jstl_test;

public class User {
    public int id;
    public int age;
    public String name;

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

    public int getAge() {
        return age;
    }

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

    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;
    }
}



package com.example.jstl_test;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;

@WebServlet(name = "GTest", value = "/test")
public class Test extends HttpServlet {
    public HashMap<Integer,User> list = new HashMap<Integer,User>();

    @Override
    public void init() throws ServletException {
        this.list.put(1,new User(1,12,"张三"));
        this.list.put(2,new User(2,12,"李四"));
        this.list.put(3,new User(3,12,"王五"));
    }


    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) {

        try{
            request.setCharacterEncoding("UTF-8");

            String method = request.getParameter("method");

            if(method == null){
                method = "";
            }

            switch (method){
                case "edit":
                    int id = Integer.parseInt(request.getParameter("id"));
                    User editUser = list.get(id);
                    request.setAttribute("user",editUser);
                    request.getRequestDispatcher("/form.jsp").forward(request,response);
                    break;
                case "save":
                    request.getRequestDispatcher("/form.jsp").forward(request,response);
                    break;
                case "del":
                    list.remove(Integer.parseInt(request.getParameter("id")));
                    response.sendRedirect("/test");
                    break;
                default:
                    request.setAttribute("list",this.list.values());
                    request.getRequestDispatcher("/index.jsp").forward(request,response);

            }



        }catch (javax.servlet.ServletException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        int id = Integer.parseInt(req.getParameter("id"));
        int age = Integer.parseInt(req.getParameter("age"));
        String  name = req.getParameter("name");
        User user = new User(id,age,name);
        list.put(id,user);
        resp.sendRedirect("/test");
    }
}


过滤器

Filter

功能:

  1. 用来拦截传入的请求和付出的响应
  2. 修改或以某种方式处理在客户端和服务端之间交换的数据流。

如何使用?
与使用Servlet类似,Filter是java WEB 提供的一个接口,开发者只需要自定义一个类并且实现该接口即可。



package com.example.filter;

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

public class ChartsetFileter implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("UTF-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }


}


web.xml中配置Filter

<filter>
        <filter-name>chartset</filter-name>
        <filter-class>com.example.filter.ChartsetFileter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>chartset</filter-name>
        <url-pattern>/hello-servlet</url-pattern>
    </filter-mapping>

注意:doFilter方法中处理完业务逻辑之后,必须添加filterChain.doFilter(servleRequest,servleResponse);
否则请求、响应无法向后传递,一直停留在过滤器中。
也可以通过注解的方式来配置过滤器

@WebFilter("/comment")
public class CommentFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("UTF-8");
        String comment = servletRequest.getParameter("comment");
        comment = comment.replaceAll("敏感词","***");
        servletRequest.setAttribute("comment", comment);
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

Filter 的生命周期

当Tomcat启动时,通过反射机制调用Filter的无参构造函数创建实例化对象,同时调用init方法实现初始化。doFilter方法调用多次,当Tomcat服务关闭的时候,调用destory来销毁对象。

无参构造函数:只调用一次,当Tomcat启动时调用,(Filter一定要进行配置)

init 方法,只调用一次,当Filter的实例化对象创建完成之后调用。

doFilter 方法,调用多次,访问Filter的业务逻辑都写在Filter中

destory 只调用一次,Tomcat关闭时调用。

同时配置多个Filter,Filter的调用顺序是由web.xml中的配置顺序来决定的。写在上面的配置先调用,因为web.xml是从上到下顺序读取的。

Fliter使用场景

  1. 设置字符编码
  2. 登录验证

package com.example.util;

import javax.servlet.http.HttpSession;

public class LoginVerify {
    public HttpSession session;
    public LoginVerify(HttpSession session){
        this.session = session;
    }

    public boolean verify(){
        String username =  (String)session.getAttribute("username");
        String password = (String)session.getAttribute("password");
        if(username == null || password == null){
            return false;
        }
        try{
            if(username.equals("admin") && password.equals("123")){
                return  true;
            }else{
                return false;
            }
        }catch (NullPointerException e ){

            e.printStackTrace();
            return false;
        }
    }

}



package com.example.filter;

import com.example.util.LoginVerify;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebFilter("/login.jsp")
public class LoginFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest res = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        HttpSession session = res.getSession();
        LoginVerify loginVerify = new LoginVerify(session);
        if(loginVerify.verify()){
            resp.sendRedirect("/downfile.jsp");
        }
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}


  1. 敏感词处理

package com.example.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/comment")
public class CommentFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("UTF-8");
        String comment = servletRequest.getParameter("comment");
        comment = comment.replaceAll("敏感词","***");
        servletRequest.setAttribute("comment", comment);
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}



<filter>
        <filter-name>commentFilter</filter-name>
        <filter-class>com.example.filter.CommentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>commentFilter</filter-name>
        <url-pattern>/comment</url-pattern>
    </filter-mapping>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值