JavaWeb学习笔记
1、JavaWeb
1.1、前言
- Web:网页
- 静态Web:
- html,css
- 提供给所有人看的数据始终不会改变
- 动态Web:
- 提供给别人看的数据会发生改变
- 技术栈:Servlet/JSP、ASP、PHP
在java中,动态Web资源开发的技术统称为javaweb;
1.2、Web应用程序
web应用程序:可以提供给浏览器访问的程序;
- html.....这些资源可以被外界访问,可以对外界提供访问
- URL
- 这些统一的外部资源会被统一放在一个文件夹、wab应用程序-->Tomcat服务器
- 一个Web应用又多部分组成(静态web和动态web)
- html、css、js
- jsp、servlet
- java程序
- jar包
- 配置文件
Web程序编写完成之后,若想给外界访问,需要一个服务器统一管理
1.3、静态Web
- html、htm,这些都是网页后缀,如果服务器上一直存在这些东西,我们可以直接获取、联络
- 静态Web存在的缺点:
- Web页面无法更新,所有用户看到的都是同一个页面
- 轮播图,点击特效
- js
- 无法和数据交互(数据无法持久化,用户无法交互)
- Web页面无法更新,所有用户看到的都是同一个页面
1.4、动态Web
页面会动态展示,“页面的展示效果因人而异”
- 缺点: 加入服务器的动态资源出现了错误,我们需要重新编写过我们的后台程序(停机维护)
- 优点:
- Web可以动态更新
- 可以与数据库交互(数据持久化)
2、Web服务器
2.1、技术讲解
ASP:微软,国内最早流行的
- 逻辑代码和页面混杂在一起
- 维护成本高
- 代码混乱
PHP: - 开发速度快,功能强大,跨平台,代码简单
- 无法存在大访问量的情况
JSP/Servlet:
B/S:浏览器和服务器
C/S:客户端和浏览器 - sun公司主推的B/S架构
- 基于java语言的(所有的大公司,开源的的组件,都是java开发)
- 可承载三高问题带来的影响(高并发、高可用、高性能)
2.2、Web服务器
服务器是一种被动的操作,用来处理一些用户的请求和给用户响应一些信息
- IIS
- 微软,ASP
- windows自带的服务器
- Tomcat
- Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目
- Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。
- 对于一个初学Web的人来说,是最好的服务器
3、Tomcat
3.1、关于Tomcat
安装:官网安装,解压
work文件夹:
jsp,tomcat的工作原理是当浏览器访问某个jsp页面时,tomcat会在work目录里把这个jsp页面转换成.java文件,比如将index.jsp转换为index_jsp.java文件,而后编译为index_jsp.class文件,最后tomcat容器通过ClassLoader类把这个index_jsp.class类装载入内存,进行响应客户端的工作。
tomcat会定时稍描容器内的jsp文件,读取每个文件的属性,当发现某个jsp文件发生改变时(文件的最后修改时间与上次稍描时不相同时),tomcat会重新转换、编译这个jsp文件。但是tomcat的稍描是定时的不是实时的,这也正是为什么jsp文件修改后需要几分钟的时间来等修改过的jsp生效。当然为了即刻生效,很多老前辈都会建议在修改jsp页面后立即清除work目录里的文件。
3.2、如何发布网站
3.3、网站该有的结构
4、Http
4.1、什么是http?
HTTP(超文本传输协议)是一种简单的传输协议,通常运行在TCP上
- 文本:html,字符串
- 超文本:图片,声音,视频,定位,地图
- 默认端口80
HTTPS:加密
- 默认端口443
4.2、两个时代
- http1.0
- HTTP/1.0:客户端与web服务器连接后,只能获得一个web资源,断开连接
- http1.1
- HTTP/1.1:客户端与web服务器连接后,可以获得多个web资源
4.3、Http请求
- 客户端--发请求--服务器
常规
Request URL:https://www.baidu.com/ 请求地址
Request Method:GET 请求方法
Status Code:200 OK 状态码
Remote(远程) Address:36.152.44.96:443 IP端口号
请求头
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,ja;q=0.5
Cache-Control: max-age=0
Connection: keep-alive
Cookie:
Host: www.baidu.com
Referer: https://cn.bing.com/
sec-ch-ua: " Not;A Brand";v="99", "Microsoft Edge";v="103", "Chromium";v="103"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.77
1、请求行
- 请求行中的请求方式: GET
- 请求方式: Get, Post, HEAD,DELETE,PUT,TRACT...
- get: 请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- post: 请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全但不高效。
2、消息头
//告诉服务器,支持哪种类型
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
//支持哪种编码格式
Accept-Encoding: gzip, deflate, br
//告诉服务器浏览器的语言环境
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,ja;q=0.5
//缓存控制
Cache-Control: max-age=0
//告诉浏览器,请求完成是断开还是保持连接
Connection: keep-alive
//主机
Host:
4.3、Http响应
- 服务器--响应--客户端
百度响应头
Bdpagetype: 2
Bdqid: 0xff178ac000047df4
Cache-Control: private
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8
Date: Mon, 01 Aug 2022 04:55:41 GMT
Expires: Mon, 01 Aug 2022 04:55:41 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=382; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=36551_36463_36724_36413_36955_36948_36165_36917_36776_36745_26350_36938; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1659329741065239809018381312961374617076
Transfer-Encoding: chunked
X-Frame-Options: sameorigin
X-Ua-Compatible: IE=Edge,chrome=1
请求响应码
- 信息响应(100–199)
- 成功响应(200–299)
- 重定向(300–399)
- 客户端错误(400–499)
- 服务器错误 (500–599)
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误
5、maven
我们为什么需要学习这个技术?
1、在JavaWeb开发中,我们需要使用大量的jar包,我们手动导入
如何能够让一个东西自动帮我们导入和配置这个jar包?
maven诞生
5.1、Maven架构管理工具
我们目前就是用来导入jar包
Maven的核心思想:约定大于配置
- 有约束,不要去违反
Maven会规定如何去写java代码,必须按照这个规范来
5.2、安装Maven
1、下载:https://maven.apache.org/
2、安装:解压即可
3、配置环境变量
5.3、修改配置文件
配置阿里云镜像
5.4、本地仓库
配置本地仓库
5.5、创建Maven项目
5.6、创建一个干净的maven项目
给项目添加web配置,作为web目录
5.7、配置tomcat
6、Servlet
6.1、Servlet简介
- Servlet就是sun公司开发动态web的一门技术
- sun在这些API中提供了一个接口,叫做Servlet,开发一个Servlet应用,只需要完成两个小步骤:
- 编写一个类,实现Servlet接口
- 把开发好的类部署到Web中
把实现了Servlet接口的程序叫做Servlet
6.2、构建一个普通的mave项目
6.3、构件父子工程
把src目录删掉后,再创建一个字工程
这个父模块pom里面没有多余的东西,子模块需要用到的依赖可以直接从父模块获取
父模块中的依赖子模块也可以使用
6.4、关于web.xml
6.5、ServletContext
ServletContext就是多个servlet类共享数据
1、共享数据
在这个文件中保存的name
public class Servlet_set extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String name = "钟海华";
servletContext.setAttribute("name",name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
在另外一个文件中去访问:
public class Servlet_get extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
ServletContext servletContext = this.getServletContext();
PrintWriter writer = resp.getWriter();
writer.print("名字:"+servletContext.getAttribute("name"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
对应的是两个不同的servlet
2、获取初始化参数
3、转发请求
//转发请求
set
servletContext.getRequestDispatcher("/get").forward(req,resp);
get
ServletContext servletContext = this.getServletContext();
PrintWriter writer = resp.getWriter();
writer.print("url:"+servletContext.getInitParameter("url"));
请求set,但是到get执行了代码
4、读取文件
6.6、HttpServletResponse
Web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表http请求的HttpServletRequest对象和一个代表响应的HttpServletresponse对象
- 如果想要获取客户端请求过来的参数,找HttpServletRequest对象
- 如果想要给客户端回应信息,找HttpServletResponse对象
1、简单分类
- 负责相浏览器发送数据的方法
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 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_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2、常见应用
1、向浏览器输出消息
2、下载文件
1.要获取下载文件的路径
2.下载的文件名是啥?
3.设置想办法让浏览器能够支持下载我们需要的东西
4.获取下载文件的输入流
5.创建缓冲区
6.获取OutputStream对象
7.将FileOutputStream流写入到buffer缓冲区
8.使用OutputStream将缓冲区中的数据输出到客户端!
3、实现重定向
void sendRedirect(String var1) throws IOException;
重定向:response.sendRedirect() 可以使用相对路径和绝对路径
当浏览器想服务器发起了一个http请求时,如:http:localhost:8080/myapp/user/Test1
相对路径:response.sendRedirect("Login") 容器相对于原来请求URL的目录加参数来生成完整的URL—http:localhost:8080/myapp/user/Login
绝对路径 :response.sendRedirect("/Login") 容器相对于Web应用本身加参数建立完整的URL—http:localhost:8080/Login
转发:request.getRequestDispatcher() 也可以使用相对路径和绝对路径
相对路径:request.getRequestDispatcher("Login") 容器相对于原来请求URL的目录加参数来生成完整的URL—http:localhost:8080/myapp/user/Login
绝对路径 :request.getRequestDispatcher("/Login") 容器相对于当前的Web应用本身加参数建立完整的URL—http:localhost:8080/myapp/Login
6.7、HttpServletRequest
1、请求数据
请求行:
GET/request-demo/req1?username=zhangsan&password=123 HTTP/1.1
String getMethod()获取请求方式:GET
String getContextPath()获取虚拟目录(项目访问路径):/request-demo
StringBuffer getRequestURL()获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
String getRequestURI()获取URI(统一资源标识符):/request-demo/req1
String getQueryString()获取请求参数(GET方式):username=zhangsan&password=123
请求头:
User-Agent:Mozilla/5.0 Chrome/91.0.4472.106
String getHeader(String name)根据请求头名称,获取值
请求体:
username=superbaby&password=123
ServletputStream getInputStream()获取字节输入流
BufferedReader getReader()获取字符输入流
Request-通用方式获取请求参数(对get和post方式都一样)
Map<String, String[]> getParameterMap()获取所有参数Map集合
String[] getParameterValues(String name)根据名称获取参数值(数组)
String getParameter(String name)根据名称获取参数值(单个值)
解决中文乱码问题
POST
request.setCharacterEncoding("UTF-8")
GET(下面的方法也可以用于POST)
乱码原因:tomcat解码的默认字符集是ISO-8859-1
解决方法
先对乱码数据进行编码:转为字节数组byte[] bytes = username.getBytes(StandardCharsets.IOS_8859_1);
字节数组解码username = new String(bytes, StandardCharsets.UTF_8);
username即还原为中文字符串
请求转发:一种在服务器内部的资源跳转方式
实现方式:req.getRequestDispatcher("转发资源路径").forward(req.resp);
请求转发资源间共享数据:使用Request对象
void setAttribute(String name, Object o)存储数据到request域中
Object getAttribute(String name)根据key,获取值
void removeAttribute(String name)根据key,删除该键值对
请求转发特点
浏览器地址栏路径不发生变化
只能转发到当前服务器的内部资源
一次请求,可以在转发的资源间使用request共享数据
7、Cookie、Session
7.1、会话
会话:用户打开了浏览器,打开了很多个连接,访问了多个超链接,关闭浏览器这个过程可以称之为会话
有状态会话: 用户来过网站,下次再来这个网站的时候,网站可以知道这个用户
7.2、保存会话的两种技术
1、cookie:客户端技术
- 客户端会话技术,将数据保存在客户端,以后每次请求都携带Cookie数据进行访问
应用:
记录客户端上一次登陆的时间
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();
if(cookies.length != 0){
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if(cookie.getName().equals("lastLoginTime")){
out.print("你上一次登陆的时间是"+new Date(Long.parseLong(cookie.getValue())).toString());
}
}
}
resp.addCookie(new Cookie("lastLoginTime",System.currentTimeMillis()+""));
Cookie的常用方法
public void setMaxAge(int expiry) {
this.maxAge = expiry;
}
public int getMaxAge() {
return this.maxAge;
}
public String getName() {
return this.name;
}
public void setValue(String newValue) {
this.value = newValue;
}
public String getValue() {
return this.value;
}
Cookie使用细节
Cookie存活时间
默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁
setMaxAge(int seconds):设置Cookie存活时间
正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除
负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
零:删除对应Cookie
Cookie存储中文
Cookie不能直接存储中文
如需要存储,则需要进行转码:URL编码URLEncoder.eccode("需要编码的内容", "UTF-8");
2、session:服务端技术
session是由服务器创建的
服务器第一次接收到请求时,开辟了一块 Session 空间(创建了Session对象),同时生成一个 sessionId ,并通过响应头的 Set-Cookie:JSESSIONID=XXXXXXX 命令,向客户端发送要求设置 Cookie 的响应;
客户端收到响应后,在本机客户端设置了一个 JSESSIONID=XXXXXXX 的 Cookie 信息,该 Cookie 的过期时间为浏览器会话结束
接下来客户端每次向同一个网站发送请求时,请求头都会带上该 Cookie信息(包含 sessionId ), 然后,服务器通过读取请求头中的 Cookie 信息,获取名称为 JSESSIONID 的值,得到此次请求的 sessionId。
session生成大概是,首先你发个请求去服务端,如果你的cookie里面有他之前写的session(叫什么都ok,jsessionid或者其他都行,取决于容器的实现),那么直接读取容器内存该sessionid对应的信息
如果是第一次请求,分2种情况:
1,如果服务端调用获取或设置session的方法,但是传过来的cookie里面没有(根本没cookie可传过去),那么自动生成一个session,并在响应头里面加上Set-Cookie,向浏览器申请写入cookie
2,如果服务端没有调用获取或设置session的方法,那么就不会生成并下发session,应该是为了节省网络以及服务器资源。
什么是session?
- 服务端会话跟踪技术:将数据保存到服务端
- 服务器会给每一个用户创建一个session对象
- 一个session独占一个浏览器,只要浏览器没有关,这个session就存在
- 用户登陆之后,整个网站都可以共用信息
- 一些常用方法
session和cookie的区别
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session把用户的数据写到用户独占Session中,服务器端保存(保存重 要的信息,减少服务器资源的浪费)
- Session对象由服务创建;
使用场景:
- 保存一个登录用户的信息;
- 购物车信息;
- 在整个网站中经常会使用的数据,我们将它保存在Session中;
在一个servlet中存储数据
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.setAttribute("p1",new Person("张三",22));
}
在一个servlet中读取数据
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
HttpSession session = req.getSession();
Person p1 = (Person)session.getAttribute("p1");
PrintWriter out = resp.getWriter();
out.write(p1.getName()+p1.getAge());
}
JavaEE提供HttpSession接口,来实现一次会话的多次请求间数据共享功能
Session基本使用
获取Session对象
HttpSession session = request.getSession();
Session对象功能
void setAttribute(String name, Object o)存储数据到session域中
Object getAttribute(String name)根据key,获取值
void removeAttribute(String name)根据key,删除该键值对
Session原理
Session是基于Cookie实现的
Session使用细节
Session钝化、活化
服务器重启后,Session中的数据是否还在?
钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中
活化:再次启动服务器后,从文件中加载数据到Session中
Session销毁
默认情况下,无操作,30分钟自动销毁(在web.xml中配置)
<session-config>
<session-timeout>30</session-timeout>
</session-config>
Cookie和Session总结
Cookie和Session都是来完成一次会话内多次请求间数据共享的
区别
- 存储位置:Cookie实践爱那个数据存储在客户端,Session将数据存储在服务端
- 安全性:Cookie不安全,Session安全
- 数据大小:Cookie最大3KB,Session无大小限制
- 存储时间:Cookie可以长期存储,Session默认30分钟
- 服务器性能:Cookie不占服务器资源,Session占用服务器资源
8、JSP
8.1、什么是jsp?
java server pages :java 服务器端页面,也和servlet一样,用于动态web技术
最大的特点:
- 写jsp就像是在写html
- 区别
- HTML只给用户提供静态数据
- jsp中可以嵌入java代码,为用户提供动态数据
8.2、jsp原理
思路:jsp是怎么执行的
jsp本质就是servlet
最后还是httpservlet的子类
在类里面内置一些对象
向客户端输出的是字符串:
输出页面前增加的代码:
以上对象我们的都可以直接使用
8.3、jsp的基础语法
1、jsp表达式
<%= %>
<%= new java.util.Date()%>
2、脚本片段
<%
%>
<%
for (int i = 0; i < 100; i++) {
out.println("<h1>"+i+"</h1><br>");
}
%>
3、jsp声明
<%!
%>
4、jsp注释
<%-- 注释 --%>
8.4、jsp指令
<%@ page ...... %>
.......
8.5、九大内置对象
JSP 中定义了 9 个内置对象,它们分别是:request、response、session、application、out、pagecontext、config、page 和 exception,这些对象在客户端和服务器端交互的过程中分别完成不同的功能。
JSP 的内置对象主要有以下特点:
- 由 JSP 规范提供,不用编写者实例化;
- 通过 Web 容器实现和管理;
- 所有 JSP 页面均可使用;
- 只有在脚本元素的表达式或代码段中才能使用。
8.6、四大域对象
在 JSP 九大内置对象中,包含四个域对象,它们分别是:pageContext(page 域对象)、request(request 域对象)、session(session 域对象)、以及 application(application 域对象)。
JSP 中的 4 个域对象都能通过以下 3 个方法,对属性进行保存、获取和移除操作。
JSP 中的 4 个域对象的作用域各不相同,如下表。
存储数据:
pageContext. setAttribute("name1", "1号"); //保存的数据只在-一个页面中有效
request. setAttribute("name2","2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session. setAttribute("name3", "3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
applicati on. setAttribute ("name4","4号"); //保存的数据只在服务 器中有效,从打开服务器到关闭服务器
取出数据:
//从pageContext取出,我们通过寻找的方式来
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");
request: 客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!
session: 客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;
application:客户端向服务器发送请求,产生的数据,-个用户用完了,其他用户还可能使用,比如:聊天数据;
8.6、JSP标签、EL表达式、JSTL
1、JSP标签
-
< jsp:forward>
该标签的作用是把请求转发给另外一个资源,页面中使用该指令之后,当前页面中的所有要显示的内容都将无法显示,因为会直接转发到了另一个页面。 -
< jsp:include>
该标签用于把另外一个文件引入到当前JSP里面,这种引入方式叫做动态引入。
动态引入和静态引入的区别
静态引入:
<%@ include file="/xxx.jsp" %>
静态引入会生成一个java文件,两个jsp文件中可以共享同一个变量,但不能定义重名的变量。
动态引入:
<jsp:include page="/xxx.jsp"/>
动态引入会生成两个java文件,两个jsp文件中不可以共享同一个变量,可以定义重名的变量。
在静态引入与动态引入均可使用时,一般使用静态引入。因为在程序运行时只存在一个Servlet,对资源的消耗较少,且不存在调用问题,执行效率较高。
2、EL表达式
EL 全名为Expression Language。EL主要作用:
-
获取数据
EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象、获取数据。(某个web域 中的对象,访问javabean的属性、访问list集合、访问map集合、访问数组) -
执行运算
利用EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算。$ -
获取web开发常用对象
EL 表达式定义了一些隐式对象,利用这些隐式对象,web开发人员可以很轻松获得对web常用对象的引用,从而获得这些对象中的数据。 -
调用Java方法
EL表达式允许用户开发自定义EL函数,以在JSP页面中通过EL表达式调用Java类的方法。
使用EL表达式获取数据语法:"${标识符}"
EL表达式语句在执行时,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、session、application四个域中查找相应的对象,找到则返回相应对象,找不到则返回”” (注意,不是null,而是空字符串)。
EL表达式可以很轻松获取JavaBean的属性,或获取数组、Collection、Map类型集合的数据
实例:
<%
request.setAttribute("name","孤傲苍狼");
%>
<%--${name}等同于pageContext.findAttribute("name") --%>
使用EL表达式获取数据:${name}
<!-- 在jsp页面中,使用el表达式可以获取bean的属性 -->
<%
Person p = new Person();
p.setAge(12);
request.setAttribute("person",p);
%>
使用el表达式可以获取bean的属性:${person.age}
<!-- 在jsp页面中,使用el表达式可以获取bean中的。。。。。。。。。的属性 -->
<%
Person person = new Person();
Address address = new Address();
person.setAddress(address);
request.setAttribute("person",person);
%>
${person.address.name}
<!-- 在jsp页面中,使用el表达式获取list集合中指定位置的数据 -->
<%
Person p1 = new Person();
p1.setName("孤傲苍狼");
Person p2 = new Person();
p2.setName("白虎神皇");
List<Person> list = new ArrayList<Person>();
list.add(p1);
list.add(p2);
request.setAttribute("list",list);
%>
<!-- 取list指定位置的数据 -->
${list[1].name}
<!-- 迭代List集合 -->
<c:forEach var="person" items="${list}">
${person.name}
</c:forEach>
<!-- 在jsp页面中,使用el表达式获取map集合的数据 -->
<%
Map<String,String> map = new LinkedHashMap<String,String>();
map.put("a","aaaaxxx");
map.put("b","bbbb");
map.put("c","cccc");
map.put("1","aaaa1111");
request.setAttribute("map",map);
%>
<!-- 根据关键字取map集合的数据 -->
${map.c}
${map["1"]}
<!-- 迭代Map集合 --
<c:forEach var="me" items="${map}">
${me.key}=${me.value}
</c:forEach>
3、JSTL
使用JSTl标签需要导包,具体百度
简介:
JSTL是一个JSP标签集合,它封装了JSP应用的通用核心功能,主要结构由五部分组成
- 1.核心标签
- 2.格式化标签
- 3.SQL标签
- 4.XML标签
- 5.JSTL函数
引入核心标签库:<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forEach>的使用,需要与el表达式联合使用
< c : forEach >标签的语法定义如下所示。
< c : forEach var="每个变量名字" items="要迭代的list" varStatus="每个对象的状态"
begin="循环从哪儿开始" end ="循环到哪儿结束" step="循环的步长">
循环要输出的东西
</ c : forEach >
<c:if>
<body>
<!-- 语法格式 -->
<c:if test="条件" var="变量名" scope="属性的作用域(可加可不加)">
...
</c:if>
<!-- 定义一个if判断 -->
<c:set var="salary" scope="session" value="${2000*2}"/>
<!-- 如果我的工资大于2000就进入判断 -->
<c:if test="${salary > 2000}">
<p>我的工资为: <c:out value="${salary}"/><p>
</c:if>
</body>
<c:choose> 本身只当做<c:when>和<c:otherwise>的父标签(感觉和 while 一样用)
<c:when> <c:choose>的子标签,用来判断条件是否成立
<c:otherwise> <c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行
<body>
<!-- 语法格式 -->
<!-- 其实这个东西感觉和IF差不多 -->
<c:choose>
<c:when test="条件">
...
</c:when>
<c:when test="条件">
...
</c:when>
...
...
<c:otherwise>
...
</c:otherwise>
</c:choose>
<c:set var="salary" scope="session" value="${2000*2}"/>
<p>你的工资为 : <c:out value="${salary}"/></p>
<c:choose>
<c:when test="${salary <= 0}">
太惨了
</c:when>
<c:when test="${salary > 1000}">
不错的薪水,还能生活。
</c:when>
<c:otherwise>
什么都没有。
</c:otherwise>
</c:choose>
</body>
<c:out>
其他:
<c:set> 用于保存数据(作用和out差不多)
<c:remove> 用于删除数据
<c:catch> 用来处理产生错误的异常状况,并且将错误信息储存起来
<c:import> 检索一个绝对或相对 URL,然后将其内容暴露给页面
<c:forTokens> 根据指定的分隔符来分隔内容并迭代输出(相比而言,<c:forEach>标签是更加通用的标签)
<c:param> 用来给包含或重定向的页面传递参数
<c:redirect> 重定向至一个新的URL.
<c:url> 使用可选的查询参数来创造一个URL
9、JavaBean
JavaBen:实体类
JavaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法;
一般用来和数据库的字段做映射
ORM :对象关系映射
- 表-->类
- 字段-->属性
- 行记录--->对象
<%
//People people = new People();
//people. setAddress();
//people. setId();
//people. setAge();
//people. setName();
%>
<jsp: useBean id="peop1e" class="com. kuang. pojo. People" scope="page"/>
<jsp: setProperty name="people"property= " address" value="西安"/>
<jsp: setProperty name="people" property="id" value="1"/>
<jsp: setProperty name="people" property="age" value="3"/>
<jsp: setProperty name="people" property=" name" value=" 小狂神呀"/>
姓名: <jsp: getProperty name= "peop1e" property="name"/>
id: <jsp:getProperty name= "people" property="id"/>
年龄: <jsp:getProperty name= "people'
property="age"/>
地址: <jsp: getProperty name=" people" property= "address"/>
10、MVC三层架构
10.1、介绍
什么是MVC:
Model 模型
view 视图
Controller 控制器
在以前,项目是这样分成的:
用户直接访问控制层,控制层就可以直接操作数据库;
servlet--CRUD-->数据库
弊端:
- 程序十分臃肿,不利于维护
- serv1et的代码中: 处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
MVC三层架构:
Model
- 业务处理:业务逻辑(Service)
- 数据持久层: CRUD (Dao)
View .
- 展示数据
- 提供链接发起Servlet请求(a, form, img...)
Controller (Servlet)
- 接收用户的请求: (req: 请求参数、Session信....
- 交给业务层处理对应的代码
- 控制视图的跳转
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username, password) ---->交
给业务层处理登录业务(判断用户名密码是否正确:事务) --->Dao层查询用户名和密码是否正确-->数据库
11、Filter
Filter:过滤器:用来过滤网站的数据;
- 处理中文乱码
- 登录验证
编写Filter步骤:
- 导包
- 实现Filter接口
- 重写doFilter方法
- 配置web.xml文件
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("执行前");
chain.doFilter(request,response);
System.out.println("执行后");
}
11.1、登陆小demo
1、登陆servlet
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
if(name.equals("admin")){
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/Filter/sys/Home.html");
}else {
resp.sendRedirect("/Filter/sys/error.html");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2、注销
public class LoginOut extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().removeAttribute("USER_SESSION");
resp.sendRedirect("/Filter/Login.html");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3、过滤器
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
resp.setDateHeader("Expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
if(req.getSession().getAttribute("USER_SESSION") != null){
chain.doFilter(req,resp);
}else {
resp.sendRedirect("/Filter/Login.html");
}
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
注意浏览器缓存机制
因为浏览器缓存,会导致注销登陆之后回退或者不刷新会回到登陆的状态,但是此时我们已经注销账户了
解决:设置响应头,让浏览器不缓存
response.setDateHeader("Expries", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
12、监听器
public class Listener01 implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("创建了一个session");
System.out.println(se.getSession().getId());
ServletContext servletContext = se.getSession().getServletContext();
if(servletContext.getAttribute("userNum") != null){
int newNum = ((int) servletContext.getAttribute("userNum")) +1;
servletContext.setAttribute("userNum",newNum);
}else {
servletContext.setAttribute("userNum",1);
}
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println(se.getSession().getId());
ServletContext servletContext = se.getSession().getServletContext();
int newNum = ((int) servletContext.getAttribute("userNum")) - 1;
servletContext.setAttribute("userNum",newNum);
}
}
13、SMBMS项目
13.1、搭建项目
- 搭建一个maven项目
- 配置tomcat
- 导入依赖
- 创建项目包结构
- 建实体类:ORM映射 表---->类
- 编写基础公共类
- 数据库配置文件
- 编写基础DAO类的crud
- 编写字符编码过滤器
- 导入静态资源
13.2、登陆注销实现
1、登陆servlet
public class LoginServlet extends HttpServlet {
private LoginService loginService = new LoginService();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("userPassword");
User user = loginService.LoginUser(userCode, userPassword);
if(user != null){
//Constant.USER_SESSION = userSession
//userSession为前端获取Javabean对象的属性
//${userSession.userName }会调用user类的get方法,所以必须拥有get方法才可以获取
req.getSession().setAttribute(Constant.USER_SESSION,user);
resp.sendRedirect(req.getContextPath()+"/jsp/frame.jsp");
}else{
//登陆错误前端需要获取error信息,这里把错误信息的kv放在req里面转发给前端
//<div class="info">${error}</div>
req.setAttribute("error","登陆错误,请检查账号密码是否正确");
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2、注销servlet
public class LoginOut extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//将对应session的kv移除,属性为空则表示非登陆状态
req.getSession().removeAttribute(Constant.USER_SESSION);
resp.sendRedirect(req.getContextPath()+"/login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
3、拦截器:用户注销之后还可以直接进入主页,需要根据session的userSession值是否存在,来拦截对应请求
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse)response;
if(req.getSession().getAttribute(Constant.USER_SESSION) == null){//未登陆
resp.sendRedirect(req.getContextPath()+"/error.jsp");
}else {
//注意这里是原来的request,response
chain.doFilter(request,response);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!