狂神说-JavaWeb
1、基本概念
1.1、前言
web开发:
-
静态web
- html,css
- 提供给所有人看的,数据始终不会发生变化
-
动态web
- 淘宝,几乎是所有的网站
- 提供给所有人看的,数据始终会发生变化
- 技术栈:Servlet/JSP,ASP,PHP
在java中,动态web资源开发的技术统称为Javaweb
1.2、动态web
页面会动态展示“Web的页面展示效果因人而异”
缺点:
- 加入服务器的动态web资源出现的错误,我们需要重新编写我们的后台程序,重新发布
优点:
- 页面会动态展示
- 可以与数据库进行交互(数据持久化)
新手村---> 训练(分析原理,看源码)-->PK场
2、Tomcat
2.1、Tomcat的启动和配置
文件夹作用
2.2、配置
服务器核心配置文件:conf目录下的server.xml
可以配置启动的端口号
- tomcat:8080
- mysql:3306
- http:80
- https:443
可以配置主机的名称
- 默认主机名:localhost
- 默认网站的存放位置:webapps
面试题:
请你谈谈网站是如何进行访问的
- 输入一个域名,回车
- 检查本机的 C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射
- 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
- 没有:去DNS服务器找,找到的话就返回,找不到就返回找不到
3、Http
3.1、什么是HTTP
HTTP(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上
- 文本:html,字符串
- 超文本:图片,音乐,视频,定位,地图
Https:安全的
两个时代
- HTTP/1.0:客户端可以与服务器连接后,只能获得一个web资源,断开连接
- HTTP/1.1:客户端可以与服务器连接后,可以获得多个web资源
3.2、Http请求
- 客户端---发送请求 ----服务器
- 百度:
Request URL: https://www.baidu.com/ 请求地址
Request Method: GET
Status Code: 200 OK 状态码:200
Remote(远程) Address: 14.215.177.39:443
1、请求行
- 请求行中的方式:GET
- 请求方式:Get,Post,HEAD,DELETE,PUT,TRACT...
- get:请求能够携带的参数较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效
2、消息头
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 IS08859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Contro1:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../ .
3.3、Http响应
- 服务器---响应---客户端
百度
Cache-Control: private 缓存控制
Connection: keep-alive 连接
Content-Encoding: gzip 编码
Content-Type: text/html 类型
1、响应体
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式 GBK UTF-8 GB2312 IS08859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Contro1:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../ .
Refresh:告诉客户端,多久刷新一次
Location:让网页重新定位
2、响应状态码
200:请求响应成功
3xx:请求重定向
- 重定向:你重新定位到我给你的新位置
4xx:找不到资源 404
- 资源不存在
5xx:服务器代码错误 500 502:网关错误
常见面试题:
当你在浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?
4、Maven
4.1、Maven项目架构管理工具
我们目前用来就是方便导入jar包的
Maven核心思想:约定大于配置
- 有约束,不要去违反
Maven会规定好你该如何去编写我们的java代码,必须按规范来
4.2、配置Maven环境变量
在系统环境变量中配置如下配置:
- M2_HOME maven目录下的bin目录
- MAVEN_HOME maven的目录
- 在系统的path中配置%MAVEN_HOME%\bin
4.3、阿里云镜像
-
镜像:mirrors
- 作用:加速下载
-
国内建议使用阿里云的镜像
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
4.4、本地仓库
建立一个本地仓库:localRepository
localRepository>E:\Environment\apache-maven-3.8.4\maven-repo</localRepository>
4.5、在IDEA中使用Maven
1、创建一个MavenWeb项目
2、IDEA中的Maven配置
注意:IDEA项目创建成功后,看一眼配置
4.5、标记文件夹功能
4.6、在IDEA中配置Tomcat
解决警告问题
必须要的配置为什么会有这个问题:我们访问一个网站,需要指定一个文件夹名字
4.7、pom文件
pom.xml是Maven的核心配置文件
Maven由于它的约定大于配置,我们之后可能遇到我们写的配置文件无法被导出或者生效的问题
解决方案:
<! --在bui1d中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
4.8、Maven仓库的使用
搜索需要的jar包,然后复制maven代码即可
5、Servlet
5.1、HelloServlet
Servlet接口有两个默认的实现类:HttpServlet,GenericServlet
1、构建一个普通的Maven项目,删掉里面的src目录,以后学习就在这里面建立Moudel,这个空的工程就是Maven的主工程
2、关于Maven父子工程的理解:
父项目中会有
<modules>
<module>servlet-01</module>
</modules>
子项目中
<parent>
<artifactId>javaweb-02-maven</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目中的子项目可以直接使用
3、Maven环境优化
- 修改web.xml为最新的
- 将Maven的结构搭建完整
4、编写一个servlet程序
5、编写Servlet的映射
为什么需要映射∶我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径;
<!-- 注册servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.gao.servlet.HelloServlet</servlet-class>
</servlet>
<!-- servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
6、配置Tomcat
注意:配置项目的发布路径
7、启动测试
5.2、Servlet原理
Servlet是由Web服务器调用,web服务器在收到浏览器请求后,会:
5.3、mapping问题
1、一个Servlet可以指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
2、一个Servlet可以指定多个映射路径
<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>
3、一个Servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
4、指定一些后缀或者前缀等等...
<!-- servlet的请求路径
可以自定义后缀实现映射
注意点: * 前面不能加项目映射的路径
-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.gao</url-pattern>
</servlet-mapping>
5、优先级问题
指定了固有的映射路径优先级最高,如果找不到就走默认的处理请求
默认路径:/*
5.4、ServletContext
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用
1、共享数据
我们在这个Servlet中保存的数据,可以在另一个Servlet中拿到
存:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = "张三";
context.setAttribute("username",username);
}
取:
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().println("名字:" + username);
}
2、获取初始化参数
<!--配置一些web应用初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306</param-value>
</context-param>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String s = context.getInitParameter("url";
resp.getWriter().println(s);
}
3、请求转发
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
//context.getRequestDispatcher 请求转发的路径
//forword用于实现请求转发
context.getRequestDispatcher("/gp").forward(req,resp);
}
4、读取资源文件
Properties
- 在Java,目录下新建properties
- 在resource目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath
思路:需要一个文件流
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().println(user + ":" + pwd);
}
5.5、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);
2、下载文件
1、向浏览器输出消息
2、下载文件
- 获取要下载文件的路径
- 下载的文件名
- 让浏览器支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区中的数据输出到客户端
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取要下载文件的路径
String realPath = "E:\\download app\\download app\\IDEA\\study\\JavaWeb\\javaweb-02-maven\\servlet-01\\src\\main\\resources\\1.png";
// 2. 下载的文件名
String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3. 让浏览器支持下载我们需要的东西
// web下载文件设置的头信息
// 使用web下载文件的时候,需要在实例化FileServlet 类的doGet方法里面添加以下设置
// resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(filename,"UTF-8"));
resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(filename,"UTF-8"));
// 4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
// 5. 创建缓冲区
int len = 0;
byte[] bytes = new byte[1024];
// 6. 获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
// 7. 将FileOutputStream流写入到buffer缓冲区
while((len = in.read(bytes)) != -1){
out.write(bytes,0,len);
}
in.close();
out.close();
// 8. 使用OutputStream将缓冲区中的数据输出到客户端
}
3、验证码功能
- 前端实现
- 后端实现,使用java的图片类,生产一个图片
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 让浏览器3秒钟自动刷新一次
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 r = new Random();
String num = r.nextInt(99999) + "";
StringBuffer sb = new StringBuffer();
for (int i =0 ;i<7-num.length();i++){
sb.append("0");
}
num = sb.toString() + num;
return num;
}
4、重定向
一个web资源收到客户端请求后,它会通知客户端去访问另一个web资源,这个过程叫做重定向
常见场景:
- 用户登录
void sendRedirect(String var1) throws IOException;
测试:
overrideprotected void doGet(HttpServletRequest req,HttpServletResponseresp) throws ServletException,IOException {
/*
resp.setHeader( "Location","/r/img");
resp.setstatus(302);*/
resp.sendRedirect(" /r/img ");//重定向}
重定向和转发的区别
相同点
- 页面都会实现跳转
不同点
- 请求转发的时候,url不会发生变化 307
- 重定向的时候,页面地址栏会发生变化 302
${pageContext.request.contextPath}代表当前的项目
注意:重定向的时候要注意路径问题,否则会404
5.6、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息
功能:获取参数,请求转发
6、Cookie、Session
6.1、会话
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话
有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学曾经来过,称之为有状态会话
6.2、保存会话的两种技术
cookie
- 客户端技术(响应,请求)
session
- 服务器技术,利用这个技术,可以保存用户的会话信息,我们可以把信息或数据放在session中
6.3、Cookie
1、从请求中拿到cookie信息
2、服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(;//获得cookie
cookie. getName(;//获得cookie中的key
cookie.getvalue(;//获得cookie中的v1aue
new Cookie("lastLoginTime",system.currentTimeMillis()+"");
//新建一个cookie
cookie.setMaxAge(24*60*60);//设置cookie的有效期
resp. addCookie(cookie);//响应给客户端一个cookie
cookie:一般会保存在本地的用户目录下appdate
- 一个Cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20个
- Cookie大小有限制—4kb
- 浏览器上限:300个cookie
删除Cookie:
- 不设置有效期,关闭浏览器,自动失效
- 设置有效期时间为0
编码解码:
URLEncoder.encode("张三", "utf-8")
URLDecoder.decode(cookie. getvalue() , "UTF-8")
7.4、Session(重点)
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
- 用户登录后,整个网站它都可以访问-->保存用户的信息
Session和Cookie的区别
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session是把用户的数据写到用户独占Session中,服务端保存(保存重要的信息,减少服务器资源的浪费)
- Session对象由服务器创建
使用场景
- 保存一个登录用户的信息
- 购物车信息
- 在整个网站中经常会使用到的数据,我们将它保存在Session中
使用:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html,character=utf-8");
resp.setHeader("content-type","text/html;charset=UTF-8");
HttpSession session = req.getSession();
session.setAttribute("name",new Person("张三",20));
String sessionId = session.getId();
if(session.isNew()){
resp.getWriter().write("Sessoin的ID:" + sessionId);
}else{
resp.getWriter().write("Session对象已存在,ID:" + sessionId);
}
}
/*
HttpSession session = req.getSession();
Person person = (Person)session.getAttribute("name");
System.out.println(person.toString());
session.removeAttribute("name");
手动注销session
session.invalidate();
*/
会话自动过期:web.xml中配置
<session-config>
<!-- 1分钟后自动失效,以分钟为单位 -->
<session-timeout>1</session-timeout>
</session-config>
7、JSP
Java Server Pages:Java服务器端页面,也和Servlet一样,用于动态Web技术
最大的特点:
- 写JSP就像在写HTML
- 区别:
- Html只给用户提供静态的数据
- JSP中可以嵌入Java代码,为用户提供动态数据
7.1、JSP原理
思路:看JSP
-
服务器内部工作
Tomcat中有一个work目录
IDEA中使用Tomcat的会在IDEA的Tomcat中生产一个work目录
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet
JSP最终也会被转换成为一个Java类
JSP本质上就是一个Servlet
使用Maven添加HttpJspBase所在的依赖
<!-- https://mvnrepository.com/artifact/tomcat/jasper-runtime -->
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-runtime</artifactId>
<version>5.5.23</version>
</dependency>
1、判断请求
2、内置一些对象
3、输出页面前添加的代码
在JSP页面中:
只要是JAVA代码就会原封不动的输出
如果是HTML代码,就会被转换为
out.write("<html>\r\n");
7.2、JSP基础语法
Jsp表达式
<%--JSP表达式
作用:用来将程序的输出,输出到客户端<%=变量或者表达式%>
--%>
<%= new java.util.Date()%>
jsp脚本片段
<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <=100 ; i++) {
sum+=i;
}
out. println("<h1>sum="+sum+ "</h1>");
%>
Jsp声明
<%!
static {
system.out.print1n ("Loading servlet! ");
}
private int g1obaTvar = 0;
public void kuang({
system.out.print1n("进入了方法Kuang!");
}
%>
区别:
JSP声明会被编译到JSP生成的Java的类中,其它的就会被生成到_jspService方法中
7.3、JSP指令
<%@page args. . . . %>
<%@include file=""%>
<%--@include会将两个页面合二为一—-%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@inc1ude file="common/footer.jsp "%>
<hr>
<%--jSP标签
jsp :include:拼接页面,本质还是三个--%>
<jsp :include page=" / common/header.jsp" />
<h1>网页主体</h1>
<jsp :include page=" /common /footer.jsp"/>
7.4、9大内置对象
- PageContext
- Request
- Response
- Session
- Application【ServletContext】
- cpnfig 【ServletConfig】
- out
- page
- exception
pagecontext.setAttribute("name1", "1号");//保存的数据只在一个页面中有效
request.setAttribute("name2" , "2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3 " , "3号");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
app1ication.setAttribute( "name4 " , "4号");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
7.5、JSP标签、JSTL标签、EL表达式
<!-- JSTL表达式的依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jst1-api</artifactId>
<version>1.2</version>
</dependency>
<!-- standard标签库-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactid>
<version>1.1.2</version>
</dependency>
EL表达式:${ }
- 获取数据
- 执行运算
- 获取web开发的常用对象
JSP标签
<%--jsp :include--%>
<%--
http://loca1host:8080/jsptag.jsp?name=gao&age=12--%>
<jsp :forward page="/jsptag2.jsp">
<jsp :param name="name" value="YSL"></jsp:param>
<jsp:param name="age " value="12"></jsp:param>
</jsp:forward>
JSTL标签
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样
格式化标签
SQL标签
XML标签
核心标签(掌握部分)
JSTL标签库使用步骤:
- 引入对应的taglib
- 使用其中的方法
- 在Tomcat中也需要引入jstl的包
8、JavaBean
实体类
JavaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM
ORM:对象映射关系
- 表-->类
- 字段-->属性
- 行记录-->对象
9、MVC三层架构
Model:
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD(Dao)
View
- 展示数据
- 提供链接发起Servlet请求
Controller(Servlet)
- 接收用户的请求(req:请求参数、Session信息...)
- 交给业务层处理对应的代码
- 控制视图的跳转
10、Filter(重点)
Filter:过滤器,用来过滤网站的数据,处于web服务器和Servlet之间
- 处理中文乱码
- 登录验证
Filter开发步骤:
- 导包
- 编写过滤器
- 导包:javax.servlet.*
- 实现Filter接口,重写对应的方法即可
- 在web。xml中配置Filter过滤器
初始化:web服务器启动,就已经初始化了,随时等待过滤对象的出现
销毁:web服务器关闭的时候,过滤器被销毁
Chain:链
- 过滤中的所有代码,在过滤特定请求的时候都会执行
- 必须要让过滤器同行 chain.doFilter(request,response)
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("hello");
}
@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;character = UFT-8");
System.out.println("执行前");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("执行后");
}
@Override
public void destroy() {
System.out.println("bye");
}
Junit单元测试
依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
简单使用:
@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行