JavaWeb进阶学习 配合学习视频:狂神说Java—JavaWeb入门到实战
内容主要包括:
web开发基本概念
Tomcat服务器的学习和使用
Maven项目的搭建
Servlet介绍
Cookie、Session
Jsp
MVC架构
过滤器Filter、监听器Listener
JDBC
1、基本概念 1.1、前言 web开发:
web:指网页
静态web
html、css
提供给所有人看的数据始终不会发生变化!
动态web
几乎所有的网站都是
提供给所有人看的数据始终会发生变化,每个人在不同的时间、地点看到的信息各不相同!
技术栈:Servlet/Jsp、ASP、PHP
在Java中,动态web资源开发的技术统称为JavaWeb
1.2、web应用程序 web应用程序:可以提供浏览器访问的程序
a.html、b.html…多个web资源,可以被外界访问,对外界提供服务;
能访问到的任何一个页面或者资源,都存在于世界上的某一个计算机;
URL:统一资源定位符
这个统一的web资源会被放在同一个文件夹下,web应用程序—>Tomcat:服务器
一个web应用由多部份组成(静态web、动态web)
html、css、js
jsp、servlet
Java程序
jar包
配置文件(Properties)
web应用程序编写完毕后,若想提供给外界访问,需要一个服务器来统一管理
1.3、静态web
*.htm、 *.html,这些都是网页的后缀,如果服务器上一直存在着这些东西,我们就可以直接进行读取
静态web缺点
Web页面无法更新,所有用户看到的是同一个页面
轮播图、点击特效:伪动态
JavaScript(实际开发中,使用最多)
VBScript
、它无法和数据库交互(数据无法持久化,用户无法交互)
1.4、动态web 页面展示的效果会因人而异
缺点:
加入服务器的动态web资源出现了错误,我们需要重新编写后台程序
优点:
Web页面可以动态更新,所有用户看到的都不是同一个页面
可以与数据库进行交互(可以数据持久化)
2、web服务器 2.1、技术讲解
ASP
微软:国内最早流行的就是ASP
在HTML中嵌入了VB脚本,ASP+COM
在ASP开发中,基本一个页面都有几千行的业务代码,页面及其混乱
维护成本高
C#
IIS
php
PHP开发速度很快,功能很强大,跨平台,代码简单
缺点:无法承载大访问量的情况(局限性)
JSP/Servlet
sun公司主推的B/S架构
基于Java语言(所有的大公司,或者一些开源的组件,都是用Java语言写的)
可以承载三高(高并发、高可用、高性能)问题带来的影响
语法像ASP,易于ASP程序员转JSP,加强市场强度
……
2.2、web服务器 服务器是一种被动的操作,用来处理用户的一些请求和给用户的一些响应信息
IIS
微软的,ASP…,Windows自带的
Tomcat
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache 、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。因为Tomcat 技术先进、性能稳定,而且免费 ,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器 ,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,是最佳选择
Tomcat 实际上运行JSP 页面和Servlet。目前Tomcat最新版本为9.0.41。
……
ps. 工作3-5年后可尝试手写Tomcat服务器(了解底层原理);
下载Tomcat:
安装 or 解压
了解配置文件及目录结构
这个东西的作用
3、Tomcat 3.1、安装Tomcat Tomcat官网
3.2、Tomcat启动和关闭
访问测试:http://localhost:8080/
可能遇到的问题:
Java环境变量没有配置
闪退问题:需要配置兼容性
乱码问题:配置文件中设置
3.3、配置 可以配置启动的端口号
Tomcat的端口号:8080
mysql:3306
http:80
https:443
1 2 3 <Connector port ="8080" protocol ="HTTP/1.1" connectionTimeout ="20000" redirectPort ="8443" />
可以配置主机名称
默认的主机名为:localhost—>127.0.0.1
默认网站应用存放的位置为:webapps
1 2 <Host name ="localhost" appBase ="webapps" unpackWARs ="true" autoDeploy ="true" >
面试题 :请你谈谈网站是如何进行访问的?
输入一个域名,回车
检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有对应这个域名的映射
有,返回对应的ip地址
没有,去DNS服务器进行域名解析,获取ip地址
3.4、发布一个web网站
将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了
网站应该有的结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 --webapps : Tomcat服务器的web目录 -ROOT -webname : 网站的目录名 -WEB-INF -classes : java程序 -lib : web应用所依赖的jar包 -web.xml : 网站的配置文件 -intdex.html 默认的首页 -static -css -style.css -js -img -......
4、Http 4.1、什么是Http 超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP 之上。
文字:html、字符串…
超文本:图片、音乐、视频、地图…
端口号:80
Https:安全的
4.2、两个时代
http1.0
HTTP/1.0:客户端与web服务器连接后,只能获得一个web资源,断开连接
http2.0
HTTP/1.1:客户端与web服务器连接后,可以获得多个web资源。
4.3、Http请求
百度:
1 2 3 4 请求 URL : https ://www.baidu.com/ 请求地址 请求方法: GET get 方法/post 方法 状态代码: 200 OK 状态码 远程地址: 110.242 .68 .4 :443
1 2 3 4 5 Accept: text/html,application/xhtml+xml,application/xml;q=0.9 ,image/webp,image/apng,*
请求行
请求行中的请求方式:GET
请求方式:Get,Post ,HEAD,DELETE,PUT,TRACT…
get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效
消息头
1 2 3 4 5 6 Accept 告诉浏览器,它所支持的数据类型 Accept-Encoding 支持哪种编码格式 GBK、UTF-8 、GB2312、ISO8859-1 Accept-Language 告诉浏览器,它的语言环境 Cache-Control 缓存控制 Connection 告诉浏览器,请求完成是断开,还是保持连接 Host 主机
4.4、Http响应
百度:
1 2 3 4 Cache-Control: private 缓存控制 Connection: keep-alive 连接Content-Encoding: gzip 编码 Content-Type: text/html 类型
1 2 3 4 5 6 7 8 Accept 告诉浏览器,它所支持的数据类型Accept -Encoding 支持哪种编码格式 GBK、UTF-8 、GB2312 、ISO8859 -1 Accept -Language 告诉浏览器,它的语言环境Cache -Control 缓存控制Connection 告诉浏览器,请求完成是断开,还是保持连接Host 主机Refresh 告诉客户端,多久刷新一次Location 让网页重新定位
200:请求响应成功
3xx:请求重定向
4xx:找不到资源(404)
5xx:服务器代码错误 500、网关错误502
面试题 :当浏览器输入地址并回车的一瞬间到页面显示出来,经历了什么?(思考)
5、Maven 为什么要学习Maven这个技术?
在Javaweb开发中,需要使用大量的jar包,手动导入效率低下
Maven——自动导入jar包
5.1、Maven项目架构管理工具 Maven核心思想:约定大于配置
5.2、下载安装Maven 官网:https://maven.apache.org/
下载完成后解压即可
友情建议:电脑所有环境都放在一个文件夹下,方便管理
5.3、配置环境变量 在系统环境变量中,配置如下配置
M2_HOME maven目录下的bin目录
MAVEN_HOME maven的目录
在系统的path中配置 %MAVEN_HOME%\bin
测试Maven是否安装成功,保证必须配置完毕:
5.4、阿里云镜像
1 2 3 4 5 6 7 8 <mirrors > <mirror > <id > aliyunmaven</id > <mirrorOf > central</mirrorOf > <name > aliyun maven</name > <url > https://maven.aliyun.com/repository/public </url > </mirror > </mirrors >
5.5、本地仓库 建立一个本第仓库:localRepository
1 <localRepository > E:\Idea_jars\apache-maven-3.6.3\maven-repo</localRepository >
5.6、在IDEA中使用Maven
启动IDEA
创建一个Maven项目
等待项目初始化完毕
观察maven仓库中多了什么东西
检查IDEA中的Maven设置
注意 :IDEA中配置Maven经常会出现一个问题:自动创建完成后,它这个MAVEN_HOME会使用IDEA默认,如果发现需要手动改为本地
到这里,Maven在IDEA中的配置和使用就OK了
5.7、标记文件夹功能 法一:
法二:
5.8、在IDEA中配置Tomcat
解决警告问题:
5.9、pom文件 pom.xml是Maven的核心配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com.zqy</groupId > <artifactId > javaweb_learn</artifactId > <version > 1.0-SNAPSHOT</version > <packaging > war</packaging > <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <maven.compiler.source > 1.7</maven.compiler.source > <maven.compiler.target > 1.7</maven.compiler.target > </properties > <dependencies > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency > </dependencies > <build > <finalName > javaweb_learn</finalName > <pluginManagement > <plugins > <plugin > <artifactId > maven-clean-plugin</artifactId > <version > 3.1.0</version > </plugin > <plugin > <artifactId > maven-resources-plugin</artifactId > <version > 3.0.2</version > </plugin > <plugin > <artifactId > maven-compiler-plugin</artifactId > <version > 3.8.0</version > </plugin > <plugin > <artifactId > maven-surefire-plugin</artifactId > <version > 2.22.1</version > </plugin > <plugin > <artifactId > maven-war-plugin</artifactId > <version > 3.2.2</version > </plugin > <plugin > <artifactId > maven-install-plugin</artifactId > <version > 2.5.2</version > </plugin > <plugin > <artifactId > maven-deploy-plugin</artifactId > <version > 2.8.2</version > </plugin > </plugins > </pluginManagement > </build > </project >
6、Servlet 6.1、Servlet简介
Servlet就是sun公司开发的一门动态web技术
sun公司在这些API中提供了一些接口叫:Servlet,如果想开发一个Servlet程序,只需要两步:
编写一个类,实现Servlet接口
把开发好的Java类部署到web服务器中
把实现了Servlet接口的Java程序叫做:Servlet
6.2、HelloServlet Servlet接口Sun公司有两个默认实现类:HttpServlet、GenericServlet
编写一个Servlet程序
编写一个普通类
实现Servlet接口,这里我们直接继承HttpServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class HelloServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html" ); resp.setCharacterEncoding("utf-8" ); PrintWriter out = resp.getWriter(); out.println("HttpServlet类" ); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
编写Servlet的映射
为什么需要映射?我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务器中注册我们的Servlet,还需要给他一个浏览器能够访问的路径
配置Tomcat
注意:配置项目发布的路径就可以了
启动测试,OK!
6.3、Servlet原理 Servlet是由Web服务器调用,web服务器在收到浏览器请求后,会:
6.4、Mapping问题
一个Servlet可以指定一个映射路径
1 2 3 4 <servlet-mapping > <servlet-name > helloServlet</servlet-name > <url-pattern > /hello</url-pattern > </servlet-mappng >
一个Servlet可以指定多个映射路径
1 2 3 4 5 6 7 8 9 10 11 12 <servlet-mapping > <servlet-name > helloServlet</servlet-name > <url-pattern > /hello1</url-pattern > </servlet-mappng > <servlet-mapping > <servlet-name > helloServlet</servlet-name > <url-pattern > /hello2</url-pattern > </servlet-mappng > <servlet-mapping > <servlet-name > helloServlet</servlet-name > <url-pattern > /hello3</url-pattern > </servlet-mappng >
一个Servlet可以指定通用映射路径
1 2 3 4 <servlet-mapping > <servlet-name > helloServlet</servlet-name > <url-pattern > /hello/*</url-pattern > </servlet-mappng >
默认请求路径:
1 2 3 4 <servlet-mapping > <servlet-name > helloServlet</servlet-name > <url-pattern > /*</url-pattern > </servlet-mappng >
一个Servlet可以指定一些后缀或者前缀等等…
1 2 3 4 5 6 <servlet-mapping > <servlet-name > helloServlet</servlet-name > <url-pattern > *.do</url-pattern > </servlet-mapping >
优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求
6.5、ServletContext web容器启动时,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用。
共享数据
获取初始化参数
1 2 3 4 5 <context-param > <param-name > url</param-name > <param-value > jdbc:mysql://localhost:3306/mybatis</param-value > </context-param >
1 2 3 4 5 6 @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this .getServletContext(); String url = context.getInitParameter("url" ); resp.getWriter().print(url); }
请求转发
1 2 3 4 5 6 7 @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this .getServletContext(); context.getRequestDispatcher("/hello" ).forward(req,resp); }
读取资源文件
Properties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <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 >
在resources目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath(类路径)
思路:需要一个文件流
1 2 username =root password =123456
1 2 3 4 5 6 7 8 9 10 11 @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this .getServletContext(); InputStream is = context.getResourceAsStream("/WEB-INF/classes/db.properties" ); Properties prop = new Properties(); prop.load(is); String user = prop.getProperty("username" ); String pwd = prop.getProperty("password" ); resp.getWriter().print(user+":" +pwd); }
6.6、HttpServletResponse web服务器接收到客户端的http请求,针对每个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse对象;
如果要获取客户端请求过来的参数:找HttpServletRequest
如果要给客户端响应一些信息:找HttpServletResponse
1、简单分类
负责向浏览器发送数据的方法
1 2 ServletOutputStream getOutputStream () throws IOException ;PrintWriter getWriter () throws IOException ;
向浏览器发送响应头的方法
1 2 3 4 5 6 7 8 9 10 11 void setCharacterEncoding (String var1) ;void setContentLength (int var1) ;void setContentLengthLong (long var1) ;void setContentType (String 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) ;
响应的状态码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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、常见应用
向浏览器输出信息
下载文件
获取下载文件路径
下载的文件名
设置浏览器支持下载
获取下载文件的输入流
创建缓冲区
获取OutputStream对象
将FileOutputStream流写入到缓冲区(buffer)
使用OutputStream将缓冲区中的数据输出到客户端!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String realPath = "E:\\java课设参考文件\\javaweb_learn\\src\\main\\resources\\头像.jpg" ; System.out.println("下载文件的路径为:" +realPath); String fileName = realPath.substring(realPath.lastIndexOf("\\" )+1 ); resp.setHeader("Content-disposition" ,"attachment;filename" + URLEncoder.encode(fileName,"utf-8" )); FileInputStream in = new FileInputStream(realPath); int len = 0 ; byte [] buffer = new byte [1024 ]; ServletOutputStream outputStream = resp.getOutputStream(); while ((len = in.read(buffer)) != -1 ){ outputStream.write(buffer,0 ,len); } in.close(); outputStream.close(); }
3、验证码功能 验证怎么来的?
前端实现
后端实现,需要java的图片类,生成一个图片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setHeader("refresh" ,"3" ); BufferedImage image = new BufferedImage(80 ,20 ,BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D)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(randNum(),0 ,20 ); resp.setContentType("image/jpg" ); resp.setDateHeader("expires" ,-1 ); resp.setHeader("Cache-Control" ,"no-cache" ); resp.setHeader("Pragma" ,"no-cache" ); ImageIO.write(image,"jpg" , resp.getOutputStream()); } private String randNum () { StringBuilder str = new StringBuilder(); Random random = new Random(); for (int i = 0 ; i < 7 ; i++) { str.append(random.nextInt(10 )); } return str.toString(); }
4、实现重定向 一个web资源收到客户端请求后,它会通知客户端去访问另外一个web资源,这个过程叫重定向
常见场景:
1 void sendRedirect (String var1) throws IOException ;
测试:
1 2 3 4 5 6 7 8 @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect("/zqy/header.jsp" ); }
面试题:请你聊聊重定向和转发的区别?
相同点:都会实现页面跳转
不同点:请求转发的时候,url不会发生跳转 307;重定向的时候url地址栏会变化 302
6.7、HttpServletRequest HttpServletRequest代表客户端的请求,用户通过Http访问服务器,Http请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,可以获得客户端的所有信息
1、获取参数、请求转发 1 2 3 4 String getParameter (String var1) ;Enumeration<String> getParameterNames () ;String[] getParameterValues(String var1); Map<String, String[]> getParameterMap();
其中getParameter() 和 getParameterValues() 重点记忆
登录示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <body> <h2>登录界面</h2> <%--这里提交的路径,需要寻找到项目的路径--%> <%--${pageContext.request.contextPath}代表当前的项目--%> <div> <%--这里表单表示的意思:以get方式提交表单,提交到我们的login请求--%> <form action="${pageContext.request.contextPath}/login" method="get" > 用户名:<input type="text" name="username" ><br> 密码:<input type="password" name="password" ><br> 爱好: <input type="checkbox" name="hobbys" value="女孩" >女孩 <input type="checkbox" name="hobbys" value="吉他" >吉他 <input type="checkbox" name="hobbys" value="网球" >网球 <input type="checkbox" name="hobbys" value="金币" >金币 <br> <input type="submit" > </form> </div> </body> </html>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @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 pwd = req.getParameter("password" ); String[] hobbys = req.getParameterValues("hobbys" ); System.out.println(username); System.out.println(pwd); System.out.println(Arrays.toString(hobbys)); System.out.println(req.getContextPath()); req.getRequestDispatcher("./header.jsp" ).forward(req,resp); }
7、Cookie、Session 7.1、Session会话 会话 :用户打开一个浏览器,点了很多超链接,访问多个web资源,关闭浏览器,这个过程称之为会话
有状态会话 :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
7.2、保存会话的两种技术 Cookie与Session是Web程序中用来跟踪用户的整个会话常用的两个技术
Cookie通过在客户端记录信息确定用户身份
Session通过在服务器端记录信息确定用户身份
7.3、Cookie
从请求中拿到cookie信息
服务器相应给客户端cookie
1 2 3 4 5 6 Cookie[] cookies = req.getCookies(); cookie.getName() cookie.getValue() new Cookie("lastLoginTime" , System.currentTimeMillis() + "" ); cookie.setMaxAge(24 *60 *60 ); resp.addCookie(cookie);
tips:Cookie一般保存在本地用户目录下的appdata
一个网站的Cookie是否存在上限?
浏览器一般只允许存放300个Cookie
一个web站点最多存放20个cookie
Cookie大小有限制,最多4kb
一个Cookie只能保存一个信息
删除Cookie:
不设置有效期,关闭浏览器,自动失效
设置有效期为0
中文乱码可以考虑的解决方式:编码解码
1 2 URLEncoder.encode("雷克萨" ,"utf-8" ) URLDecoder.decode(cookie.getValue(),"utf-8" );
7.4、Session(重点)
什么是Session?
服务器会给每一个用户(浏览器)创建一个Session对象
一个Session独占一个浏览器,只要浏览器没关,这个Session就存在
用户登录后,保存用户的信息
Session和Cookie的区别:
使用场景:
保存一个登录用户的信息
购物车信息
在整个网站中经常会使用的数据,我们将它保存在Session中
使用Session:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Override 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(); session.setAttribute("name" ,"雷克萨" ); String id = session.getId(); if (session.isNew()){ resp.getWriter().write("session创建成功,ID为:" +id); }else { resp.getWriter().write("session已经存在了,ID为:" +id); } } HttpSession session = req.getSession(); Person person = (Person)session.getAttribute("name" ); System.out.println(person.toString()) HttpSession session = req.getSession(); session.removeAttribute("name" ) session.invalidate();
会话自动过期,web.xml配置
1 2 3 4 <session-config > <session-timeout > 1</session-timeout > </session-config >
8、JSP 8.1、什么是JSP Java Server Pages:Java服务器端页面,也和Servlet一样,用于动态Web技术
最大的特点:写Jsp就像写Html
区别:
Html只给用户提供静态的数据
Jsp页面可以嵌入Java代码,为用户提供动态数据
8.2、Jsp原理 思路:Jsp到底是如何执行的?
我电脑的地址:
1 C:\Users\86138 \.IntelliJIdea2019.3 \system\tomcat\Unnamed_javaweb_learn_4\work\Catalina\localhost\zqy\org\apache\jsp
发现页面转成了Java程序
浏览器向服务器发起请求,不管访问什么资源,其实都是在访问Servlet!
Jsp最终会被转为一个Java类,本质上就是一个Servlet
1 2 3 4 5 6 public void _jspInit () {}public void _jspDestroy () {}public void _jspService (final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) {...}
判断请求
内置一些对象
1 2 3 4 5 6 7 8 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 ; HttpServletRequest request; HttpServletResponse response;
输出页面前增加的代码:
1 2 3 4 5 6 7 8 response.setContentType("text/html;charset=UTF-8" ); 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中直接使用
在Jsp页面中,只要是Java代码,就会原封不动的输出,如果是Html代码,就会转换为
这样的格式,输出到前端!
8.3、Jsp基础语法 Jsp作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可),支持Java的所有语法
Jsp表达式 1 2 <%-- JSP表达式,作用:将程序输出到客户端<%= 变量或者表达式%> --%> <%= new java.util.Date()%>
Jsp脚本片段 1 2 3 4 5 6 7 8 <%--Jsp脚本片段:--%> <% int sum = 0; for (int i = 0; i <= 100; i++) { sum += i; } out.println("<h1 > Sum="+sum+"</h1 > "); %>
脚本片段的再实现 1 2 3 4 5 6 7 <% for (int i = 0 ; i < 5 ; i++) { %> <h1>Hello World <%=i%></h1> <% } %>
Jsp声明
Jsp声明:会被编译到Jsp生成的Java类中!其他的就会被生成_jspService方法中!
综上,在Jsp中嵌入Java代码即可
1 2 3 4 5 <%%> <%=%> <%!%> <%--注释--%>
Jsp的注释不会在客户端显示,而Html的注释<!—- >当查看源代码时会显示出来
8.4、Jsp指令 1 2 3 4 5 6 7 8 9 10 11 12 <%@ page args ...%> <%@ include file="" %> <%--include会将两个页面合二为一--%> <%@include file="common/header.jsp" %> <h1>网页主体</h1> <%@include file="common/footer.jsp" %> <%--jsp标签,jsp:include:拼接页面,本质还是三个--%> <jsp:include page="common/header.jsp" /> <h1>网页主体</h1> <jsp:include page="common/footer.jsp" />
8.5、九大内置对象
PageContext 存东西
Request 存东西
Response
Session 存东西
Application【ServletContext】 存东西
config【ServletConfig】
out
page 不用了解
exception
demo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <% pageContext.setAttribute("name1" ,"雷克萨1号" ); request.setAttribute("name2" ,"雷克萨2号" ); session.setAttribute("name3" ,"雷克萨3号" ); application.setAttribute("name4" ,"雷克萨4号" ); %> <% 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表达式输出 ${}--%> <h1>保存的值为:</h1> <h3>${name1}</h3> <h3>${name2}</h3> <h3>${name3}</h3> <h3>${name4}</h3> <h3>${name5}</h3> <%--什么也不输出--%> <h3><%= name5%></h3> <%--会输出null--%>
request:客户端向服务端发送请求,产生的数据,用户看完就没用了,比如新闻
session:客户端向服务端发送请求,产生的数据,用户看完一会还有用,比如购物车
application:客户端向服务端发送请求,产生的数据,一个用户用完其他用户还可能用,比如聊天数据
8.6、Jsp标签,Jstl标签,EL表达式 需要导包:
1 2 3 4 5 6 7 8 9 10 11 12 <dependency > <groupId > javax.servlet.jsp.jstl</groupId > <artifactId > jstl-api</artifactId > <version > 1.2</version > </dependency > <dependency > <groupId > taglibs</groupId > <artifactId > standard</artifactId > <version > 1.1.2</version > </dependency >
EL表达式:${ }
获取数据
执行运算
获取web开发的常用对象
调用java方法
Jsp标签 :
1 2 3 4 5 6 <%-- <jsp:include > --%> <jsp:forward page ="jsp1.jsp" > <jsp:param name ="name" value ="雷克萨" /> <jsp:param name ="age" value ="12" /> </jsp:forward >
Jstl表达式
Jstl标签库的使用就是为了弥补Html标签的不足,它自定义了许多标签,标签的功能和java一样
核心标签 (掌握部分)
引用核心标签库的语法如下:
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Jstl标签库使用步骤
引入对应的taglib
使用其中的方法
在Tomcat也需要引入jstl包,否则会报错:Jstl解析错误
c:if 测试
1 2 3 4 5 6 7 8 9 10 11 12 13 <h4>if 测试</h4> <form action="/index.jsp" method="get" > <%--EL表达式获取表单中的数据:${param .参数名}}--%> <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}" />
c:choose测试
1 2 3 4 5 6 7 8 9 <c:set var ="score" value="88" /> <c:choose> <c:when test="${score>=90}" > 你的成绩为优秀 </c:when> <c:when test="${score>=80}" > 你的成绩为优秀 </c:when> </c:choose>
c:forEach测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <% ArrayList<String> people = new ArrayList<>(); people.add("张三" ); people.add("李四" ); people.add("王五" ); people.add("赵六" ); people.add("田七" ); request.setAttribute("list" ,people); %> <%-- var :每一次遍历出来的变量 items:要遍历的对象 begin:开始下标 end:结束下标 step:步长 --%> <c:forEach var ="people" items="${list}" begin="1" end="3" step="1" > <c:out value="${people}" /><br> </c:forEach>
格式化标签
JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:
1 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
SQL标签
JSTL SQL标签库提供了与关系型数据库(Oracle,MySQL,SQL Server等等)进行交互的标签。引用SQL标签库的语法如下:
1 <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
XML 标签
JSTL XML标签库提供了创建和操作XML文档的标签。引用XML标签库的语法如下:
1 <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
JSTL函数
JSTL包含一系列标准函数,大部分是通用的字符串处理函数。引用JSTL函数库的语法如下:
1 <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
9、JavaBeen 实体类
Javabeen有特定的写法:
必须要有一个无参构造
属性必须私有化
必须有get/set方法
一般用来和数据库的字段做映射 ORM(对象关系映射)
比如people表:
id
name
age
address
1
雷克萨
18
金星
2
巫妖王
100
木星
3
恶魔猎手
3
土星
1 2 3 4 5 6 class People { private int id; private String name; private int age; private String address; }
10、MVC架构 什么是MVC:Model View Controller 模型 、视图、控制器
10.1、早期
用户可以直接访问控制层,控制层就可以直接操控数据库
servlet——>CRUD——>数据库
servlet代码中:要处理请求、响应,视图跳转、处理JDBC、处理业务代码、处理逻辑代码
弊端:程序十分臃肿,不利于维护
架构:没有什么是加一层解决不了的!
10.2、MVC三层架构 Model
业务处理:业务逻辑(Service)
数据持久层:CRUD(Dao)
View
展示数据
提供链接发起Servlet请求(a,form,img)
Controller(Servlet)
接收用户的请求(req:请求参数,Session信息……)
交给业务层处理对应的代码
控制视图跳转
用户登录——>接收用户请求——>处理用户请求(获取用户登录的参数,username,password)——>交给业务层处理业务(验证用户名和密码是否正确:事务)——>Dao层查询——>数据库
11、Filter(重点) Filter:过滤器,用来过滤网站的数据
Filter开发步骤:
导包
编写过滤器
导包不要错
2. 实现Filter接口,重写对应方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Override public void init (FilterConfig filterConfig) throws ServletException { System.out.println("初始化" ); } @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;charse=utf-8" ); System.out.println("过滤器执行前" ); filterChain.doFilter(servletRequest,servletResponse); System.out.println("过滤器执行后" ); } @Override public void destroy () { System.out.println("销毁" ); }
3. 在web.xml中配置Filter
1 2 3 4 5 6 7 8 9 <filter > <filter-name > CharacterEncodingFilter</filter-name > <filter-class > filter.CharacterEncodingFilter</filter-class > </filter > <filter-mapping > <filter-name > CharacterEncodingFilter</filter-name > <url-pattern > /servlet/*</url-pattern > </filter-mapping >
12、监听器 实现一个监听器的接口(有N种)
编写一个监听器的接口
实现监听器的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Override public void sessionCreated(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); Integer num = (Integer) ctx.getAttribute("OnlineCount" ); if (num == null ){ num = 1 ; }else { num += 1 ; } ctx.setAttribute("OnlineCount" ,num ); } @Override public void sessionDestroyed(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); Integer num = (Integer) ctx.getAttribute("OnlineCount" ); if (num == null ){ num = 0 ; }else { num -= 1 ; } ctx.setAttribute("OnlineCount" ,num ); }
web.xml中注册监听器
1 2 3 <listener > <listener-class > listener.OnlineCountListener</listener-class > </listener >
看情况使用
13、过滤器、监听器常见应用 监听器:GUI编程中经常使用
demo:用户登录后才能进入主页,用户注销后不能。
用户登入以后,向Session中放入用户的数据
进入主页的时候,要判断用户是否已经登入,要求在过滤器中实现
1 2 3 4 5 6 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; if (request.getSession().getAttribute("USER_SESSION" ) == null ){ response.sendRedirect("/error.jsp" ); } chain.doFilter(req,resp);
14、JDBC 什么是JDBC:java连接数据库(java database connectivity)
需要jar包的支持:
java.sql
Javax.sql
mysql-connector-java连接驱动(必须要导入)
1 2 3 4 5 6 <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.23</version > </dependency >
JDBC六大步骤:
加载驱动
获取连接
获得执行命令
执行
结果处理
释放资源(关闭资源)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 private static final String CLASSDRIVER="com.mysql.cj.jdbc.Driver" ;private static final String URL="jdbc:mysql://127.0.0.1:3306/test?" ;private static final String USERNAME="root" ;private static final String PASSWORD="qingyang1234" ;public static void main (String[] args) throws ClassNotFoundException, SQLException { Class.forName(CLASSDRIVER); Connection conn = DriverManager.getConnection(URL,USERNAME,PASSWORD); Statement stat = conn.createStatement(); String sql = "select * from emp" ; ResultSet rs = stat.executeQuery(sql); while (rs.next()){ System.out.println(rs.getString("ename" )+"\t" +rs.getString("sal" )); } rs.close(); stat.close(); conn.close(); }
事务
一句话:要么都成功,要么都失败
ACID原则,保证数据的安全
开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务
Junit单元测试
依赖
1 2 3 4 5 <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > </dependency >
简单使用
@Test注解只有在方法上有效,只要加了注解,就可以直接运行