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的功能
- 创建并返回基于客户请求的动态HTML页面。
- 与数据库进行通信。
如何使用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,映射需要开发者手动配置,有两种配置方式。
- 使用xml方式
- 基于注解的方式
Servlet的生命周期
- 当浏览器访问Servlet的时候,Tomcat会查询当前Servlet的实例化对象是否存在,如果不存在,则通过反射机制创建对象。如果存在,直接执行第3步。
- 调用 init方法完成初始化操作。
- 调用 service方法完成业务逻辑操作。
- 关闭tomcat时,会调用destory方法。
Servlet的生命周期方法:无参构造、init、service、destory。
- 无参构造函数只调用一次,创建对象。
- service调用N次,执行业务方法
- 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种:
- JSP脚本、执行java逻辑代码
<% Java代码 %>
- JSP声明:定义java方法
<%! 声明Java方法 %>
- 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常用方法:
- String getParametes(String key) 获取客户端传来的参数。
- void setAttribute(String key ,Object value) 通过键值对的形式保存数据。
- Object gertAttribute(String key 通过key取出value。
- RequestDispatcher getRequestDispatcher(String path) 返回一个RequestDispatcher对象,该对象的forward方法用于请求转发。
- String[] getParameterValues() 获取客户端传来的多个同名参数。
- void setCharacterEncoding(String charset) 指定每个请求的编码。
HTTP请求状态码
200 正常
403 没有权限
404 资源找不到
400 请求类型不匹配
500 java程序抛出异常
response
- 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,长度为0的String,size为0的list
JSTL
JSP Standard Tag Library JSP 标准标签库,JSP为开发者提供的一系列的标签,使用这些标签可以完成一些逻辑处理,比如循环遍历集合,让代码更加简洁,不再出现JSP脚本穿插的情况。
实际开发中EL和JSTL结合来使用,JSTL负责数据,EL负责展示数据。
JSTL的使用
- 需要导入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)]
- 在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优点
- 提供了统一的标签
- 可以用于编写各种动态功能
常用标签:
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
功能:
- 用来拦截传入的请求和付出的响应
- 修改或以某种方式处理在客户端和服务端之间交换的数据流。
如何使用?
与使用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使用场景
- 设置字符编码
- 登录验证
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() {
}
}
- 敏感词处理
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>