javaweb笔记
1.基础概念
1.1 前言
web开发
-
? web
-
? 静态web
-
html,css
-
提供给所有人开的数据始终不会发生变化
-
一个能动的页面不是动态页面!!!
-
-
动态web
-
淘宝,
-
提供给所有人看的数据始终会发生变化话,每个人在不同的时间不同的地点看到的信息各不相同
-
技术栈:Servlet/jsp,ASP,PHP
-
1.2 web应用程序
web应用程序,可以提供浏览器访问得程序
- ? a.html,b.html....多个web资源,可以被外界访问,对外界提供服务
- 能访问到的任何一个页面或者资源,都存在与这个世界的米一个角落的计算机上
- URL
- 这个同一个的web资源会被放在用一个文件夹下:web应用程序-->Tomcat服务器
- 一个web应用由多个部分组成(静态web,动态web)
- html,js,css
- jsp,servlet
- java程序
- jar包
- 未知文件(Properties
web应用程序比那些完毕后,若想要提供给外界访问,需要一个服务器来统一管理
1.3 静态web
- *.html 这些页面如果服务器上一直存在这些东西,就能获取
? client---> Request---->server
? client<-----Response-----server
- 静态web的缺点:
- web页面无法动态更新,所有用户看见的都是一个页面
- javascript
- VBScript
- 无法和数据库交互,数据无法持久化,用户无法交互
1.4 动态web
页面的展示效果因人而异

-
缺点:
- 加入服务器的动态web起源出现了问题,需要重新编写后台程序,重新发布
- 停机维护
- 加入服务器的动态web起源出现了问题,需要重新编写后台程序,重新发布
-
优点:
- web页面可以动态的更新
- 可以与数据库交互
- 可以做数据持久化:注册
2 web服务器
ASP:
- 微软:国内最早流行的
- 在HTML中嵌入vb的脚本,ASP+COM
- 在ASP开发中,要在页面中嵌入很多后端代码
- 页面混乱,维护难
- C#
- IIS
PHP:
- 开发速度快,功能大,跨平台,代码超级简单
- 无法承载大访问量
JSP:/Servlet
- BS:浏览器和服务器
- CS:客户端和服务器
- sun公司主推的bs架构
- 基于Java语言
- 高承载量
- 语法像ASP
2.2 web服务器
服务器是一种被动的操作,用来处理用户的一些清秀和给用户一些相应信息
-
IIS:微软的
-
Tomcat
3. Tomcat安装
文件夹作用:
3.1 配置
更改默认端口,默认域名,默认工程目录
3.2发布一个web网站
- ? 将网站项目放到Tomcat指定的web应用文件夹下,就可以访问了
--webapps:
-ROOT
-test:网站目录
-WEB-INF
-classes:java程序
-lib:web应用所以来的jar包
web.xml:网站的配置文件
-indexx.thml:默认的首页
-static
-ccs
-js
-img
.......
4. HTTP
4.1 啥是HTTP
超文本传输协议,请求-相应协议,运行在tcp之上
HTTPS:
- s:安全的
- 443
4.2 俩时代
- http1.0
- HTTP/1.0
- 客户端可以和web服务器连接,只能获得一个web资源,断开连接
- http2.0
- HTTP/1.1
- 可以获得多个ewb资源,保持连接
4.3 Http请求
- Request
请求 URL: https://www.baidu.com/
请求方法: GET
状态代码: 200 OK
远程地址: 182.61.200.7:443
引用站点策略: strict-origin-when-cross-origin //协议
Accept: text/html //类型
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7 //语言
Cache-Control: max-age=0
Connection: keep-alive
4.3.1 请求行
- ? 请求行中的请求方式,GET
- 请求方式:Get Post HEAD DELETE PUT TRACT
- get:请求能够携带的参数少,大小有限制,会在url地址栏显示数据内容,不安全,但是高效
- Post:能够携带的参数无限,大小无限制,不限制内容,安全,没那么快
4.3.2消息头
Accept:告诉浏览器它所支持的数据类型
Accept-Encoding:支持的编码格式,GBK,UTF-8,GB2312,ISO8859-1
Accept-Language:语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
4.4 Http相应
百度为例:
Cache-Control: no-cache //缓存控制
Connection: keep-alive //保持连接
Content-Encoding: gzip //编码
Content-Type: text/html;charset=utf-8 //类型
Coremonitorno: 0
Date: Sun, 06 Mar 2022 13:48:42 GMT //时间
Server: apache //服务
4.4.1响应体
Accept:告诉浏览器它所支持的数据类型
Accept-Encoding:支持的编码格式,GBK,UTF-8,GB2312,ISO8859-1
Accept-Language:语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
Host:主机
Refresh:告诉客户端,多久刷新一次
Location:让网页重新定位
4.4.2 响应状态码
- 200:成功
- 4**:找不到资源(404)
- 3**:请求重定向
- 重定向:重新到我告诉你的新位置去找
- 5**:服务器代码错误(500,502网关错误)
5.Maven
5.1 是啥,为啥学
- ? 在javaweb开发中,需要使用大量的jar包,需要手动导入
- 如何能找个玩意自动帮我导入和配置这个jar包呢
- 使用Maven工具
5.2 Maven项目架构管理工具
- ? Maven的核心思想:约定大于配置,之后可能遇到写的配置文件,无法被导出或者生效的问题:
- ? 解决方案:pom中指定读取资源文件的路径
src/main/resources
**/*.properties
**/*.xml
true
src/main/java
**/*.properties
**/*.xml
true
- 有约束,就不要去违反
5.3 环境变量+阿里云镜像
5.4 本地仓库
? 在本地的仓库,远程的仓库
? 建立一个本地仓库:
//默认的本地目录
而且必须写!!不写话子模块识别不到整体工程下的pom.xml配置文件,全局的jar包局部用不了
6.2.4 Maven环境优化
1.修改web.xml为下面新的
<?xml version="1.0" encoding="UTF-8"?>
2.将maven的结构补充完整--添加java和resource文件夹,并设置为source root 和res root
6.2.5 编写servlet程序
- 编写一个普通类
- 实现servlet接口(继承HttpServlet实现类)
- 自定义实现类:
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不用方式,可以相互调用,业务逻辑多一样,所以写一个就行,另一个调用他
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//resp.getOutputStream();//响应字节流,一次调用,一次响应,所以这俩只能根据情况用一个
PrintWriter writer = resp.getWriter();//响应字符流
writer.print("Hello.Serlvet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
6.2.6 编写Servlet的映射
- 为啥需要映射,我都已经有响应servlet的类了??
- 我们写的是java程序,但是要通过client访问,而浏览器需要连接web服务器
- 所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能访问得路径
- 人话:想让别人用,就得让别人知道你有,还得让他知道在哪
在web.xml中:
hello
com.zhang.servlet.HelloServlet
hello
/hello
6.2.7 配置tomcat
- 注意配置项目发布的路径
- 这里的/s01和上面映射的/hello有啥关系??
- tomcat配置里面的/s01相当于服务器的地址
- 访问时需要输入localhost:8080/s01才能访问到服务器,显示的是项目的默认主页index.jsp
- 内容是helloWorld!
- Servlet映射中配置的/hello相当于,响应的地址
- 即怎么获得你写的这个Servlet响应,输入:localhost:8080/s01/hello就能得到你的Servlet方法响应
- 内容是实现类doGet方法里的打印流:hello,servlet
- 具体底层就是/s01找到服务地址,再通过服务里面的servlet映射找到/hello映射到了哪个Servlet,再通过找到的servlet-name找到具体的类
- tomcat配置里面的/s01相当于服务器的地址
6.3 Servlet-Mapping
- Servlet可以对应多个Servlet-Mapping ,只要Servlet-name一样,这些路径就都能映射到对应的Servlet响应上
- Mapping可以使用*通配符
- *.zhang ,只要以项目域名开始,.zhang 结尾的,都可以匹配到
- 但是!!不能使用/*.zhang的Mapping映射
6.4 指定Error页面处理错误映射
6.4.1 mapping的优先级问题
- 制定了固有的Mapping映射路径优先级最高
- 如果找不到,就会找默认页面
6.4.2 Error Mapping
Error
com.zhang.servlet.ErrorServlet
Error
/*
6.5 ServletContext对象
- web容器在启动的时候,他会为每个web程序都创建一个ServletContext对象,他代表当前的web应用
6.5.1 共享数据
在一个Servlet中保存的数据,可以再另外一个Servlet中获取
存入ServletContext类
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter();//初始化参数
//this.getServletConfig();//Servlet配置
//this.getServletContext();//Servlet上下文
ServletContext sc = this.getServletContext();
String username="张";//只要涉及到中文,后面肯定要处理编码
sc.setAttribute("username",username);//将一个数据保存到ServletContext中
}
}
读取ServletContext的类:
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();//这几个Servlet里面的this.出来的ServletContext肯定都是一个SContext
String username = (String) servletContext.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().write("名字"+username);
}
}
6.5.2 获取初始化参数
可以再web.xml中写一些参数配置,然后通过ServletContext获取
- web.xml配置
url
jdbc:myusql://localhost:3306/mybatis
- 实现类:
public class ServletContextGetParam extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp){//省略异常,省略post
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
}
6.5.3 请求转发dispatcher
- 通过ServletContext将数据请求转发到其他页面
- 但是页面不会跳转(状态码还是200(not 300))
- 区别于重定向,重定向会改变路径
实现类:
public class ServletDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入ServletDemo04");
ServletContext context = this.getServletContext();//这几个Servlet里面的this.出来的ServletContext肯定都是一个SContext
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/getparam");//转发的请求路径
requestDispatcher.forward(req,resp);//调用forward方法,实现转发
//this.getServletContext().getRequestDispatcher("/getparam").forward(req,resp);//三步合一
}
}
Servlet响应请求后,通过ServletContext将请求发往GetRequestDispatcher()指定的路径,然后由这个路径转发响应
6.5.4 读取资源文件(最主要功能)
-
Properties (翻译:所有物; 财产; 财物; 不动产; 房地产; 房屋及院落; 庄园)
-
问题1:资源在哪了?
- 不在你的工程文件路径resources下!!你写的是web应用,是要编译部署到服务器上面的
- 通过运行tomcat,在target目录下,WEB-INF/classes下面
- 也就是classpath路径下
-
问题2:maven的资源导出可能存在问题(解决方案上面见5.2)
- 比如:java(代码路径)下的资源文件(Properties配置文件,图片)并不能放到上面提到的classpath里
左:工程目录,中:编译目录,java路径下的资源文件都没了 右:添加资源目录配置后,正常出现
- 资源读取
- 思路:使用文件流
public class PropertiesServlet 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 username = prop.getProperty("username");
String password = prop.getProperty("password");
resp.getWriter().print(username+":"+password);
}
}
6.5.5 后话
mlgb,学完了你告诉我这一节以后基本不会用,能不用ServletContext就不用,用session替代,用request替代,用反射替代
6.6 HttpServletResponse
- 响应:web服务器接收到client的http请求,会针对这个请求,分别创建 一个代表请求的HttpServletRequest对象,和一个代表响应的HttpServletResponse对象(下一节)
- 如果要获取client请求过来的参数,找HttpServletRequest
- 如果要给客户端响应一些信息,找HttpServletResponce
6.6.1源码
- 大体看HttpServletResponce类里面的方法:getXxx,setXxx,addXxx,没了。。。
- 负责像client发送数据的方法:
public ServletOutputStream getOutputStream() throws IOException;//字节流
printWriter getWriter() throws IOException;//字符流
- 负责向client发送响应头的方法
public void setCharacterEncoding(String charset);
public voit setContentLength(int len);
public void setContentLengthLong(long len);
public void setContentType(String type);
6.6.2 常见应用
6.6.2.1 向client输出消息
6.6.2.2 下载文件
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 要获取下载文件的路径
// String realPath = this.getServletContext().getRealPath("/张.jpg");
String realPath="D:\\project\\IDEA\\javaweb-servlet\\response\\src\\main\\resources\\张.jpg";
System.out.println(realPath);
//2. 下载的文件名
//字符串截取/后面的获取文件名,看似很蠢,实测真实开发基本都这么干
String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);
//3. 设置想办法让浏览器能支持下载
//web下载文件头长得很难看,没人记,每次现搜就行
//resp.setHeader("Content-Disposition","attachment;filename="+filename);//直接写文件名,对于中文文件可能会乱码
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
//4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);//文件的输入流,把文件变成流就可以用了
//5. 创建缓冲区
//固定招式
int len=0;
byte[] buffer = new byte[1024];
//6. 获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
//7. 将FileOutputStream流写入到buffer缓冲区
//8. 使用OutputStream将缓冲区的数据输出到client
while((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
}
}
6.6.2.3 验证码功能
- 验证码怎么来的
- 前端生成
- 后端生成,java 图片类生成
6.6.2.4 Response重定向!!!
- 四个小节,就TM这个有用
- 一个web资源收到客户端请求后,他会通知client访问另外一个web资源,这个过程叫重定向
- 用户登录
public void sendRedirect(String location) throws IOException;
resp.sendRedirect("/res/img");//一句话就行,就跳转了
6.7 HttpServletRequest
- HeepServlet代表client的请求,用户通过Http协议访问服务器,Http请求中的所有信息都可以通过req参数获得
6.7.1 获取前端传递的参数
req.getParameter(String)
7 Cookie,Session
7.1 会话
- 用户打开一个浏览器,点击很多超链接,可以访问多个web资源,再关闭浏览器,这就是会话。。。
- 有状态会话
- 对于一个网站,怎么证明曾经来过
- server给客户端一个cookie,客户端下次访问服务端带上cookie
- server登记用户来过,下次来的时候就匹配这个client:seesion
- 对于一个网站,怎么证明曾经来过
7.2 保存会话的两种技术
-
Cookie
- 客户端行为(请求+响应)
-
session
- 服务器行为,利用这个技术可以保存用户的会话信息
-
应用:client登录一次之后,再点击就直接登录了
7.3 Cookie (not import)
- 从请求中拿到cookie
- 服务器响应给客户端cookie
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
Cookie[] cookies = req.getCookies();//获得cookie
if(cookies!=null){
out.write("上一次访问服务器的时间是");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if(cookie.getName().equals("lastLoginTime")){//获得cookie的key
long l = Long.parseLong(cookie.getValue());//获得cookie的value
Date date = new Date(l);
out.write(date.toLocaleString());
}
}
}else{
out.write("第一次访问服务器");
}
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(10);//设置有效期,单位s,
resp.addCookie(cookie);//响应给client
}
cookie,一般保存在本地用户目录下appdata
- 一个网站的cookie是否存在上限
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
- cookie大小有限制,4kb
- 300个cookie浏览器上限
删除cookie
- 不设置有效期,关闭浏览器自动失效
- 设置有效期为0
7.4 Session (重点)
- 啥是Session
- 服务器会对每一个用户(浏览器)创建一个session
- 一个session独占一个浏览器,只要浏览器不关闭,这个session就存在
- 用户登录之后,整个网站就都可以访问了
7.4.1 session vs cookie
- session把用户的数据写到用户独占Session中,服务器端保存
- cookie把用户的数据写到用户的浏览器中,浏览器保存
- sessioni对象由服务器创建
session使用场景:
- 保存用户登录信息
- 购物车信息
- 整个网站中常用的数据
session过期自动设置
15 单位:分钟
8 JSP 还学不学啊,都过时一万年了
8 javaBean
-
咖啡豆???
-
javaBean有特定的写法
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
- 一般用来和数据库的字段做映射
-
ORM 对象关系映射
- 表-类
- 字段-属性
- 行记录-对象
9 MVC三层架构
- model view controller 模型视图控制器
- model模型:pojo里的实体类
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD(Dao)
- view视图:前端
- 展示数据
- 提供连接发起Servlet请求(a,form,img..
- Controiller控制器:servlet
- 接受用户的请求(req,session。。。。
- 交给业务层处理对应的代码
- 控制视图跳转
- 难么? 难个粑粑
- model模型:pojo里的实体类
- 为啥这么搞?
- 之前都这么搞:用户直接访问控制层,控制层直接操作数据库
servlet-----crud------数据库
弊端:程序臃肿,不利于维护
servlet的代码中,要处理请求,响应,视图跳转,处理jdbc,处理业务代码,处理有逻辑代码
啥是架构啊?就是如果这一层用着很难受,那就再加一层好了
真谛:架构中,没有什么是加一层解决不了的
10 过滤器 Filter
Filter用来过滤网站的数据:
- 处理中文乱码
- 登录验证
Filter层处理乱码
public class CharacterEncodingFilter implements Filter {
//web服务器启动了,他就初始化了
//过滤中的所有代码,在过滤人特定请求时
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharcterEncodingFilter初始化");
}
@Override
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("CharacterEncdingFilter执行前");
chain.doFilter(request,response);//让请求继续走,不写程序到这里就拦截停止了
System.out.println("CharacterEncdingFilter执行后");
}
//web服务器关闭时才销毁
@Override
public void destroy() {
System.out.println("CharcterEncodingFilter销毁");
}
}
web.xml配置:
任何经过mapping的请求都会经过该过滤器
CharacteEncodingFilter
com.zhang.filter.CharacterEncodingFilter
CharacteEncodingFilter
/filter
11 Listener监听器 没啥大用
gui编程里面才有大用,知道了吧
- 比如统计网上在线人数。。。
public class OnlineCountListener implements HttpSessionListener{
//
public void sessionCreated(HttpSessionEvent se){
ServletContext ctx=se.getSession().getServletContext();
Int onlineCount (Integer)ctx.getArrtibute("Onlinecount");
if(onlineCount==null){
onlineCount=1;
}else{
onlineCount=onlieCount.inValue()+1;
}
ctx.setArrivute("OnlineCOunt",onlineCount);
}
//销毁就是-1
}
web.xml也得设置.lue........