本文最后编辑于 前,其中的内容可能需要更新。
基本概念 前言 web开发:
web,网页的意思,www.baidu.com
静态web
html,css
提供给所有人看的数据始终不会发生变化!
动态web
淘宝,几乎所有的网站
提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同
技术栈:Servlet/JSP,ASP,PHP
在java中,动态web资源开发的技术统称为javaWeb
web应用程序 web应用程序,可以提供浏览器访问的程序:
a.html、b.html……多个web资源,这些web资源可以被外界访问,对外界提供服务
我们能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上
URL
这个统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat:服务器
一个web应用由多部分组成(静态web,动态web)
html,css,js
jsp,servlet
java程序
jar包
配置文件(Properties)
web应用程序编写完毕后,若想提供给外界访问,需要一个服务器来统一管理
静态web
*.htm, *.html这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取,同学
静态web存在的缺点
web页面无法动态更新,所有用户看到的都是同一个页面
轮播图,点击特性:伪动态
javaScript [实际开发中,用的最多]
VBScript
它无法和数据库交互(数据无法持久化,用户无法交互)
动态web
页面会动态展示:”web的页面展示的效果因人而异“
缺点
加入服务器的动态web资源出现错误,我们需要重新编写我们的后台程序
优点:
web页面可以动态更新,所有用户看到的都不是同一个页面
它可以和数据库交互(数据持久化:注册,商品信息,用户信息)
web服务器 技术讲解 ASP:
微软:国内最早流行的就是ASP
在HTML中嵌入了VB的脚本,ASP+COM
在ASP开发中,基本一个页面都有几千行的业务代码,页面极其混乱
维护成本高
C#
IIS
PHP
PHP开发速度很快,功能很强大,跨平台,代码很简单(70%,WP)
无法承载大访问量的情况(局限性)
JSP/Servlet B/S:浏览器和服务器
C/S:客户端和服务器
sun公司主推的B/S架构
基于java语言的(所有的大公司,或者一些开源的组件,都是用java写的)
可以承载三高问题带来的影响
语法像ASP
web服务器 服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息
IIS 微软的,ASP…,Windowss中自带的
Tomcat 面向百度编程
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,因为Tomcat 技术先进、性能稳定,而且免费 ,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器 ,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个java初学web的人来说,它是最佳的选择
Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS 等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML 的能力不如Apache服务器。Tomcat最新版本为10.0.14。
下载tomcat:
安装 or 解压
了解配置文件及目录结构
这个东西的作用
Tomcat 安装Tomcat tomcat官网:https://tomcat.apache.org/
Tomcat启动 文件夹作用
启动,关闭Tomacat
访问测试:http://localhost:8080/
可能遇到的问题:
java环境变量没有配置
闪退问题:需要配置兼容性
可在startup.bat最后加上pause,再启动即可显示原因
乱码问题:配置文件中设置
配置
可以配置启动的端口号
tomcat的默认端口号为:8080
mysql:3306
http:80
https:443
1 2 3 <Connector port ="8081" 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地址,这个地址中,有我们需要访问的web程序,可以直接访问
没有:去DNS服务器找,找到的化就返回,找不到就返回找不到
发布一个web网站 将自己写的网站,放大服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了
网站应该有的结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 --webapps : Tomcat服务器的web目录 -Root -xcwStudy :网站的目录名 - WEB-INF -classes :java程序 -lib :web应用程序所依赖的jar包 -web.xml :网站配置文件 - index.html 默认的首页 - static -css -style.css -js -img -...
HTTP 什么是HTTP HTTP (超文本传输协议) 是一个简单的请求-响应协议,它通常运行在TCP 之上。
文本:html、字符串、…
超文本:图片、音乐、视频、定位、地图….
80
https:安全的
两个时代
http1.0
HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
http2.0
HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源
HTTP请求
百度:
1 2 3 4 Request URL: https://www.baidu.com/ 请求地址 Request Method: GET get方法/post方法 Status Code: 200 OK 状态码 Remote(远程)Address: 110.242.68.4:443
1 2 3 4 Accept:image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8 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 语言 Connection: keep-alive
请求行
请求行中的请求方式: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:主机.../.
HTTP响应
百度:
1 2 3 4 Cache-Control: no-cache 缓存控制 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:网关错误
常见面试题: 当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?
Maven 为什么要学习这个技术?
在javaweb开发中,需要使用大量的jar包,我们手动去导入
如何能够让一个东西自动帮我导入和配置这个jar包
由此,Maven诞生了
Maven项目架构管理工具 我们目前用来就是方便导入jar包的
Maven的核心思想:约定大于配置
Maven会规定号你该如何去编写我们的java代码,必须要按照这个规范来
下载安装Maven 官网:https://maven.apache.org/
配置参考博客 :maven的安装和配置(包括配置环境变量,镜像,本地仓库,jdk)_机智大头-CSDN博客_阿里云仓库配置
配置环境变量 在我们的系统环境变量中
配置如下配置:
M2_HOME maven目录下的bin目录
MAVEN_HOME maven的目录
在系统的path中配置 %MAVEN_HOME%\bin
测试Maven是否安装成功,保证必须配置完毕
报错:The JAVA_HOME environment variable is not defined correctly
maven配置报错以及The JAVA_HOME environment variable is not defined correctly的解决方法_cms18374672699的博客-CSDN博客
阿里云镜像
1 2 3 4 5 6 <mirror > <id > alimaven</id > <mirrorOf > central</mirrorOf > <name > aliyun maven</name > <url > http://maven.aliyun.com/nexus/content/repositories/central/</url > </mirror >
本地仓库 在本地的仓库,远程仓库
建立一个本地仓库 :localRepository
1 <localRepository>E:\Java\apache-maven-3.8.4-bin\apache-maven-3.8.4\maven-repo</localRepository>
在IDEA中使用Maven
打开idea
创建一个Maven项目
等待系统初始化完毕
观察maven仓库中多了什么东西?
IDEA中的Maven设置
注意:IDEA项目创建成功后,看一眼Maven的配置
到这里,Maven在IDEA中的配置和使用就ok了
创建一个普通的Maven项目
这个只有在Web应用下才会有!
标记文件夹功能
在IDEA中配置Tomcat 社区版IDEA配置Tomcat:Java 在IDEA社区版中配置Tomcat并使用_weixin_44953227的博客-CSDN博客_社区版idea配置tomcat
启动Tomact
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 76 <?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.xcw</groupId > <artifactId > javaweb-01-maven</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-01-maven</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 >
Maven由于它的约定大于配置,之后可能遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <build > <resources > <resource > <directory > src/main/resources</directory > <excludes > <exclude > **/*.properties</exclude > <exclude > **/*.xml</exclude > </excludes > <filtering > false</filtering > </resource > <resource > <directory > src/main/java</directory > <includes > <include > **/*.properties</include > <include > **/*.xml</include > </includes > <filtering > false</filtering > </resource > </resources > </build >
解决遇到的问题 maven默认web项目中的web.xml版本问题
替换为webapp5.0版本和tomact一致
重复配置maven问题
maven仓库的使用 地址:https://mvnrepository.com/
Servlet 简介
Servlet就是sun公司开发动态web的一门技术
sun在这些API中提供了一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
编写一个类,实现Servlet接口
把开发好的java类部署到web服务器中
把实现了Servlet接口的java程序叫做:Servlet
HelloServlet Serlvet接口Sun公司有两个默认的实现类:HttpServlet,GenericServlet
构建一个普通的Maven项目,删掉里面的src目录,以后的学习可以在这个项目里建立Moudel;这个空的工程就是Maven主工程
关于Maven父子工程的理解:
父项目中会有
1 2 3 <modules > <module > servlet-01</module > </modules >
子项目中会有
1 2 3 4 5 <parent > <artifactId > javaweb-02-maven</artifactId > <groupId > com.xcw</groupId > <version > 1.0-SNAPSHOT</version > </parent >
父项目中的jar子项目可以直接使用
Maven环境优化
修改web.xml为最新的
1 2 3 4 5 6 7 8 9 10 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version ="4.0" metadata-complete ="true" > </web-app >
将maven的结构搭建完整
编写一个Servlet程序
编写一个普通类
实现Servlet接口,这里我们直接继承HttpServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class HelloServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.print("Hello,Serlet" ); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
编写Servlet的映射
为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给它一个浏览器能够访问的路径;
1 2 3 4 5 6 7 8 9 10 <servlet > <servlet-name > hello</servlet-name > <servlet-class > com.xcw.HelloServlet</servlet-class > </servlet > <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > /hello</url-pattern > </servlet-mapping >
配置Tomcat
注意:配置项目发布的路径就可以了
启动测试
Servlet原理 Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
Mapping问题
一个Servlet可以指定一个映射路径
1 2 3 4 <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > /hello</url-pattern > </servlet-mapping >
一个Servlet可以指定多个映射路径
1 2 3 4 5 6 7 8 9 10 11 12 <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > /hello</url-pattern > </servlet-mapping > <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > /hello1</url-pattern > </servlet-mapping > <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > /hello2</url-pattern > </servlet-mapping >
一个Servlet可以指定通用映射路径
1 2 3 4 <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > /hello/*</url-pattern > </servlet-mapping >
默认请求路径
1 2 3 4 5 <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > /*</url-pattern > </servlet-mapping >
指定一些后缀或者前缀等等….
1 2 3 4 5 6 7 8 <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > *.xingchuwu</url-pattern > </servlet-mapping >
优先级问题
指定了固有的映射路径优先级最高,如果找不到就会由默认的处理请求
ServletContext web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用
共享数据 我在这个Servlet中保存的数据,可以在另外一个servlet中拿到
1 2 3 4 5 6 7 8 9 10 public class HelloServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this .getServletContext(); String username = "行初雾" ; servletContext.setAttribute("username" ,username); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class GetServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this .getServletContext(); String username = (String)context.getAttribute("username" ); resp.setContentType("text/html" ); resp.setCharacterEncoding("utf-8" ); resp.getWriter().print("名字:" +username); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <servlet > <servlet-name > hello</servlet-name > <servlet-class > com.xcw.servlet.HelloServlet</servlet-class > </servlet > <servlet-mapping > <servlet-name > hello</servlet-name > <url-pattern > /hello</url-pattern > </servlet-mapping > <servlet > <servlet-name > getc</servlet-name > <servlet-class > com.xcw.servlet.GetServlet</servlet-class > </servlet > <servlet-mapping > <servlet-name > getc</servlet-name > <url-pattern > /getc</url-pattern > </servlet-mapping >
测试访问结果
获取初始化参数 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 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 8 9 protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this .getServletContext(); System.out.println("进入了ServletDemo04" ); context.getRequestDispatcher("/gp" ).forward(req,resp); }
读取资源文件 Properties
在java目录下新建properties
在resources目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath
思路:需要一个文件流
1 2 username =xingchuwu password =123456
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class ServletDemo05 extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream is = this .getServletContext().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); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
测试访问结果
HttpServletResponse web服务器接受到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,和一个代表响应的HttpServletResponse
如果要获取客户端请求过来的参数:找HttpServletRequest
如果要给客户端响应一些信息:找HttpServletResponse
简单分类 负责向浏览器发送数据的方法
1 2 3 ServletOutputStream getOutputStream () throws IOException ;PrintWriter getWriter () throws IOException ;
负责向浏览器发送响应头的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void setCharacterEncoding (String var1) ;void setContentLength (int var1) ;void setContentLengthLong (long var1) ;void setContentType (String var1) ;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 ;
下载文件
要获取下载文件的路径
下载的文件名是啥?
设置想办法让浏览器能够支持下载我们需要的东西
获取下载文件的输入流
创建缓冲区
获取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:\\javadProgram\\javaweb\\javaweb-02-maven\\response\\target\\response-1.0-SNAPSHOT\\WEB-INF\\classes\\1.png" ; 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 out = resp.getOutputStream(); while ((len = in.read(buffer))>0 ){ out.write(buffer,0 ,len); } in.close(); out.close(); }
验证功能 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 public class ImageServlet extends HttpServlet { @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(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; } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
实现重定向
一个web资源(B)收到客户端A请求后,B会通知客户端(A)去访问另外一个web资源(C),这个过程叫重定向
常见场景:
1 void sendRedirect (String var1) throws IOException ;
测试
1 2 3 4 5 6 7 protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect("/r/img" ); }
面试题:请你聊聊重定向和转发的区别?
相同的
不同点
请求转发的时候,url不会产生变化
重定向的时候,url地址栏会发生变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class RequestTest extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username" ); String password = req.getParameter("password" ); System.out.println(username+":" +password); resp.sendRedirect("/r/success.jsp" ); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
1 2 3 4 5 6 7 8 9 10 11 12 <html> <body> <h2>Hello World!</h2> <form action="${pageContext.request.contextPath}/login" method="get" > 用户名:<input type="text" name="username" > <br> 密码:<input type="password" name="password" > <br> <input type="submit" > </form> </body> </html>
1 2 3 4 5 6 <html> <body> <h2>Success</h2> </form> </body> </html>
HttpServletRequest
获取前端传递的参数,请求转发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class LoginServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8" ); String username = req.getParameter("username" ); String password = req.getParameter("password" ); String[] hobbys = req.getParameterValues("hobbys" ); System.out.println("===============" ); System.out.println(username); System.out.println(password); System.out.println(Arrays.toString(hobbys)); System.out.println("===============" ); req.getRequestDispatcher("/success.jsp" ).forward(req,resp); } @Override protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
Cookie、Session 会话 会话 :用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话
有状态会话 :一个同学来过教室,下次再来教师,我们会知道这个同学,曾经来过,称之为有状态会话
一个网站,怎么证明你来过?
客户端 服务端
服务端给客户端一个信件,客户端下次访问服务器带上信件就可以了;cookie
服务器登记你来过了,下次你来的时候我来匹配你;sesion
保存会话的两种技术 cookie
session
服务器技术,利用这个技术,可以保存用户的会话信息,我们可以把信息或数据放在Session中
常见案例:网站登录之后,下次不用再登陆了,第二次访问直接就上去了
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);
cookie:一般会保存至本地的 用户目录下 appdata
一个网站cookie存在上限
一个Cookie只能保存一个信息
一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
Cookie大小有限制4kb
300个cookie浏览器上限
删除cookie
不设置有效期,关闭浏览器,自动失效
设置有效期时间为0
编码解码:
1 2 URLEncoder.encode("行初雾","utf-8") URLDecoder.decode(cookie.getValue(),"utf-8")
Session(重点)
什么是Session:
服务器会给每一个用户(浏览器)创建一个Session对象
一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
用户登录之后,整个网站它都可以访问!..>保存用户的信息;保存购物车信息…
Session和Cookie的区别:
Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
Session把用户的数据写到用户独占Session中服务器端保存(保存重要的信息,减少服务器资源的浪费)
Session对象由服务器创建
使用场景:
保存一个登录用户的信息
购物车信息
在整个网站中经常会使用的数据,我们将保存在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 30 31 32 33 34 35 36 37 38 39 40 41 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.setContentType("text/html;charset=utf-8" ); HttpSession session = req.getSession(); session.setAttribute("name" ,new Person("行初雾" ,22 )); String sessionId = session.getId(); 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); } } 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 5 <session-config > <session-timeout > 15</session-timeout > </session-config >
JSP 什么是JSP Java Server Pages:java服务器端页面,也和Servlet一样,用于动态web技术!
最大的特点:
写JSP就像在写HTML
区别
HTML只给用户提供静态的数据
JSP页面中可以嵌入JAVA代码,为用户提供动态数据
JSP原理 思路:JSP到底怎么执行的
tomcat中有一个work目录
IDEA中使用Tomcat的会在IDEA的tomcat中生产一个work目录
我电脑的地址为:
1 C:\Users\10923\AppData\Local\JetBrains\IntelliJIdea2021.2\tomcat\12c51b42-bf99-464e-af4f-a79ba8bc2230\work\Catalina\localhost\ROOT\org\apache\jsp
发现页面转变成了Java程序
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet
JSP最终也会被转换成一个Java类
JSP本质上就是一个Servlet
1 2 3 4 5 6 7 8 //初始化 public void _jspInit() { } //销毁 public void jspDestroy() { } //JSPService public void _jspService(HttpServletRequest var1, HttpServletResponse var2)
判断请求
内置一些对象
1 2 3 4 5 6 7 8 final javax.servlet.jsp.PageContext pageContext; //页面上下文 javax.servlet.http.HttpSession session = null; //session final javax.servlet.ServletContext application; //application context final javax.servlet.ServletConfig config; //config javax.servlet.jsp.JspWriter out = null; //out final java.lang.Object page = this; //当前页 HttpServletRequest request //请求 HttpServletResponse response //响应
输出页面前增加的代码
1 2 3 4 5 6 7 8 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页面中直接使用
在JSP页面中
只要是JAVA代码就会被原封不动的输出
如果是HTML代码,就会被转换为:
这样的格式,输出到前端
JSP基本语法 任何语言都有自己的语法,JAVA中有。。JSP作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),java所以语法都支持!
JSP表达式 1 2 3 4 5 <%-- 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 8 <%--在代码中嵌入HTML元素--%> <% for (int i = 0 ; i < 5 ; i++) { %> <h1>Hello,World <%=i%></h1> <% } %>
JSP声明 1 2 3 4 5 6 7 8 9 10 <%! static { System.out.println("Loading Servlet!" ); } private int globalvar = 0 ;public void xcw () { System.out.println("进入了方法xcw!" ); } %>
JSP声明:会被编译到JSP生成的java的类中,其他的就会被生成到_jspService方法中!
再JSP,嵌入java代码即可
1 2 3 4 5 <%%> <%=%> <%!%> <%--注释-->
JSP指令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <%@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" />
9大内置对象
PageContext 存东西
Request 存东西
Response
Session 存东西
Application 【SerlvetContext】 存东西
config 【SerlvetConfig】
out
page ,不用了解
exception
1 2 3 4 pageContext.setAttribute("name1" ,"行初雾1号" ); request.setAttribute("name2" ,"行初雾2号" ); session.setAttribute("name3" ,"行初雾3号" ); application.setAttribute("name4" ,"行初雾4号" );
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!
session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据
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表达式:${ }
JSP标签:
1 2 3 4 5 6 <%--jsp:include--%> <jsp:forward page="jsptag2.jsp" > <jsp:param name="name" value="xingchuwu" /> <jsp:param name="age" value="23" /> </jsp:forward>
JSTL标签:
JSTL标签库的使用就是为了弥补HTML标签的不足;他自定义许多标签,可以供我们使用,标签的功能和java代码一样!
格式化标签
SQL标签
XML标签
核心标签(掌握部分)
JSTL标签库使用步骤:
引入对应的taglib
使用其中的方法
在Tomcat也需要引入jstl的包,否则会报错:JSTL解析错误
c:if
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <body > <h4 > if测试</h4 > <hr > <form action ="coreif.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}" /> </body >
c:when
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <body> <%--定义一个变量score,值为85 --%> <c:set var ="score" value="85" /> <c:choose> <c:when test="${score>=90}" > 你的成绩为优秀 </c:when> <c:when test="${score>=80}" > 你的成绩为良好 </c:when> <c:when test="${score>=60}" > 你的成绩为及格 </c:when> <c:when test="${score<60}" > 你的成绩为不及格 </c:when> </c:choose> </body>
c:forEach
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 <body> <% List<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 ="people" items="${list}" > <c:out value="${people}" /> <br> </c:forEach> <hr> <c:forEach var ="people" items="${list}" begin="1" end="3" step="2" > <c:out value="${people}" /> <br> </c:forEach> </body>
JavaBean 实体类
JavaBean有特定的写法:
必须要有一个无参构造
属性必须私有化
必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM
ORM:对象关系映射
People表
id
name
age
address
1
行初雾1号
18
邯郸
2
行初雾2号
20
西安
3
行初雾3号
23
西安
1 2 3 4 5 6 7 8 9 10 11 12 class People { private int id; private String name; private int age; private String address; } class A { new People(1 ,"行初雾1号" ,18 ,"邯郸" ); new People(2 ,"行初雾2号" ,20 ,"西安" ); new People(3 ,"行初雾3号" ,23 ,"西安" ); }
MVC三层架构 什么是MVC:Model View Controller 模型、视图、控制器
早期
用户直接访问控制器,控制器就可以直接操作数据库
1 2 3 4 5 6 7 8 9 10 servlet--CRUD-->数据库 弊端:程序十分臃肿,不利于维护 servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码 架构:没有什么是加一层解决不了的! 程序员调用 | JDBC | Mysql Oracle SqlServer....
MVC三层架构
Model
业务处理:业务逻辑(Service)
数据持久层:CRUD(Dao)
View
展示数据
提供链接发起Servlet请求(a,form,img….)
Controller(Servlet)
接收用户的请求:(req:请求参数,Session信息..)
交给业务层处理对应的代码
控制视图的跳转
1 登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)--->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确--->数据库
Filter(重点) Filter:过滤器,用来过滤网站的数据
Filter开发步骤:
导包
编写过滤器
导包不要错
实现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 25 26 27 28 29 public class CharacterEncodingFilter implements Filter { public void init (FilterConfig filterConfig) throws ServletException { System.out.println("CharacterEncodingFilter初始化" ); } 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("CharacterEncodingFilter执行前..." ); chain.doFilter(request,response); System.out.println("CharacterEncodingFilter执行后..." ); } public void destroy () { System.out.println("CharacterEncodingFilter销毁" ); } }
在web.xml中配置Filter
1 2 3 4 5 6 7 8 9 <filter > <filter-name > CharacterEncodingFilter</filter-name > <filter-class > com.xcw.filter.CharacterEncodingFilter</filter-class > </filter > <filter-mapping > <filter-name > CharacterEncodingFilter</filter-name > <url-pattern > /servlet/*</url-pattern > </filter-mapping >
监听器 实现一个监听器的接口(有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 35 36 37 38 39 40 41 42 43 44 45 46 47 public class OnlineCountListener implements HttpSessionListener { public void sessionCreated (HttpSessionEvent httpSessionEvent) { ServletContext ctx = httpSessionEvent.getSession().getServletContext(); System.out.println(httpSessionEvent.getSession().getId()); Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount" ); if (onlineCount == null ){ onlineCount = new Integer(1 ); } else { int count = onlineCount.intValue(); onlineCount = new Integer(count+1 ); } ctx.setAttribute("OnlineCount" ,onlineCount); } public void sessionDestroyed (HttpSessionEvent httpSessionEvent) { ServletContext ctx = httpSessionEvent.getSession().getServletContext(); System.out.println(httpSessionEvent.getSession().getId()); Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount" ); if (onlineCount == null ){ onlineCount = new Integer(0 ); } else { int count = onlineCount.intValue(); onlineCount = new Integer(count-1 ); } ctx.setAttribute("OnlineCount" ,onlineCount); } }
web.xml中注册监听器
1 2 3 <listener > <listener-class > com.xcw.listener.OnlineCountListener</listener-class > </listener >
看情况是否使用
过滤器、监听器常见应用 用户登录之后才能进入主页!用户注销后就不能进入主页了
用户登录后,向Session中放入用户的数据
进入主页的时候判断用户是否已经登录,要求:在过滤器中实现
1 2 3 4 5 6 7 HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; if (request.getSession().getAttribute(Constant.USER_SESSION)==null ){ response.sendRedirect("/error.jsp" ); } filterChain.doFilter(request,response);
JDBC 什么是JDBC:java连接数据库
需要的jar包的支持:
java.sql
javax.sql
mysql-conneter-java… 连接驱动(必须要导入)
实验环境搭建
1 2 3 4 5 6 7 8 9 10 CREATE TABLE users( id INT (3 ) PRIMARY KEY, `name` VARCHAR (20 ), `password` VARCHAR (20 ), `email` VARCHAR (20 ), `birthday` DATE ) INSERT INTO users(id,`name`,`password`,`email`,`birthday`)VALUES (1 ,'张三' ,'123456' ,'zs@qq.com' ,'2000-01-01' ),(2 ,'李四' ,'123456' ,'ls@qq.com' ,'2000-01-01' ),(3 ,'王五' ,'123456' ,'ww@qq.com' ,'2000-01-01' )
导入数据库依赖
1 2 3 4 5 6 <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.47</version > </dependency >
IDEA中连接数据库
JDBC固定步骤
加载驱动
连接数据库,代表数据库
向数据库发送SQL的对象Statement :CRUD
编写SQL(根据业务,不同的SQL)
执行查询SQL,返回一个ResultSet :结果集
关闭连接
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 public class TestJdbc { public static void main (String[] args) throws ClassNotFoundException, SQLException { String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8" ; String username = "root" ; String password = "cjy521213" ; Class.forName("com.mysql.jdbc.Driver" ); Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement(); String sql = "select * from users" ; ResultSet rs = statement.executeQuery(sql); while (rs.next()){ System.out.println("id=" + rs.getObject("id" )); System.out.println("name=" + rs.getObject("name" )); System.out.println("password=" + rs.getObject("password" )); System.out.println("email=" + rs.getObject("email" )); System.out.println("birthday=" + rs.getObject("birthday" )); System.out.println("--------------------------" ); } rs.close(); statement.close(); connection.close(); } }
预编译SQL 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 public class TestJdbc2 { public static void main (String[] args) throws ClassNotFoundException, SQLException { String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8" ; String username = "root" ; String password = "cjy521213" ; Class.forName("com.mysql.jdbc.Driver" ); Connection connection = DriverManager.getConnection(url, username, password); String sql = "insert into users(id, name, password, email, birthday) value(?,?,?,?,?)" ; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setInt(1 ,4 ); preparedStatement.setString(2 ,"行初雾" ); preparedStatement.setString(3 ,"123456" ); preparedStatement.setString(4 ,"1092315259@qq.com" ); preparedStatement.setDate(5 ,new Date(new java.util.Date().getTime())); int i = preparedStatement.executeUpdate(); if (i>0 ){ System.out.println("插入成功" ); } preparedStatement.close(); connection.close(); } }
事务 要么都成功,要么都失败
ACID原则:保证数据的安全
1 2 3 4 5 6 7 8 9 10 开启事务 事务提交 事务回滚 关闭事务 转账: A:1000 B:1000 A(900) --100--> B(1100)
Junit单元测试
依赖
1 2 3 4 5 6 7 <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.11</version > <scope > test</scope > </dependency
简单实用
@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行
1 2 3 4 @Test public void test () { System.out.println("hello" ); }