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

页面的展示效果因人而异

image-20220306205639564
  • 缺点:

    • 加入服务器的动态web起源出现了问题,需要重新编写后台程序,重新发布
      • 停机维护
  • 优点:

    • web页面可以动态的更新
    • 可以与数据库交互
    • 可以做数据持久化:注册
    image-20220306205941019

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安装

文件夹作用:

image-20220306211639546

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 是啥,为啥学

  1. ? 在javaweb开发中,需要使用大量的jar包,需要手动导入
  2. 如何能找个玩意自动帮我导入和配置这个jar包呢
  3. 使用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实现类)

image-20220310093056639

  • 自定义实现类:
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

  • 注意配置项目发布的路径

image-20220310095605415

  • 这里的/s01和上面映射的/hello有啥关系??
    1. tomcat配置里面的/s01相当于服务器的地址
      • 访问时需要输入localhost:8080/s01才能访问到服务器,显示的是项目的默认主页index.jsp
      • 内容是helloWorld!
    2. Servlet映射中配置的/hello相当于,响应的地址
      • 即怎么获得你写的这个Servlet响应,输入:localhost:8080/s01/hello就能得到你的Servlet方法响应
      • 内容是实现类doGet方法里的打印流:hello,servlet
    3. 具体底层就是/s01找到服务地址,再通过服务里面的servlet映射找到/hello映射到了哪个Servlet,再通过找到的servlet-name找到具体的类

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路径下的资源文件都没了 右:添加资源目录配置后,正常出现

image-20220310154238765image-20220310154320005image-20220310161039441

  • 资源读取
    • 思路:使用文件流
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登录一次之后,再点击就直接登录了

  • 从请求中拿到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就存在
    • 用户登录之后,整个网站就都可以访问了
  1. session把用户的数据写到用户独占Session中,服务器端保存
  2. cookie把用户的数据写到用户的浏览器中,浏览器保存
  3. 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。。。。
      • 交给业务层处理对应的代码
      • 控制视图跳转
    • 难么? 难个粑粑

image-20220313184835388

  • 为啥这么搞?
    • 之前都这么搞:用户直接访问控制层,控制层直接操作数据库
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........