JavaWeb(一)
JavaWeb
- Web
- 静态Web
- html,css
- 提供给所有人看的数据始终不会发生变化
- 动态Web
- 淘宝,几乎是所有的网站
- 提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同
- 技术栈:Servlet/JSP,ASP,PHP
在Java中,动态Web资源开发的技术统称为JavaWeb
Web应用程序
可以提供浏览器访问的程序
- a.html...多个web资源,可以被外界访问,为外界服务
- 能访问到的资源都存在于某一个计算机上
- URL
- 这个同意的web资源会被放在同一文件夹下,web应用程序->Tomcat:服务器
- 一个web应用由多部分组成
- html,css, js
- jsp,servlet
- Java程序
- jar包
- 配置文件(Properties)
web应用程序编写完后,若想提供给外界访问,需要一个服务器来同意管理
静态web
- *.html
- web页面无法动态更新,所有用户看到都是同一个页面
- 无法和数据库交互(数据无法持久化)
动态web
-
页面会动态展示,web页面展示效果因人而异
-
缺点:加入服务器的动态web资源出现了错误,需要重新编写后台的程序
- 停机维护
-
优点:可以动态更新,与数据库交互
web服务器
ASP
- 微软:国内最早流行的就是ASP
- 在HTML中嵌入了VB的脚本,ASP+COM
- 在ASP开发中,基本一个页面都有几千行的业务代码,页面机器混乱
- 维护成本高
- C#
- IIS
php
- PHP开发速度很快,功能很强大,跨平台,代码简单
- 无法承载大访问量的情况(局限性)
JSP/Servlet
- sun公司主推的B/S架构
- 基于java语言的(所有的大公司或者一些开源的组件,都是用java写的)
- 可以承载三高问题带来的影响
- 语法像ASP,ASP->JSP
Web服务器
服务器是一种被动的操作,用来处理用户的一下请求和给用户的一下响应信息
IIS
- 微软的,ASP,Window中自带的
Tomcat
- Tomcat服务器是一个免费的开放源代码的Web服务器,属于轻量级应用服务器
- Tomcat实际上运行JSP页面和Servlet
下载Tomcat
- 安装or解压
- 了解配置文件及目录结构
- 这个东西的作用
Tomcat
- 下载解压zip文件
- 启动和配置文件
- 启动 startup.bat
- 访问:http://localhost:8080/
- 关闭:关闭控制台或者shutdown.bat
可能遇到的问题:
- Java环境变量没有配置
-闪退问题:需要配置兼容性
-乱码问题:在配置文件中设置
- 配置
- servler.xml核心配置文件
- 可以配置启动端口号,Tomcat默认端口号是8080
- 可以配置主机的名称,默认的主机名为:localhost->127.0.0.1
- servler.xml核心配置文件
高频面试题:网站如何进行访问的
->输入一个域名,回车
->检查本机的C:\Window\System32\drivers\etc\hosts配置文件下有没有这个域名映射
->有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
->没有,去DNS服务器上查询,找的话就返回,找不到就返回
- 可以配置一个环境变量,命令行启动
- 发布一个Web网站
- 将自己写的网站放到服务器中制定的web应用文件夹(webapp)下就可以访问了
网站的结构
--webapps:Tomcat服务器的web目录
-ROOT
-ming:网站的目录名
-web-inf
-classes java程序
-lib web应用依赖包
-web.xml 网站配置文件
-index.html
HTTP
什么是HTTP
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,HTTP是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII码形式给出;而消息内容则具有一个类似MIME的格式
- 文本:html,字符串~
- 超文本:图片,音乐,视频,定位,地图~
- 80
Https:安全的
- 443
两个时代
-
http1.0
- HTTP/1.0:客户端可以与web服务端连接后,只能获得一个web资源,断开连接
-
http2.0
- HTTP/1.1:客户端可以与web服务端连接后,可以获得多个web资源
HTTP请求
客户端->发请求->服务器
Request URL: https://www.baidu.com/ 请求地址
Request Method: GET 请求方法
Status Code: 200 OK 状态码
Remote Address: 36.152.44.96:443 远程地址
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Cookie: PSTM=1572915522; BAIDUID=AEE83A4561351C047835C81814E7DAB3:FG=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; __cfduid=dd901a57541008dfd0526053e84d327641601701966; COOKIE_SESSION=43143_2_7_1_27_15_0_0_5_5_1_0_43105_0_2_0_1601783578_1600787276_1601783576%7C9%23914695_54_1601701964%7C9; __yjsv5_shitong=1.0_7_029c42c2330bce56039f567defeeb8eab188_300_1601783791000_223.104.6.2_91d6f323; BD_HOME=1; delPer=0; BD_CK_SAM=1; PSINO=3; H_PS_645EC=0adb8OnixJEvwehHv06qoTetzPAQswro0E1MQyD1BqaqwQq19lHx2X4yECM; BIDUPSID=0ECED95EB3E98304F84B985062804BB4; BD_UPN=19314753; H_PS_PSSID=32756_32617_1468_32734_31660_32723_32230_7517_32719
Host: www.baidu.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0
-
请求行
- 请求行的请求方式:GET
- 请求方式:Get,Post,Head,Delete,Put,Tract
- get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全但不高效
-
消息头:
Accept:告诉浏览器,它所支持的数据类型 Accept-Encoding:支持哪种编码格式, GBK,UTF-8 GB2312 Accept-Language:告诉浏览器它的语言环境 Cache-Control:缓存控制 Connection:告诉浏览器,请求完成时断开还是保持连接 Host:
HTTP响应
服务端->响应->客户端
Cache-Control: private 缓存控制
Connection: keep-alive 连接:
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 类型
-
响应体:
Accept:告诉浏览器,它所支持的数据类型 Accept-Encoding:支持哪种编码格式, GBK,UTF-8 GB2312 Accept-Language:告诉浏览器它的语言环境 Cache-Control:缓存控制 Connection:告诉浏览器,请求完成时断开还是保持连接 Host: Refresh:告诉客户端,多久刷新一遍 Location:让网页重新定位
-
响应状态码
- 200:请求响应成功
- 3xx:请求重定向
- 重定向:
- 404:找不到资源
Maven
- 在JavaWeb需要使用大量的jar包,我们手动去导入
- 如何能够让一个东西自动帮我们导入和配置这些jar包
- Maven项目架构管理工具
Maven的核心思想:约定大于配置
- 有约束,不要去违反
-
下载
-
配置环境变量
- M2_HOME maven目录下bin目录
- MAVEN_HOME maven的目录
- 在系统的path中配置%MAVEN_HOME%\bin
-
阿里云镜像
-
镜像:mirrors
- 加速下载
-
国内建议阿里云镜像
-
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<!-- 国内推荐阿里云的Maven镜像 -->
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
- 本地仓库
<localRepository>D:\maven-3.6.3\my_repository</localRepository>
IDEA中maven的操作
- 启动IDEA
- 配置maven环境
- 创建一个maven 项目,选择模板,webapp
- 等待加载依赖库完成
不用模板的maven项目
- 不选择模板
- 直接创建项目
可以为标记功能目录,或者在Project Structure中标记
在idea中配置Tomcat
- Add Configure配置
- 点+新增Tomcat Server->local
- 服务器命名,默认设置,包括端口号,浏览器,jdk
- 配置Tomcat位置
pom.xml文件是核心文件
package:项目打包方式
jar:java应用
war:web应用
maven资源导出失败,解决办法
<build>
<resources>
<resource>
<directory>src/main/resource(资源目录)</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
maven默认的web项目中web.xml版本是2.3,选择Tomcat里的最新的5.0,不会出现版本问题
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
</web-app>
java,resources,标记为功能目录
Maven仓库的使用
HelloServlet
web.xml注册
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
<!--注册servlet-->
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.company.servlet.HelloServlet</servlet-class>
</servlet>
<!--一个servlet对应一个Mapping映射-->
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<!--请求路径-->
<url-pattern>/ming</url-pattern>
</servlet-mapping>
</web-app>
helloServlet编写
package com.company.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Hello World!</h1>");
out.println("</body>");
out.println("</html>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
Servlet
-
Servlet就是sun公司开发动态web的一门技术
-
sun在这些API中提供一个接口叫做:Servlet
-
如果你想开发一个Servlet程序,只需要完成两个小步骤
- 编写一个类,实现Servlet接口
- 把开发好的Java类部署到web服务器中
把实现了Servlet接口的程序叫做,Servlet
HelloServlet
Servlet接口有两个默认的实现类:HttpServlet,GenericServlet
-
构建一个普通的maven项目,删掉里面的src目录,以后就在这个项目里建立Module,这个空的工程就是maven主工程
-
关于maven父子工程的理解
父项目中会有
<modules> <module>servlet-01</module> </modules>
子项目中
<parent> <artifactId>Mavendemo</artifactId> <groupId>org.company</groupId> <version>1.0-SNAPSHOT</version> </parent>
父项目中的jar包子项目中可以直接使用
-
Maven环境优化
- 修改web.xml为最新的
- 将maven的结构搭建,java,resources
-
编写一个Servlet程序
- 编写一个普通类
- 实现一个Servlet接口,这里我们直接继承HttpServlet
package com.company;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
//由于get后者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();//响应流
writer.print("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
-
编写Servlet的映射web.xml
为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册写的servlet,还需给他一个浏览器能访问的路径
<!--注册servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.company.HelloServlet</servlet-class>
</servlet>
<!--一个servlet对应一个Mapping映射-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<!--请求路径-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 配置Tomcat
- 启动测试
Servlet原理
Servlet是由web服务器调用,web服务器在收到浏览器请求后,调用相应的Servlet
Mapping问题
- 一个Servlet可以指定一个映射路径
- 一个Servlet可以指定多个映射路径
- 一个Servlet可以指定通用映射路径
- 指定一些后缀或者前缀等等
优先级问题:指定了固有的映射路径优先级最高,找不到就会走默认的请求
响应乱码问题可以修改
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext对象
web容器在启动的时候,它会为每个Web程序都创建一个对应的ServletContext对象,它代表了当前的web应用
-
共享数据
我在这个Servlet中保存的数据,可以在另外一个Servlet中拿到
-
获取初始化参数
//web.xml
<contextparam>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</contextparam>
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
- 请求转发
ServletContext servletContext = this.getServletContext();
servletContext.getRequestDispatcher("/ser1").forward(req,resp);//调用forward方法实现转发
- 读取资源文件
- 在java目录下新建properties
- 在resources目录下新建properties
发现都被打包到了同一个路径下,classes,我们俗称这个路径为classpath
思路:需要一个文件流
//db.properties
username=root
password=123456
ServletContext servletContext = this.getServletContext();
InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/dp.properties");
Properties pro = new Properties();
pro.load(is);
String username = pro.getProperty("username");
String password = pro.getProperty("password");
resp.getWriter().print(username+":"+password);
HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的HttpServletResponse对象
- 如果要获取客户端请求过来的参数,找HttpServletRequest
- 如果要获取客户端响应的一些信息,找HttpServletResponse
简单分类
负责向浏览器发送数据的方法
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 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);
常见应用
- 向浏览器输出消息
- 下载文件
- 获取下载文件的路径
- 文件名
- 设置浏览器支持
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区中的数据输出到客户端
String path = this.getServletContext().getRealPath("1.png");
String filename = path.substring(path.lastIndexOf("//")+1); //URLEncode解决乱码问题
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(path,"utf-8"));
FileInputStream in = new FileInputStream(path);
int len = 0;
byte[] buffer = new byte[1024];
ServletOutputStream out = resp.getOutputStream();
while((len=in.read())!=-1){
out.write(buffer,0,len);
}
in.close();
out.close();
-
验证码功能
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器5秒自动刷新一次
resp.setHeader("refresh","5");
//在内存中创建图片
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D graphics = (Graphics2D) image.getGraphics();//笔
//设置图片的背景颜色
graphics.setColor(Color.white);
graphics.fillRect(0,0,80,20);
//给图片写数据
graphics.setColor(Color.blue);
graphics.setFont(new Font(null,Font.BOLD,20));
graphics.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;
}
-
实现重定向
/*resp.setHeader("Location","/img"); resp.setStatus(302);*/ resp.sendRedirect("/img");
重定向和转发的区别
页面都会转发
请求转发的时候,url不会发生变化
重定向的时候,url会发生变化
重定向的时候注意路径,要加上项目的路径
index.jsp
<%--${pageContext.request.contextPath}代表当前的项目--%> <form action="${pageContext.request.contextPath}/hello" method="get"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit"> </form>
String username = req.getParameter("username"); String password = req.getParameter("password");
常见场景:
登录界面