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
    • 无法和数据交互(数据无法持久化,用户无法交互)

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步骤:

  1. 导包
  2. 实现Filter接口
  3. 重写doFilter方法
  4. 配置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、搭建项目

  1. 搭建一个maven项目
  2. 配置tomcat
  3. 导入依赖
  4. 创建项目包结构
  5. 建实体类:ORM映射 表---->类
  6. 编写基础公共类
    1. 数据库配置文件
    2. 编写基础DAO类的crud
    3. 编写字符编码过滤器
  7. 导入静态资源

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

13.2、密码修改

posted @   看海、听风  阅读(127)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示