【Tomcat安装以及可能存在的问题】
下载安装
- 官网
https://tomcat.apache.org/
根据个人电脑情况选择tomcat版本下载
下载完成后,解压到自定义目录
- 启动/关闭Tomcat
在apache-tomcat-9.0.65的bin目录下
启动之后,访问测试:http://localhost:8080/
可能遇到问题:
-
Java环境变量没有配置
系统变量中添加 JAVA_HOME C:\Program Files\Java\jdk1.8.0_301 path中添加 %JAVA_HOME%\bin
-
端口被占用
修改路径:apache-tomcat-9.0.65/conf/server.xml中找到以下代码修改port值即可
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
- 闪退问题:需配置兼容性
- 乱码问题:配置文件中设置
【搭建maven环境】
为什么要学习maven
- 在Javaweb中需要大量手动导入jar包,maven可以自动帮我们导入
- maven核心思想:约定大于配置
下载maven
官网:https://maven.apache.org/
下载完后解压即可
配置环境变量
在系统环境变量中进行如下设置
- M2_HOME maven目录下的bin目录
- MAVEN_HOME maven的目录
- 在系统的path中配置%MAVEN_HOME%\bin
配置完环境变量,测试maven是否安装成功
修改镜像,本地仓库##
-
镜像:mirrors
作用:加快我们的下载
在个人安装的apache-maven-3.8.6\conf下的setting.xml中mirrors中插入以下代码
<mirror>
<id>aliyun</id>
<mirrorOf>central</mirrorOf>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
- 本地仓库
在个人安装的apache-maven-3.8.6\conf下的setting.xml中默认存储在${user.home}/.m2/repository
localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
这里可以根据个人情况修改配置,我修改为
<localRepository>D:\Maven\apache-maven-3.8.6\maven-repo</localRepository>
【HelloServlet】
- 狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类
构建一个普通Maven项目
删除里面的src目录,这个空的工程为Maven的主工程,在此工程中可以创建许多子模块工程,依赖尽量放在主工程
创建子模块
- 父子项目
父项目中有:
<modules>
<module>servlet-01</module>
<module>untitled</module>
</modules>
子项目中有:
<parent>
<artifactId>javaweb-02-maven</artifactId>
<groupId>com.canso</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
Maven环境优化
编写Servlet
编写HelloServlet继承HttpServlet 并且重写doPost和doGet
package com.canso.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.doGet(req, resp);
PrintWriter writer = resp.getWriter();
writer.println("hello");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
编写Servlet映射
- 为什么需要映射:我们编写的Java程序若需要通过浏览器访问,需要在浏览器中注册我们写的Servlet,还需给他一个浏览器能够访问的路径
<!-- 注册servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.canso.servlet.HelloServlet</servlet-class>
</servlet>
<!-- servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
配置Tomcat
启动测试
至此,我们可以通过 http://localhost:8080/s1/hello 访问我们的HelloServlet程序
【Servlet原理】
- Servlet是由Web服务器调用,Web服务器在收到浏览器请求之后,会:
Servlet-mapping配置文件
1.指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
2.指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
3.指定通用映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
4.默认请求路径(少用)
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
5.指定一些后缀或前缀等等(*之前不能+/)
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.canso</url-pattern>
</servlet-mapping>
6.优先级问题
指定的固有映射优先于默认的
【Response验证码与重定向】
Respond验证码
package com.canso.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器3秒自动刷新一次
resp.setHeader("refresh","3");
//内存中创建图片
BufferedImage image = new BufferedImage(300,200,BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D g = (Graphics2D) image.getGraphics();//笔
//设置背景颜色
g.setColor(Color.white);
g.fillRect(0,0,300,200);
//图片写数据
g.setColor(Color.BLUE);
g.setFont(new Font(null,Font.BOLD,60));
g.drawString(makeNum(),0,100);
//告诉浏览器,请用图片的方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片给浏览器
ImageIO.write(image, "jpg", resp.getOutputStream());
}
//生成随机数
private String makeNum(){
Random random = new Random();
String s = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-s.length(); i++) {
sb.append("0");
}
s = sb.toString() + s;
return s;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>com.canso.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/image</url-pattern>
</servlet-mapping>
Respond重定向
- B收到A请求后,B通知A去访问C
对比记忆
转发
package com.canso.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/r1/image");//重定向
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
注意:重定向的路径需要将当前路径加入,如:resp.sendRedirect(“/r1/image”);
web.xml
<servlet>
<servlet-name>RedirectServlet</servlet-name>
<servlet-class>com.canso.servlet.RedirectServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/red</url-pattern>
</servlet-mapping>
【Cookie Session】
会话
用户打开一个浏览器,点击许多链接,访问多个web资源,关闭浏览器,这个过程可以称为会话
HttpServletRequest 对象和 ServletContext 对象都可以对数据进行保存,但是这两个对象都不可行,具体原因如下。
(1)客户端请求 Web 服务器时,针对每次 HTTP 请求, Web 服务器都会创建一个HttpServletRequest 对象,该对象只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求中的数据将会丢失。
(2)使用 ServletContext 对象保存数据时,由于同一个 Web 应用共享的是同一个 ServletContext 对象,因此,当用户在发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中所有用户购买的商品进行结算,这显然也是不可行的。
为了保存会话过程中产生的数据,在 Servlet 技术中,提供了两个用于保存会话数据的对象,分别是 Cookie 和 Session
cookie 和 session 的区别
- Cookie是把用户的数据写到用户的浏览器,浏览器保持(可以保持多个)
- Session是把用户的数据写到用户独有的Session中,服务器保持,服务器给每个用户一个SessionID
- Session对象由服务器创建
//解决中文乱码
req.setCharacterEncoding("utf-8");
resp.setHeader("Content-type", "text/html;charset=UTF-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
cookie
客户端技术(请求,响应)
Cookie[] cookies = req.getCookies();//获得cookie
cookie.getName();//获得cookie的key
cookie.getValue();//获得cookie的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+"");//新建一个cookie
cookie.setMaxAge(24*60*60);//设置cookie的有效期
resp.addCookie(cookie);//响应给客户端一个cookie
package com.canso.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import static java.lang.System.out;
//保存用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器告诉你来的时间,将时间封装为一个信件,下次来时带来
//解决中文乱码
req.setCharacterEncoding("utf-8");
resp.setHeader("Content-type", "text/html;charset=UTF-8");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
//服务端从客户端获取
Cookie[] cookies = req.getCookies();
//判断Cookie是否存在
if (cookies!=null){
//如果存在
//out.write(Integer.parseInt("上一次访问时间:"));
writer.write("上一次访问:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//获取名字
if (cookie.getName().equals("lastLoginTime")){
//获取cookie的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
//out.write(Integer.parseInt(date.toLocaleString()));
writer.write(date.toLocaleString());
}
}
}else {
writer.write("第一次访问");
//out.write(Integer.parseInt("第一次访问"));
}
//服务器给客户端响应一个cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
resp.addCookie(cookie);
}
// protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// req.setCharacterEncoding("utf-8");
// resp.setHeader("Content-type", "text/html;charset=UTF-8");
// resp.setCharacterEncoding("utf-8");
// PrintWriter writer = resp.getWriter();
// Cookie[] cookies = req.getCookies();
// if(cookies != null){
// writer.write("上一次访问的时间:");
// for (Cookie cookie : cookies) {
// if(cookie.getName().equals("bill")){
// SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// String format = simpleDateFormat.format(new Date(Long.parseLong(cookie.getValue())));
// writer.write(format);
// }
// }
// }else {
// writer.write("这是您第一次访问");
// }
//
// Cookie cookie = new Cookie("bill", System.currentTimeMillis() + "");
// resp.addCookie(cookie);
// //设置过期时间为一天
// cookie.setMaxAge(24*60*60);
//
// }
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
session
服务器技术,信息与数据可以放在session中
session设置内容
//得到session
HttpSession session = req.getSession();
//为session设置内容
session.setAttribute("name","canso");
session.setAttribute("name1",new Person("cs",7));
Session获取内容
//得到session
HttpSession session = req.getSession();
//获取内容
String name = (String) session.getAttribute("name");
System.out.println(name);
Person person = (Person) session.getAttribute("name1");
System.out.println(person);
System.out.println(person.toString());
手动注销
HttpSession session = req.getSession();
//收到注销“name”Session
session.removeAttribute("name");
//手动注销所有Session
session.invalidate();
自动注销(注意:在web.xml中配置)
<!--设置Session默认失效时间-->
<session-config>
<!--Session 自动失效,以分钟为单位-->
<session-timeout>1</session-timeout>
</session-config>
【JSP】
原理
java Servlet Pages:Java服务器端页面,也和Servlet一样,用于动态Web技术
HTML只给用户提供静态的数据
JSP页面中嵌套JAVA代码,为用户提供动态数据
- JSP 的运行过程具体如下。
(1)客户端发出请求,请求访问 JSP 文件。
(2) JSP 容器先将 JSP 文件转换成一个 Java 源文件( Java Servlet 源程序),在转换过程中,如果发现 JSP 文件中存在任何语法错误,则中断转换过程,并向服务端和客户端返回出错信息。
(3)如果转换成功,则 JSP 容器将生成的 Java 源文件编译成相应的字节码文件***. class** 。该 class 文件就是一个 Servlet , Servlet 容器会像处理其他 Servlet 一样来处理它。
(4)由 Servlet 容器加载转换后的 Servlet 类(. class 文件)创建一个该 Servlet ( JSP 页面的转换结果)实例,并执行 Servlet 的 jsplnit ()方法。 jsplnit ()方法在 Servlet 的整个生命周期中只会执行一次。
(5)执行jspService()方法来处理客户端的请求。对于每一个请求, JSP 容器都会创创建一个新的线程来处理它。如果多个客户端同时请求该 JSP 文件,则 JSP 容器也会创建多个线程,使得每一个客户端请求都对应一个线程。 JSP 运行过程中采用的这种多线程的执行方式可以极大地降低对系统资源的需求,提高系统的并发量并缩短响应时间。需要注意的是,由于第(4)步生成的 Servlet 是常驻内存的,所以响应速度非常快。
(6)如果 JSP 文件被修改了,则服务器将根据设置决定是否对该文件重新编译。如果需要重新编译,则使用重新编译后的结果取代内存中常驻的 Servlet ,并继续上述处理过程。
(7)虽然 JSP 效率很高,但在第1次调用的时候往往由于需要转换和编译,所以会产生一些轻微的延迟。此外,由于系统资源不足等原因, JSP 容器可能会以某种不确定的方式将 Servlet 从内存中移除,发生这种情况时首先会调用jspDestroy()方法,然后 Servlet 实例会被加入“垃圾收集”处理。
(8)当请求处理完成后,响应对象由 JSP 容器接收,并将 HTML 格式的响应信息发送回客户端。
了解了 JSP 的运行原理后,完全可以利用其中的一些步骤来做一些工作,如:可以在 jsplnit ()中进行一些初始化工作(建立数据库的连接、建立网络连接、从配置文件中获取一些参数等),可以在 jspDestroy ()中释放相应的资源等。
JSP基本语法
JSP脚本元素是指嵌套在<%和%>之间的一条或多条代码
JSP脚本元素主要分为:
- JSP Scriptlets(脚本段)
- JSP 声明语句
- JSP 表达式
JSP Scriptlets(脚本段)
<%--脚本片段
<% 变量或者表达式 %>
--%>
<%
int sum = 0;
for (int i = 0; i < 5; i++) {
out.println(i);
}
%>
JSP 声明语句
<%--声明片段
<%! 定义的变量或方法 %>
--%>
<%!
int a = 10;
public int age(int x){
return x;
}
%>
JSP 表达式
<%--JSP表达式
作用:将程序的输出,输出到客户端
<%= 变量或者表达式 %>
--%>
<%= new java.util.Date() %>
注意
JSP脚本 <% %>可进行属性定义,输出内容,不能进行方法定义
JSP声明 <%! %>不能输出内容,定义的属性相当于类的属性,定义的方法为全局方法
JSP注释
<!--这个是HTML注释-->
<%--这个是JSP注释--%>
Tomcat编译文件之后,会将HTML注释当做文本发给客户端,而JSP注释则不会
JSP指令
page指令
<%@ page 属性名1=“属性值1” 属性名2=“属性值2” ··· %>
<%@ page errorPage="error/500.jsp" %>
<%
int x = 1/0;
%>
500.jsp
<img src="500.jpg">
web.xml中的error-page指令
<web-app>
<display-name>Archetype Created Web Application</display-name>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
</web-app>
include指令
在实际开发中,有时需要在JSP页面中静态包含一个文件,include指令可以实现。其类似组件
<%@ include file=“被包含的文件地址” %>
date.jsp
<% out.println(new java.util.Date().toLocaleString());%>
include.jsp
<%-- @include 会将页面合为一个--%>
欢迎你,现在时间:
<%@ include file="date.jsp"%>
<%-- jsp标签
jsp:include 拼接页面,本质还是两个
--%>
欢迎你,现在时间:
<jsp:include page="date.jsp"></jsp:include>
JSP隐式对象
out对象
用于向客户端发送信息
JSP页面通过out隐式对象写入JspWriter对象的缓冲区,只有调用了ServletResponse.getWriter()方法,缓冲区中的数据才写入Servlet引擎提高的缓冲区
<%
out.println("first line<br />");
response.getWriter().println("second line<br />");
%>
虽然response.getWriter().println(“second line”);在out.println(“first line”);之后,但输出却在前,说明response.getWriter().println是直接将语句写入Servlet缓冲区,而out.println则是间接写入
pageContext
<%--内置对象--%>
<%
pageContext.setAttribute("name1","canso1");//保存的数据只在一个页面中有效
request.setAttribute("name2","canso2");//保存的数据只在一次请求中有效,请求转发会携带
session.setAttribute("name3","canso3");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","canso4");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%
//从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");
%>
<h1>取出的值:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>//不显示
<h3><%=name5%></h3><%--显示null--%>
注意:若输出${name1}等需要在<%@ page %> 中加入 isELIgnored=“false”
作用域
<%
pageContext.setAttribute("hello","hello",PageContext.SESSION_SCOPE);
//等价于 session.setAttribute("hello","hello");
//当用到findAttribute()方法后,寻找顺序:page->request->session->application
pageContext.findAttribute("hello");
%>
exception对象
//若该页面出错则跳转
<%@ page errorPage="跳转的地址" %>
//定义该页面为错误页面
<%@ page isErrorPage="true" %>
//显示异常信息
<%=exception.getMessage()%>
HelloWorld.jsp
<%@ page errorPage="error/500.jsp" %>
<%
int x = 1/0;
%>
500.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
<title>Title</title>
</head>
<body>
//显示异常信息
<%=exception.getMessage()%>
</body>
</html>
JSP动作元素
<jsp:include page=" URL" flush=“true/false”>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%Thread.sleep(3000);%>
include.jsp<br>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
dynamicInclude.jsp<br>
<jsp:include page="include.jsp" flush="true"></jsp:include>
</body>
</html>
执行dynamicInclude.jsp结果
flush="true"时,客户端先输出dynamicInclude.jsp,3秒之后才输出include.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%Thread.sleep(3000);%>
include.jsp<br>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
dynamicInclude.jsp<br>
<jsp:include page="include.jsp" flush="false"></jsp:include>
</body>
</html>
执行dynamicInclude.jsp结果
flush="false"时,客户端先等待3秒,之后一起输出dynamicInclude.jsp和include.jsp
<jsp:forward page=“URL”>
转发
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:forward page="dynamicInclude.jsp"></jsp:forward>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
dynamicInclude.jsp<br>
</body>
</html>
结果
【El表达式和JSTL】
JavaBeen
JavaBeen可以对数据和功能进行封装,做到“一次编写,到处运行”
JavaBeen是一个可以重复使用的软件组件,本质上是一个Java类
- 它必须具有一个公共的、无参的构造方法,这个方法可以是编译器自动产生的默认构造方法
- 它提供公共的setter方法和getter方法
BeenUtils工具
官网:https://commons.apache.org/proper/commons-beanutils
logging包:https://commons.apache.org/proper/commons-logging/
常用方法
EL表达式
${表达式}
package com.canso.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("username","canso");
req.setAttribute("password","123");
RequestDispatcher dispatcher = req.getRequestDispatcher("/myjsp.jsp");
dispatcher.forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<%--
Created by IntelliJ IDEA.
User: zcs
Date: 2022/7/27
Time: 16:15
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
用户名:<%= request.getAttribute("username")%><br>
密码:<%= request.getAttribute("password")%><br>
使用EL表达式:<br>
用户名:${username}<br>
密码:${password}<br>
</body>
</html>
EL隐式对象
pageContext对象
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false"%>
<html>
<head>
<title>Title</title>
</head>
<body>
请求URL:${pageContext.request.requestURL}<br>
Content-Type响应头:${pageContext.response.contentType}<br>
服务器信息为:${pageContext.servletContext.serverInfo}<br>
Servlet注册名:${pageContext.servletConfig.servletName}
</body>
</html>
Web域相关对象
<%
pageContext.setAttribute("name1","canso1");//保存的数据只在一个页面中有效
request.setAttribute("name2","canso2");//保存的数据只在一次请求中有效,请求转发会携带
session.setAttribute("name3","canso3");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","canso4");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%
${pageScope.name1}<br> //canso1
${requestScope.name2}<br> //canso2
${sessionScope.name3}<br> //canso3
${application.name4}<br> //canso4
%>
param和paramValues对象
${param.num}
${paramValues.nums[0}
Cookie对象
JSTL标签库
官方下载地址:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/
下载 jakarta-taglibs-standard-1.1.2.zip 包并解压,将 jakarta-taglibs-standard-1.1.2/lib/ 下的两个 jar 文件:standard.jar 和 jstl.jar 文件拷贝到 /WEB-INF/lib/ 下。
注意:同时将两个jar包复制到maven的lib目录下
核心标签
<c:out> <c:if>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:out value=" Hello World!"></c:out>
<form action="JSTLtext01.jsp" method="get">
<input type="text"name="username" value="${param.username}">
<input type="submit" value="login">
</form>
<c:if test="${param.username=='admin'}" var="isadmin">
<c:out value="管理员欢迎你~"></c:out>
</c:if>
<c:out value="${isadmin}"></c:out>
</body>
</html>
<c:choose> <c:when> <c:otherwise>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><html>
<head>
<title>Title</title>
</head>
<body>
<c:choose>
<c:when test="${param.score>=90}">
优秀
</c:when>
<c:when test="${param.score>=60}">
及格
</c:when>
<c:otherwise>
不及格
</c:otherwise>
</c:choose>
</body>
</html>
<c:foreach>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int a[]={1,2,3,4};
%>
int 数组中的元素<br/>
<c:forEach var="num" items="<%=a%>">
${num}
<c:out value="${num}"/>
<br/>
</c:forEach>
<hr/>
<%
ArrayList<String> people = new ArrayList<>();
people.add(0,"赵");
people.add(1,"张");
people.add(2,"李");
people.add(3,"王");
request.setAttribute("list",people);
%>
ArrayList集合中的元素<br/>
<c:forEach var="p1" items="${list}">
<c:out value="${p1}"/>
<br/>
</c:forEach>
</body>
</html>
begin=“1” end=“7” step=“2”
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int b[]={0,1,2,3,4,5,6,7,8};
%>
int 数组中的元素(从1开始,到7结束,步长2)<br/>
<c:forEach var="num" items="<%=b%>" begin="1" end="7" step="2">
${num}
<br/>
</c:forEach>
</body>
</html>
<c:forEach varStatus=" " >
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int c[]={0,1,2,3};
%>
int 数组中的元素varStatus<br/>
<table border="1">
<tr>
<td>序号</td>
<td>索引</td>
<td>是否为第一个元素</td>
<td>是否为最后一个元素</td>
<td>元素的值</td>
</tr>
<c:forEach var="num" items="<%=c%>" varStatus="status" >
<tr>
<td>${status.count}</td>
<td>${status.index}</td>
<td>${status.first}</td>
<td>${status.last}</td>
<td>${num}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
格式化标签
SQL标签
XML 标签
JSTL函数
https://www.runoob.com/jsp/jsp-jstl.html
【过滤器Filter 监听器Listener】
过滤器Filter
pom.xml中导包
<!-- Servlet依赖 -->
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- JSP依赖 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- JSTL表达式的依赖 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
创建ShowServlet extends HttpServlet,内容 resp.getWriter().write(“你好”); 输出你好,运行结果为乱码
代码结果如下:
package com.canso.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("你好");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>com.canso.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
我们可以在doGet中添加 resp.setCharacterEncoding(“utf-8”); 来解决乱码问题,但是若有多个程序需要添加,则比较不方便
所以我们可以添加过滤器
创建CharacterEncodingFilter类,实现接口,注意导包javax.servlet,之后重写方法
package com.canso.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动时,便初始化,
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//chain:链
@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执行后");
}
//摧毁:web服务器关闭时,过滤会销毁
@Override
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
在web.xml中配置,为/servlet的任何请求设置过滤器
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.canso.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- 只要是/servlet的任何请求,都会经过这个过滤器 -->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
当我们运行程序时,程序输出以下结果,说明init()初始化在web服务器启动时,便初始化
当我们在浏览器输入http://localhost:8080/filter_listener_war/servlet/show运行后,程序输出以下结果,且我们每一次执行都会输出以下结果
客户端输出以下结果
当我们关闭浏览器后,程序输出以下结果
监听器Listener
package com.canso.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MyListener implements ServletContextListener, HttpSessionListener, ServletRequestListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象被创建");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext对象被销毁");
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("ServletRequest对象被销毁");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("ServletRequest对象被创建");
}
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("HttpSession对象被创建");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("HttpSession对象被销毁");
}
}
<!--监听器-->
<listener>
<listener-class>com.canso.listener.MyListener</listener-class>
</listener>
<!-- 设置session超时时间为1分钟 -->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
运行程序,console出现
一分钟之后出现
结束项目,console出现
说明web服务器启动时,ServletContext对象便创建了,而监听器一直在监听,所以web服务器创建完对象后便调用监听器