文章目录
JavaWeb
JavaWeb基本概念
Java Web,是用Java技术来解决相关web互联网领域的技术栈。web包括:web服务端和web客户端两部分。Java在客户端的应用有Java Applet,不过使用得很少,Java在服务器端的应用非常的丰富,比如Servlet,JSP、第三方框架等等。
静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变 。静态web资源开发技术:HTML、CSS
动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。。动态web资源开发技术:JavaScript、JSP/Servlet、ASP、PHP等。在Java中,动态web资源开发技术统称为Java Web
Web概述
XML基础
XML语法:
<?xml 版本信息 [编码信息] [文档独立性信息] ?>
<?xml version="1.0" encoding="UTF-8"?>
XML注释:
<!--注释信息-->
DTD约束
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
内部的 DOCTYPE 声明
假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
<!DOCTYPE 根元素 [元素声明]>
Schema约束
schema概述
schema约束同为xml文件的约束模式语言之一, 最大的作用是为了验证xml文件的规范性的.
HTTP
HTTP简介
-
HTTP:超文本传输协议 (Hypertext Transfer Protocol)
-
默认端口号:80
-
HTTPS 默认端口号 443 (S代表Safe 安全的)
-
HTTP1.0
- HTTP1.0 协议的客户端与服务器在交互过程中需要经过建立连接,发送请求消息,回送响应消息,关闭连接四个步骤。客户端与服务器建立连接后,每次只能处理一个HTTP请求
-
HTTP1.1
- 客户端与服务器建立连接后,可以传送多个HTTP请求和响应
HTTP请求
- 客户端------>发送请求------->服务器
General:
Request URL: http://localhost:2019/servlet_war/Servlet01 //请求地址
Request Method: GET //请求方法,get/post方法
Status Code: 200 //状态码
Remote Address: [::1]:2019 //远程地址
Request Header:
Accept:text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7,zh-TW;q=0.6,zh;q=0.5
Cache-Control: max-age=0
Connection: keep-alive
Cookie: JSESSIONID=83A28ABEF514F89A9A746C55FACCC21C; Idea-6b53f3ef=66018b3b-efdd-4d19-8e0b-c206dfe4b3e0
Host: localhost:2019
......
-
HTTP请求行
- 请求行中的请求方式:Get
- 请求方式:Get、Post、(最为常用) HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS
-
HTTP请求消息头
Accept //指出客户端程序(浏览器)能够支持的类型 Accept-Encoding //支持哪种编码格式 GBK、UTF-8、GB2312、ISO8859-1 Accept-Language //支持的语言环境 Cache-Control: //缓存控制 Connection //连接 Cookie //Cookie Host //主机 ......
HTTP响应
- 服务器----->响应----->客户端
Response Header:
Cache-Control: private //缓存控制
Connection: keep-alive //连接
Content-Encoding: gzip //文本编码
Content-Type: text/html;charset=utf-8 //文本类型
......
-
HTTP响应状态码
- 1xx:表示请求已接收,需要继续处理
- 2xx(200):表示请求已经成功被服务器接收、理解并接受
- 3xx(302,304):为完成请求,客户端需进一步细化请求
- 4xx(404):客户端的请求有错误
- 5xx(500):服务端出现错误
-
HTTP响应消息头
Accept //指出客户端程序(浏览器)能够支持的类型
Accept-Encoding //支持哪种编码格式 GBK、UTF-8、GB2312、ISO8859-1
Accept-Language //支持的语言环境
Cache-Control: //缓存控制
Connection //连接
Cookie //Cookie
Host //主机
Refresh //告诉客户端多久刷新一次
location //让网页重新定向
......
Tomcat
目录图:
Servlet
servlet体系结构图:
Servlet接口中的抽象方法
// 容器在创建好Servlet对象后,就会调用此方法。该方法接收一个ServletConfig类型的参数,Servlet容器通过这个参数向Servlet传递初始值
void init(ServletConfig var1);
//用于获取Servlet对象的配置信息,返回Servlet的ServletConfig对象
ServletConfig getServletConfig();
//负责响应用户的请求,当容器(指web服务器)接收到客户端访问Servlet对象的请求时,就会调用此方法。(提供服务的方法,每一次Servlet被访问时执行,会执行多次。)
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
//返回一个字符串,其中包含关于Servlet的信息,如:作者,版权和版本等信息
String getServletInfo();
//负责释放Servlet对象占用的资源。当服务器关闭或者Servlet对象被移除时,Servlet对象会被摧毁,容器调用此方法
void destroy();
HttpServlet类常用的方法:
//用于处理GET类型的HTTP请求方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
//用于处理POST类型的HTTP请求方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
Servlet虚拟路径的映射
- Servlet的多重映射
- 配置多个元素
<servlet>
<servlet-name>Servlet</servlet-name>
<servlet-class>com.sgl.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/Servlet01</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/Servlet001</url-pattern>
</servlet-mapping>
2. 在一个元素下配置多个 子元素
<servlet>
<servlet-name>Servlet</servlet-name>
<servlet-class>com.sgl.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/Servlet01</url-pattern>
<url-pattern>/Servlet001</url-pattern>
</servlet-mapping>
-
Servlet映射路径中使用的通配符
- “ *.拓展名 ”
- “ /* ”
-
缺省Servlet
- web.xml文件中
<servlet-mapping><url-patten>/</url-patten></servlet-mapping>
即url的值为/的servlet为此项目的缺省servlet,映射路径仅仅十余个正斜线(/)
ServletConfig接口
当Tomcat初始化一个Servlet时,会将Servlet的配置信息封装到一个ServletConfig对象中,通过调用init(ServletConfig var1)方法将ServletConfig对象传递给Servlet,ServletConfig定义了一系列获取配置信息的方法
ServletConfig接口的常用方法
String getInitParameter(String name) //根据初始化参数名返回对应的初始化参数值
Enumeration getInitParameterNames() //返回一个Enumeration对象,其中包含了所有的初始化参数名
ServletContext getServletContext() //返回一个代表当前Web应用的ServletContext对象
String getServletName() //返回Servlet的名字,即web.xml中<servlet-name>元素的值
web.xml配置
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.sgl.servlet.TestServlet01</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/Servlet02</url-pattern>
</servlet-mapping>
package com.sgl.servlet;
import javax.servlet.ServletConfig;
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 TestServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
//获得ServletConfig对象
ServletConfig config = this.getServletConfig();
//获得参数名为encoding对应的参数值
String param = config.getInitParameter("encoding");
writer.println("encoding="+param);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
启动Tomcat服务器结果
ServletContext接口
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletConfig对象,它代表了当前的web应用
共享数据
在这个Servlet中保存的数据可以在另一个Servlet中拿到
web.xml配置
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.sgl.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>GetHelloServlet</servlet-name>
<servlet-class>com.sgl.servlet.GetHelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetHelloServlet</servlet-name>
<url-pattern>/GetHelloServlet</url-pattern>
</servlet-mapping>
package com.sgl.servlet;
import javax.servlet.ServletContext;
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 HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter(); 初始化参数
//this.getServletConfig(); Servlet配置
//this.getServletContext(); Servlet上下文
ServletContext servletContext = this.getServletContext();
String username = "刚龙";
servletContext.setAttribute("username",username); //将一个数据保存在ServletContext中,名字为:username 值为:username
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.sgl.servlet;
import javax.servlet.ServletContext;
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 GetHelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String username = (String) servletContext.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.println("名字:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
获得初始化参数
web.xml配置
<!--配置一些web应用的初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
package com.sgl.servlet;
import javax.servlet.ServletContext;
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 TestServlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().println("url:"+url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
请求转发
- 请求转发
- 请求转发: xxServlet收到请求,然后直接转发给yyServlet,然后yyServlet返回给客户端。整个过程中,客户端发出一个请求,收到一个响应。
- 请求转发:利用RequestDispather接口中的forward方法实现请求转发。
- 重定向
- 重定向:xxServlet收到请求,然后发出一个响应给客户端,客户端立即又发送一个请求访问xxServlet中给的URL,即yyServlet的路径,然后yyServlet给客户端一个响应。整个过程中,客户端发出两个请求,收到两个响应。
- 请求重定向:利用HttpServletResponse的sendRedirect方法实现请求重定向。
ABC代替,大概就是这样:
package com.sgl.servlet;
import javax.servlet.ServletContext;
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 TestServlet02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/TestServlet01");
//requestDispatcher.forward(req,resp); //调用forward实现请求转发
servletContext.getRequestDispatcher("/TestServlet01").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
读取资源文件
Properties
- 在Java目录下新建properties
- 在resources目录下新建properties
都被打包在同一个路径下:classes,这个路径俗称为classpath
思路:需要一个文件流
db.properties(resources目录下)
username=root
password=123456
aa.properties (Java目录下),需要解决资源导出问题
username=root
password=456789
解决资源导出问题 : 在pom.xml(该模块下的)文件加入以下:
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
package com.sgl.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.InputStream;
import java.util.Properties;
public class TestProperties extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/sgl/servlet/aa.properties");
Properties properties = new Properties();
properties.load(is);
String user = properties.getProperty("username");
String pwd = properties.getProperty("password");
resp.getWriter().println("user:"+user);
resp.getWriter().println("pwd:"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
HttpServletResponse
web服务器接收到客户端的http请求。针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的HttpServletResponse
- 如果获取客户端请求过来的参数 找:HttpServletRequest
- 如果要给客户端响应一些信息 找:HttpServletResponse
HttpServletResponse对象提供解决乱码问题
第一种方式
//设置HttpServletResponse使用utf-8编码
resp.setCharacterEncoding("utf-8");
//通知浏览器使用utf-8
resp.setHeader("Context-Type","text/html;charset=utf-8");
第二种方式
//包含第一种方式的两种功能
resp.setContentType("text/html;charset=utf-8");
分类
以下方法都是HttpServletResponse类(HttpServletResponse继承ServletResponset)和ServletResponset类中的方法
- 负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
- 负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setBufferSize(int var1);
void sendError(int var1, String var2) throws IOException;
void sendError(int var1) throws IOException;
void sendRedirect(String var1) throws IOException;
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
void setStatus(int var1);
- 响应的状态码
int SC_OK = 200;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_NOT_MODIFIED = 304;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_BAD_GATEWAY = 502;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
下载文件
- 获取要下载的文件的绝对路径
- 获取要下载的文件名
- 设置content-disposition响应头控制浏览器以下载的形式打开文件
- 获取要下载的文件输入流
- 创建数据缓冲区
- 通过response对象获取OutputStream流
- 将FileInputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区的数据输出到客户端浏览器
package com.sgl.demo01;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取要下载的文件的绝对路径
//String realPath = "E:\\Idea\\Javaweb-02-Servlet02\\HttpServletResponse\\src\\main\\resources\\1.jpeg";
String realPath = "E:\\Idea\\Javaweb-02-Servlet02\\HttpServletResponse\\src\\main\\resources\\刚龙.jpeg";
System.out.println("下载文件的路径:"+realPath);
// 2. 获取要下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3. 设置Content-Disposition响应头控制浏览器以下载的形式打开文件
//resp.setHeader("Content-Disposition", "attachment;filename="+fileName);
resp.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
// 4. 获取要下载的文件输入流
FileInputStream in = new FileInputStream(realPath);
// 5. 创建数据缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6. 通过response对象获取OutputStream流
ServletOutputStream out = resp.getOutputStream();
// 7. 将FileInputStream流写入到buffer缓冲区
while ((len=in.read(buffer))!=-1){
// 8. 使用OutputStream将缓冲区的数据输出到客户端浏览器
out.write(buffer,0,len);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
验证码功能
package com.sgl.demo01;
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(80, 20, BufferedImage.TYPE_INT_BGR);
//得到图片
Graphics g = image.getGraphics(); //🖊笔
//设置图片的背景颜色
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//给图片写数据
g.setColor(Color.BLUE);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告诉浏览器,这个请求用图片打开
resp.setContentType("image/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 num = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-num.length(); i++) {
sb.append("0");
}
num = sb.toString() + num;
return num;
}
}
实现重定向
-
重定向:xxServlet收到请求,然后发出一个响应给客户端,客户端立即又发送一个请求访问xxServlet中给的URL,即yyServlet的路径,然后yyServlet给客户端一个响应。整个过程中,客户端发出两个请求,收到两个响应。
-
请求重定向:利用HttpServletResponse的sendRedirect方法实现请求重定向。
void sendRedirect(String var1) throws IOException;
测试:
package com.sgl.demo01;
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.setHeader("Location","/HttpServletResponse_war/ImageServlet");
resp.setStatus(302); //resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);等价于302
*/
resp.sendRedirect("/HttpServletResponse_war/ImageServlet"); //重定向
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
请求转发和重定向的区别:
- 相同点:页面都会跳转
- 不同点:
- 请求转发的时候,url地址栏不会发生变化
- 重定向的时候,url地址栏会发生变化
Response重定向
index.jsp (启动Tomcat时,显示的页面)
通过form表单 action=“${pageContext.request.contextPath}/RequestTest” ,然后输入,可以进入到RequetTest,然后右通过重定向进入到success.jsp
<html>
<body>
<h2>Hello World!</h2>
<%--这里提交的路径,需要寻找到项目的路径--%>
<%--${pageContext.request.contextPath}代表当前的项目--%>
<form action="${pageContext.request.contextPath}/RequestTest" method="get">
用户名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"> <br>
<input type="submit">
</form>
</body>
</html>
创建的RequestTest类
package com.sgl.demo01;
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 RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入这个请求");
//处理请求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+" "+password);
//重定向一定要注意路径问题 否则404
resp.sendRedirect("/HttpServletResponse_war/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
success.jsp
<%--
Created by IntelliJ IDEA.
User: shiga
Date: 2021/9/2
Time: 21:06
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>
<h1>Success</h1>
</body>
</html>
HttpServletRequest
获取参数和请求转发
index.jsp
<html>
<body>
<h2>登录</h2>
<div>
<%--这里的表单表示的意思:以post方式提交表单,提交到我们的LoginServlet请求--%>
<form action="${pageContext.request.contextPath}/LoginServlet" method="post">
用户名:<input type="text" name="username" required><br>
密码:<input type="password" name="password"><br>
爱好:
<input type="checkbox" name="hobbies" value="女孩">女孩
<input type="checkbox" name="hobbies" value="代码">代码
<input type="checkbox" name="hobbies" value="唱歌">唱歌
<input type="checkbox" name="hobbies" value="电影">电影
<br>
<input type="submit">
</form>
</div>
</body>
</html>
创建的LoginServlet类
package com.sgl.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.util.Arrays;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobbies");
System.out.println("=================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
System.out.println("=================");
//通过请求转发
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
success.jsp
<%--
Created by IntelliJ IDEA.
User: shiga
Date: 2021/9/2
Time: 21:40
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>
<h1>success</h1>
</body>
</html>
Cookie
cookie:
- 客户端技术 (响应,请求)
常见现象:网站登录之后,下次无需登录,第二次直接登录上去
测试:
package com.sgl.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.util.Date;
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setHeader("Context-Type","text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//Cookie 服务端从客户端获取
Cookie[] cookies = req.getCookies(); //返回类型为一个数据,说明cookie可以存在多个
//判断cookie是否存在
if (cookies!=null){
//如果存在怎么办
out.write("您上一个访问时间为:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if (cookie.getName().equals("LastLoginTime")){
//获取cookie的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}
//服务端响应一个cookie
Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
//cookie有效期为1天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
用到的方法
Cookie[] cookies = req.getCookies(); //获取cookie
cookie.getName() //获取cookie中的key
cookie.getValue() //获取cookie中的value
Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
Cookie:一般会保存本地的 用户目录下 appdata
一个网站cookie是存在上线!
- 一个Cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
- Cookie大小限制4kb
- 300个cookie是浏览器上线
删除cookie
- 不设置有效期,关闭浏览器自动失效
- 设置有效期时间为0
测试删除CookieDemo01类的cookie访问信息,启动Tomcat后,访问CookieDemo01上次访问时间被保存,然后访问CookieDemo02,再访问CookieDemo01,cookie上次访问时间删除
package com.sgl.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;
public class CookieDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建一个cookie,名字必须和删除的名字一致
Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
//将cookie有效期设置为0
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
中文数据传递
package com.sgl.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.net.URLDecoder;
import java.net.URLEncoder;
public class CookieDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setHeader("Context-Type","text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
//Cookie 服务端从客户端获取
Cookie[] cookies = req.getCookies(); //返回类型为一个数据,说明cookie可以存在多个
//判断cookie是否存在
if (cookies!=null){
//如果存在怎么办
out.write("上一次访问的用户:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if (cookie.getName().equals("name")){
//输出cookie的值
out.write(URLDecoder.decode(cookie.getValue(),"utf-8")); //解码
}
}
}
//编码
Cookie cookie = new Cookie("name", URLEncoder.encode("刚龙","utf-8"));
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
用到编码和解码
URLEncoder.encode("刚龙","utf-8") //编码
URLDecoder.decode(cookie.getValue(),"utf-8") //解码
Session ***
session:
-
服务端技术,保存会话信息,把信息或者数据存放在session中
-
服务器会给每一个用户(浏览器)创建一个session对象
-
一个Session独占一个浏览器,只要浏览器没有关闭,Session就存在
-
用户登陆后,整个网站它都可以访问 ---->保存用户的信息;保存购物车的信息等等
HttpSession中的方法:
//得到一个Session
HttpSession session = req.getSession();
long getCreationTime();
String getId();
long getLastAccessedTime();
ServletContext getServletContext();
void setMaxInactiveInterval(int var1);
int getMaxInactiveInterval();
/** @deprecated */
@Deprecated
HttpSessionContext getSessionContext();
Object getAttribute(String var1);
/** @deprecated */
@Deprecated
Object getValue(String var1);
Enumeration<String> getAttributeNames();
/** @deprecated */
@Deprecated
String[] getValueNames();
void setAttribute(String var1, Object var2);
/** @deprecated */
@Deprecated
void putValue(String var1, Object var2);
void removeAttribute(String var1);
/** @deprecated */
@Deprecated
void removeValue(String var1);
void invalidate();
boolean isNew();
测试:
获取Session并给Session存东西
package com.sgl.servlet;
import com.sgl.pojo.Person;
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 SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setHeader("text/html","charset=utf-8");
//得到一个Session
HttpSession session = req.getSession();
//给session存东西
//session.setAttribute("name","刚龙");
session.setAttribute("name",new Person("刚龙",18));
//获取session的ID
String sessionId = session.getId();
//判断session是不是新创建
if (session.isNew()){
resp.getWriter().write("session创建成功,ID"+sessionId);
}else {
resp.getWriter().write("session已经再服务器中存在了,ID:"+sessionId);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
得到Session的保存的值
package com.sgl.servlet;
import com.sgl.pojo.Person;
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 SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setHeader("text/html","charset=utf-8");
//得到Session
HttpSession session = req.getSession();
//String name = (String) session.getAttribute("name");
Person person = (Person) session.getAttribute("name");
//resp.getWriter().write(name);
resp.getWriter().write(person.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
会话过期的两种方式:
- 手动注销Session
package com.sgl.servlet;
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 SessionDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销session
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 会话自动过期,在web.xml中配置
<!--设置Session默认的失效时间-->
<session-config>
<!--1分钟后session自动失效,以分钟为单位-->
<session-timeout>1</session-timeout>
</session-config>
Session和Cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session是把用户的数据写到用户独占的Session中,服务端保存(保存重要的信息,减少服务器资源的浪费)
- Session对象由服务器创建
JSP
JSP(全称JavaServer Pages)JSP将Java代码和特定变动内容嵌入到静态的页面中,实现以静态页面为模板,动态生成其中的部分内容。
JSP原理
**浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet ** JSP本质就是一个Servlet
JSP最终会被转换成一个Java类
找不到的话,打开IDEA点击 Help 下的 Show Log in Explorer 会在文件夹中显示
index_jsp.java : 源代码
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/9.0.52
* Generated at: 2021-09-03 08:44:35 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
final java.lang.String _jspx_method = request.getMethod();
if ("OPTIONS".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
return;
}
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
return;
}
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("<html>\n");
out.write("<body>\n");
out.write("<h2>Hello World!</h2>\n");
out.write("</body>\n");
out.write("</html>\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
部分讲解:
方法
//初始化
public void _jspInit() {}
//销毁
public void _jspDestroy() {}
//
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
内置对象
final javax.servlet.jsp.PageContext pageContext; //页面上下文
javax.servlet.http.HttpSession session = null; //session
final javax.servlet.ServletContext application; //applicationContext
final javax.servlet.ServletConfig config; //config
javax.servlet.jsp.JspWriter out = null; //out
final java.lang.Object page = this; //page:代表当前页
final javax.servlet.http.HttpServletRequest request //请求
final javax.servlet.http.HttpServletResponse response //响应
输出页面前的增加的代码
response.setContentType("text/html"); //
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
在JSP页面中:
只要是Java代码就会原封不动的输出;
如果是HTML代码,就会被转换为:
out.write("<html>\n");
然后输出
JSP原理图:
JSP基础语法
JSP表达式
<%--JSP表达式
作用:用来将程序输出到客户端
<%= 变量或者表达式%>
--%>
<%= new java.util.Date()%>
JSP脚本片段
<%--JSP脚本片段--%>
<%
int sum = 0;
for (int i = 0; i < 100; i++) {
sum = sum + i;
}
out.println("<h1>Sum="+sum+"</h1>");
%>
脚本片段的再实现
<%
int x = 10;
out.println(x);
%>
<%
int y = 10;
out.println(y);
%>
<hr>
<%--在代码中嵌入HTML代码--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h1>Hello World <%=i%></h1>
<%
}
%>
JSP声明
<%!
static {
System.out.println("Loading Servlet");
}
private int globalVar = 0;
public void test(){
System.out.println("进入了test方法");
}
%>
JSP声明会被编译到JSP生成的Java类中!! 其他的会被生成到 _jspService 方法中
在JSP中嵌入Java代码即可
<%%>
<%=%>
<%!%>
<%--注释--%>
JSP的注释不会在客户端显示,HTML会!
测试定制页面错误,页面跳转到自定义错误的页面
<%--
Created by IntelliJ IDEA.
User: shiga
Date: 2021/9/3
Time: 20:58
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--在web.xml文件配置了,这里就不需要了--%>
<%--定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int x =1/0;
%>
</body>
</html>
自定义的404和500页面:
<%--
Created by IntelliJ IDEA.
User: shiga
Date: 2021/9/3
Time: 21:20
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>
<img src="image/404.jpg" alt="">
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: shiga
Date: 2021/9/3
Time: 20:59
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>
<img src="image/500.jpg" alt="">
</body>
</html>
跳转页面的两种方式:
- 使用JSP指令<% @ args… %>
<%--定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>
- 在web.xml文件中配置
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
JSP指令
<% @ page 属性名1="属性值1" 属性名2="属性值2" ... %>
属性名称 | 取值范围 | 描述 |
---|---|---|
language | Java | 指明解释该JSP时采用的语言,默认为Java |
import | 任何包名,类名 | import属性,写了之后会自动添加到servlet的import语句中,但不进行包存在性的检查 |
session | true,false | Session对象是否参与会话,session="false"就没有session对象了 |
isErrorPage | true,false | isErrorPage=“true false” 设置此页是否为出错页,如果被设置为true,你就能使用exception对象 |
errorPage | 某个JSP页面的相对路径 | 设置处理异常事件的JSP文件。 |
contentType | 有效的文档类型 | contentType属性设置发送到客户端文档的响应报头的类型和字符编码。多个使用;号分开。 pageEncodeing属性只用于更改字符编码 |
PageEnCoding | 当前页面 | 指定页面编码格式 |
例子:
<%--定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>
<%--显示的声明这是一个错误页面--%>
<%@ page isErrorPage="true" %>
<%@ page pageEncoding="utf-8" %>
include指令
网站前面的导航栏和底部栏,跳转页面一直固定不动,用的是i<%@ include file=“”%>或<jsp:include page=“”/>
<%--@ include会将两个页面合二为一--%>
<%@ include file="common/header.jsp"%>
<h2>网页主体</h2>
<%@ include file="common/footer.jsp"%>
<hr>
<%--JSP标签
jsp:include:拼接页面,本质还是三个
--%>
<%--JSP标签--%>
<jsp:include page="common/header.jsp"/>
<h2>网页主体</h2>
<jsp:include page="common/footer.jsp"/>
9大内置对象(JSP隐式对象)
JSP隐式对象:
名称 | 类型 | 描述 |
---|---|---|
out | javax.servlet.jsp.JspWriter | 用于页面输出 |
request | javax.servlet.jsp.HttpServletRequest | 得到用户请求 |
response | javax.servlet.jsp.HttpServletResponse | 服务端向客户端回应信息 |
config | javax.servlet.jsp.ServletConfig | 服务器配置,可以得到初始化参数 |
session | javax.servlet.http.HttpSession | 用来保存用户信息 |
application | javax.servlet.jsp.ServletContext | 所有用户的共享信息 |
page | java.lang.Object | 指当前页面转换后的Servlet实例 |
pageContext | javax.servlet.jsp.PageContext | JSP的页面容器 |
exception | java.lang.Throwable | 表示JSP页面所发生的异常,在错误页面才起作用 |
测试:
pageContextDemo01.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>pageContext</title>
</head>
<body>
<%--内置对象--%>
<%
pageContext.setAttribute("name1","鲁班一号");//保存的数据只在一个页面中有效
request.setAttribute("name2","鲁班二号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","鲁班三号");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","鲁班四号");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%--脚本片段中的代码,会被原封不动的生成到JSP.java
要求:必须保证Java语法的正确性
--%>
<%--
public static final int PAGE_SCOPE = 1;
public static final int REQUEST_SCOPE = 2;
public static final int SESSION_SCOPE = 3;
public static final int APPLICATION_SCOPE = 4;
--%>
<%
//从PageContext取出,通过寻找的方式
//从底层到高层(作用域):page->request->session->application
//JVM:双亲委派机制
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5"); //不存在
pageContext.forward("/PageDemo02.jsp"); //请求转发到PageDemo02.jsp
%>
<%--使用EL表达式输出${}--%>
<h3>取出的值为:</h3>
<h4>${name1}</h4>
<h4>${name2}</h4>
<h4>${name3}</h4>
<h4>${name4}</h4>
<h4>${name5}</h4> <%--什么也不会输出,也不报错--%>
<h4><%=name5%></h4> <%--会输出 null--%>
</body>
</html>
PageDemo02.jsp
从PageDemo02.jsp页面输出,只输出了 “鲁班三号和鲁班四号” (作用域不同)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--脚本片段中的代码,会被原封不动的生成到JSP.java
要求:必须保证Java语法的正确性
--%>
<%
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5"); //不存在
%>
<%--使用EL表达式输出${}--%>
<h3>取出的值为:</h3>
<h4>${name1}</h4>
<h4>${name2}</h4>
<h4>${name3}</h4>
<h4>${name4}</h4>
<h4>${name5}</h4> <%--什么也不会输出,也不报错--%>
<h4><%=name5%></h4> <%--会输出 null--%>
</body>
</html>
PageDemo03.jsp
关于作用域的一些方法和类(源码)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--PageContextImpl--%>
<%--
public void setAttribute(String name, Object attribute, int scope) {
switch(scope) {
case 1:
this.mPage.put(name, attribute);
break;
case 2:
this.mRequest.put(name, attribute);
break;
case 3:
this.mSession.put(name, attribute);
break;
case 4:
this.mApp.put(name, attribute);
break;
default:
throw new IllegalArgumentException("Bad scope " + scope);
}
}
--%>
<%--PageContext--%>
<%--
public abstract class PageContext extends JspContext {
public static final int PAGE_SCOPE = 1;
public static final int REQUEST_SCOPE = 2;
public static final int SESSION_SCOPE = 3;
public static final int APPLICATION_SCOPE = 4;
public static final String PAGE = "javax.servlet.jsp.jspPage";
public static final String PAGECONTEXT = "javax.servlet.jsp.jspPageContext";
public static final String REQUEST = "javax.servlet.jsp.jspRequest";
public static final String RESPONSE = "javax.servlet.jsp.jspResponse";
public static final String CONFIG = "javax.servlet.jsp.jspConfig";
public static final String SESSION = "javax.servlet.jsp.jspSession";
public static final String OUT = "javax.servlet.jsp.jspOut";
public static final String APPLICATION = "javax.servlet.jsp.jspApplication";
public static final String EXCEPTION = "javax.servlet.jsp.jspException";
--%>
<%
pageContext.setAttribute("hello1","hello2",PageContext.SESSION_SCOPE);//等价于session.setAttribute("hello1","hello2");
%>
</body>
</html>
PageContextDemo02.jsp
两者都可以实现请求转发
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
pageContext.forward("/index.jsp");//request.getRequestDispatcher("/index.jsp").forward(request,response);两个都可以实现请求转发
%>
</body>
</html>
JSP标签 JSTL标签 EL表达式
JSTL标签 EL表达式需要导入相应的包
<!--JSTL依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签库依赖-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表达式
${ }
- 获取数据
- 执行运算
- 获取web开发的常用对象
JSP标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<jsp:forward page="jsptag02.jsp">
<jsp:param name="name" value="sgl"/>
<jsp:param name="age" value="22"/>
</jsp:forward>
</body>
</html>
JSTL表达式
核心标签***
格式:
<c:标签>
标签 | 描述 |
---|---|
<c:out> | 用于在JSP中显示数据,就像<%= … > |
<c:set> | 用于保存数据 |
<c:remove> | 用于删除数据 |
<c:catch> | 用来处理产生错误的异常状况,并且将错误信息储存起来 |
<c:if> | 与我们在一般程序中用的if一样 |
<c:choose> | 本身只当做<c:when>和<c:otherwise>的父标签 |
<c:when> | <c:choose>的子标签,用来判断条件是否成立 |
<c:otherwise> | <c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行 |
<c:import> | 检索一个绝对或相对 URL,然后将其内容暴露给页面 |
<c:forEach> | 基础迭代标签,接受多种集合类型 |
<c:forTokens> | 根据指定的分隔符来分隔内容并迭代输出 |
<c:param> | 用来给包含或重定向的页面传递参数 |
<c:redirect> | 重定向至一个新的URL. |
<c:url> | 使用可选的查询参数来创造一个URL |
使用JSTL标签的步骤:
- 引用核心标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- 使用其中的方法
- 在Tomcat也需要引入 jstl-api 和 standard 两个包,否则会报错:JSTL解析错误
c:if c:out
EL表达式获取表单中的数据
${param.username}
<%@ 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="Jstl01.jsp" method="get">
<%--
EL表达式获取表单中的数据
${param.username}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>
<%--判断如果提交的用户是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员欢迎你"/>
</c:if>
<%--自闭和标签--%>
<c:out value="${isAdmin}"/>
</body>
</html>
c:set c:choose c:when
<%@ 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>
<%--定义一个变量score 值为85--%>
<c:set var="score" value="85"/>
<c:choose>
<c:when test="${score>=90}">
<c:out value="你的成绩为优秀"/> <%--用<c:out>输出,直接输出也可--%>
你的成绩为优秀
</c:when>
<c:when test="${score>=80}">
<c:out value="你的成绩为良好"/>
你的成绩为良好
</c:when>
<c:when test="${score>=70}">
<c:out value="你的成绩为中等"/>
你的成绩为中等
</c:when>
<c:when test="${score>=60}">
<c:out value="你的成绩为一般"/>
你的成绩为一般
</c:when>
<c:when test="${score<60}">
<c:out value="你的成绩为不及格"/>
你的成绩为不及格
</c:when>
</c:choose>
</body>
</html>
c:forEach
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
ArrayList<String> people = new ArrayList<>();
people.add(0,"李四");
people.add(1,"王五");
people.add(2,"王二麻子");
people.add(3,"天吴");
people.add(4,"李六");
request.setAttribute("list",people);
%>
<%--
var:每一次遍历出来的变量
items:要遍历的对象
begin: 开始
end:结束
step:步长
--%>
<c:forEach var="person" items="${list}">
<c:out value="${person}"/>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1">
<c:out value="${people}"/>
</c:forEach>
</body>
</html>
JavaBean(了解一下)
实体类
JavaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM;
ORM:对象关系映射
- 表----->类
- 字段----->属性
- 行记录----->对象
People表:
id | name | age | address |
---|---|---|---|
1 | 鲁班一号 | 18 | 信阳 |
2 | 鲁班二号 | 19 | 新县 |
3 | 鲁班三号 | 20 | 潢川 |
package com.sgl.pojo;
//实体类 一般都是和数据库中的表结构一一对应!
public class People {
private int id;
private String name;
private int age;
private String address;
public People() {
}
public People(int id, String name, int age, String address) {
this.id = id;
this.name = name;
this.age = age;
this.address = address;
}
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "People{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
jsp:useBean jsp:setProperty jsp:getProperty
<%@ page import="com.sgl.pojo.People" %><%--
Created by IntelliJ IDEA.
User: shiga
Date: 2021/9/5
Time: 20:45
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>
<%
People people02 = new People();
people02.setAddress("新县");
people02.setAge(19);
people02.setId(2);
people02.setName("鲁班二号");
%>
<%=people02.getAddress()%>
<%=people02.getAge()%>
<%=people02.getId()%>
<%=people02.getName()%>
<br>
<%--id="people01" people01就相当于People类的一个实例化对象--%>
<jsp:useBean id="people01" class="com.sgl.pojo.People" scope="page"/>
<jsp:setProperty name="people01" property="address" value="信阳"/>
<jsp:setProperty name="people01" property="age" value="18"/>
<jsp:setProperty name="people01" property="id" value="1"/>
<jsp:setProperty name="people01" property="name" value="鲁班一号"/>
住址:<jsp:getProperty name="people01" property="address"/>
年龄:<jsp:getProperty name="people01" property="age"/>
id:<jsp:getProperty name="people01" property="id"/>
姓名:<jsp:getProperty name="people01" property="name"/>
</body>
</html>
在数据库建立对应的表
MVC三层架构
JSP Model2模型采用JSP(View)+Servlet(Controller)+JavaBean(Model)的技术
- 模型(Model):负责管理应用程序的业务数据,定义访问控制以及以及修改这些业务数据的业务规则
简单理解:
1. 业务处理:业务逻辑(Service)
2. 数据持久化:CRUD(Dao)
- 视图(View):负责与用户交互,它从模型中获取数据向用户展示,同时也能将用户请求传递给控制器进行处理。当模型的状态发送改变时,视图会对用户界面进行同步更新,从而保持与模型数据的一致性
简单理解:
1. 展示数据
2. 提供链接发送Servlet请求(a,form,img.....)
- 控制器(Controller):是负责应用程序中处理用户交互的部分,它负责从视图中读取数据,控制用户输入,并向模型发送数据
简单理解:
1. 接收用户的请求:(req:请求参数、Session信息)
2. 交给业务层处理相对于的代码 3.控制视图的跳转
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)--->交给业务层处理登录业务(判断用户密码是否正确:事务)--->Dao层查询用户和密码是否正确--->数据库
JSP Model2工作原理图
3个模型之间的关系和功能图
Filter***
Filter:过滤器,用来过滤网站的数据;
- 处理中文乱码
- 登录验证
Filter开发步骤:
- 导包不要导错
pom.xml
<!--Servlet依赖-->
<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>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签库依赖-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--连接数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
</dependencies>
- 编写过滤器
过滤器:看代码注释理解
package com.sgl.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初始化");
}
//销毁:web服务器关闭的时候,过滤会销毁
@Override
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
//filterChain:链
/*
1.过滤中的所有代码,在过滤特定请求的时候都会执行
2.必须让过滤器继续同行
filterChain.doFilter(servletRequest,servletResponse)
*/
@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执行后...");
}
}
经过过滤器处理中文乱码的代码
package com.sgl.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);
}
}
虚拟路径配置 web.xml
<servlet>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>com.sgl.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/ShowServlet</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.sgl.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是经过/CharacterEncodingFilter的请求,都会经过这个过滤器-->
<url-pattern>/*</url-pattern>
</filter-mapping>
监听器
实现监听器的接口:N种
-
编写一个监听器
实现监听器接口
package com.sgl.listener; import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; //统计网站在线人数:统计session public class OnlineCountListener implements HttpSessionListener { //创建session监听 //一旦创建session就会触发这个事件 @Override public void sessionCreated(HttpSessionEvent se) { ServletContext context = se.getSession().getServletContext(); Integer onlineCount = (Integer) context.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount = new Integer(1); }else { int count = onlineCount.intValue(); onlineCount = new Integer(count+1); } context.setAttribute("OnlineCount",onlineCount); } //销毁session监听 //一旦销毁session就会触发这个事件 @Override public void sessionDestroyed(HttpSessionEvent se) { ServletContext context = se.getSession().getServletContext(); Integer onlineCount = (Integer) context.getAttribute("OnlineCount"); if (onlineCount==null){ onlineCount = new Integer(0); }else { int count = onlineCount.intValue(); onlineCount = new Integer(count-1); } context.setAttribute("OnlineCount",onlineCount); } /* 1.手动销毁 getSession().invalidate(); 2.自动销毁 在web.xml配置 */ }
回忆session销毁
- 手动销毁 getSession().invalidate();
- 自动销毁 在web.xml配置
<session-config> <session-timeout>1</session-timeout> </session-config>
-
web.xml中配置监听器
<!--注册监听器-->
<listener>
<listener-class>com.sgl.listener.OnlineCountListener</listener-class>
</listener>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h1>当前有 <span style="color: blue"><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人在线</h1>
</body>
</html>
效果:
过滤器 监听器的常见应用
监听器:GUI中经常使用
package com.sgl.listener;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class TestPanel {
public static void main(String[] args) {
Frame frame = new Frame("中秋节快乐"); //新建一个窗口
Panel panel = new Panel(null); //面板
frame.setLayout(null);//设置窗体的布局
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(0,0,0));//设置背景颜色
panel.setBounds(50,50,300,300);
panel.setBackground(new Color(0,25,26));
frame.add(panel);
frame.setVisible(true);
//监听事件
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(1);
}
});
}
}