JavaWeb.md 24 KB

JavaWeb


1、基本概念


1.1、前言

web开发:

  • web,网页的意思,www.baidu.com
  • 静态web
    • html,css
    • 提供给所有人看的数据始终不会发生变化!
  • 动态web
    • 淘宝,几乎是所有的网站;
    • 提供给所有人看的数据始终会发生变化!
    • 技术栈:Servlet/JSP,ASP,PHP

在Java中,动态web资源开发的技术统称为JavaWeb

1.2、web应用程序

web应用程序:可以提供浏览器访问的程序

  • a.html,b.html.........多个web资源,可以被外界访问,对外界提供服务;
  • 资源存在物理机上面
  • URL
  • 统一的web资源会被放在同一个文件夹下,web应用程序
  • 一个web应用由多部分组成
    • html,css,js
    • jsp,servlet
    • java程序
    • jar包
    • 配置文件(properties)

web应用程序编写完毕后,若想提供给外部访问;需要一个服务器来统一管理;

1.3、静态web

  • .htm,.html,这些都是网页的后端,如果服务器上一直存在这些东西,我们就可以直接进行读取 image-20211112143650663
  • 静态web存在的缺点
    • 微博页面无法动态更新,所有用户看到都是同一个页面
    • 轮播图,点击特效:为动态
    • javascript
    • 无法与数据库交互

1.4、动态web

页面会动态展示:“展示效果因人而异” image-20211112145114932

缺点

  • 如果服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布;
    • 停机维护

优点

  • web页面可以动态更新
  • 可以与数据库交互

2、web服务器


2.1、技术讲解

ASP

  • 微软
  • 在HTML中嵌入了VB脚本 PHP
  • 开发速度很快,功能强大,跨平台,代码简单
  • 无法承载大访问量的情况 JSP/Servlet:
  • sun公司主推的B/S架构
  • 基于Jva语言
  • 可以承载三高问题带来的影响

2.2、web服务器

服务器是一种被动操作,用来处理用户的一些请求和用户一些相应信息; IIS Tomcat

3、Tomcat


  1. JAVA环境必须有
  2. 乱码:修改命令行编码为UTF-8

xml文件可以配置

  • 端口号
  • 主机名称
  • 应用的存放位置

访问网站:

  1. 输入域名
  2. 检查本机hosts
  3. 访问DNS服务器

4、Servlet


4.1、Servlet简介

  • Servlet就是sun公司开发动态web的一门技术
  • sun在这些API中提供了一个接口叫做:Servlet
    • 编写一个类实现这个接口
    • 开发好的类部署到web服务器中

4.2、HelloServlet

  1. 构建一个主工程
  2. 关于maven父子工程的理解: 父项目中会有一个

    <modules>
    	<module>servlet01</module>
    </modules>
    

    子项目中会有一个

    <parent></parent>
    

    父项目中的java子项目可以直接引用

  3. 编写一个servlet类,继承HttpServlet接口

    public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 响应流
        PrintWriter writer = resp.getWriter();
        writer.print("Hello,Servlet");
    }
    }
    
    1. 为什么编写Servlet的映射 我们写的是JAVA程序,但是需要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的servlet,还需给他一个浏览器能够访问的路径 xml <servlet> <servlet-name>Hello</servlet-name> <servlet-class>com.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
  4. 配置Tomcat image-20211112211142264

4.3、Servlet原理

Servlet是由web服务器调用,web服务器在收到浏览器请求之后,会: image-20211113134002803

4.4、Mapping问题

  1. 一个Servlet可以指定一个映射路径

    <servlet-mapping>
    <servlet-name>Hello</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
    1. 一个Servlet可以指定多个映射路径 xml <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>
  2. 一个Servlet可以指定通用映射路径------servlet优先级较高,会覆盖默认请求

    <servlet-mapping>
    <servlet-name>Hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
    
    1. 指定一些后缀或者前缀 xml <servlet-mapping> <servlet-name>Hello</servlet-name> <!--*前面不能加项目映射路径--> <url-pattern>*.do</url-pattern> </servlet-mapping>
  3. 默认请求路径------少用

    <servlet-mapping>
    <servlet-name>Hello</servlet-name>
    <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
    1. 优先级问题 指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求。

    4.5、ServletContext

    web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,他代表了当前的web应用;

    4.5.1、共享数据

    servlet中保存的数据,在另外的servlet可以拿到。

    ServletContext servletContext = this.getServletContext();
    servletContext.setAttribute("userName", userName);
    String userName = (String) servletContext.getAttribute("userName");
    

4.5.2、获取初始化参数

ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);

4.5.3、请求转发

// 该转发会带上d
this.getServletContext().getRequestDispatcher("/gp").forward(req,resp);

image-20211113145845150 通过这张图你就可以看到,转发是在服务器之间进行的,它的意思虽然我没有你想要的资源但是我可以帮你找到,

重定向是告诉你,我Servlet1没有这个资源,但是我告诉你那里有,你自己通过浏览器去找,

4.5.4、读取资源文件

maven由于他的约定大于配置,我们写的配置文件,可能无法被导出或者生效,解决方法

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

Properties 发现都被打包到了同一个路径下:classes,我们俗称为classpath 通过文件流读取。

4.6、HttpServletResponse

webn服务器接收到客户端的http请求,针对请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse

  • 如果要获取客户端请求过来的参数:HttpServletRequest
  • 如果要找客户端响应的一些信息:HttpServletResponse

4.6.1、常用应用

  1. 输出信息
  2. 下载文件
    1. 获取下载文件的路径
    2. 下载的文件名
    3. 设置让浏览器能够支持我们需要的东西
    4. 获取下载文件的输入流
    5. 创建缓冲区
    6. 获取OutputStream对象
    7. 将OutputStream写入缓冲区
    8. 将缓冲区写入磁盘
  3. 验证码功能 验证怎么来的?
  4. 前端实现
  5. 后端实现,需要用到java的图片类,产生一个图片
  6. 重定向 image-20211113164517356 常见场景:
  7. 用户登录

    // 需要设置改项目的路径
    resp.setHeader("Location", "/r/image");
    resp.setStatus(HttpServletResponse.SC_FOUND);
    resp.sendRedirect("/r/image");
    

    重定向和转发区别? 相同点:

    • 界面都会实现改变 不同点:
    • 一个是web服务器
    • 一个是浏览器
    • 转发会加上项目路径,而重定向不会
    • 重定向:302
    • 转发:307

    4.7、HttpServletRequest

    HttpServletRequest代表客户端的请求,用户通过http服务请求都被封装到Request下面。

    1. 获取前端请求的参数
    2. 转发请求 java req.getRequestDispatcher("/image").forward(req,resp);

5、Cookie、Session


5.1、会话

会话:用户打开一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,这个过程称之为会话。 有状态会话:保存上次会话的状态 怎么证明自己是西电学生?

  1. 发票
  2. 登记 一个网站,怎么证明你来过? 客户端 服务端
  3. 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了:cookie
  4. 服务器登记你来过了,下次你来的时候我来匹配你:session

5.2、保存会话的两种技术

cookie

  • 客户端技术(响应,请求)

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息!我们可以把信息或者数据放入session

常见场景:网站登录之后,下次不需要登录

5.3、cookie

  1. 从请求中拿到cookie信息
  2. 服务器响应给客户端cookie

    Cookie[] cookies = req.getCookies();
    
    1. 一般会保存在本地目录下

    一个网站cookie是否存在上限

    • 一个cookie只能保存一个信息
    • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
    • 300个浏览器上限
    • cookie大小有限制4kb

    删除cookie;

    • 不设置有效期,关闭浏览器,自动失效;
    • 有效期设置为0,自动消失

    5.4、Session(重点)

    什么是session:

    • 服务器会给每一个用户(浏览器创建一个)session对象
    • 一个session独占一个浏览器,只要浏览器没有关闭,这个session就存在
    • 用户登录之后,整个网站都可以访问!保存用户的信息;保存购物车的信息

    session和cookie的区别:

    • cookie是浏览器保存(可以保存多个)
    • session是用户独占,服务器端保存(保存重要信息,减少服务器资源浪费)
    • session对象是由服务器创建

    session使用场景:

    • 保存一个登录用户的信息
    • 购物车信息:
    • 整个网站中经常会使用的数据

    什么时候会被销毁? 话题:当浏览器关闭后,Session就销毁了吗? 答案:存在于浏览器上的唯一标识符JSESSIONID(sessionid)消失了,但是服务器中存放的sessionid并没有立马销毁。 分析:我们知道Session是JSP的九大内置对象(也叫隐含对象)中的一个,它的作用是可以保存当前用户的状态信息,初学它的时候,认为Session的生命周期是从打开一个浏览器窗口发送请求到关闭浏览器窗口,但其实这种说法是不正确的!当一个Session开始时,Servlet容器会创建一个HttpSession对象,那么在HttpSession对象中,可以存放用户状态的信息,Servlet容器为HttpSession对象分配一个唯一标识符即Sessionid,Servlet容器把Sessionid作为一种Cookie保存在客户端的浏览器 中用户每次发出Http请求时,Servlet容器会从HttpServletRequest对象中取出Sessionid,然后根据这个Sessionid找到相应的HttpSession对象,从而获取用户的状态信息。

    其实让Session结束生命周期,有以下两种办法:

    1. 一个是Session.invalidate()方法,不过这个方法在实际的开发中,并不推荐,可能在强制注销用户的时候会使用;
    2. 一个是当前用户和服务器的交互时间超过默认时间后,Session会失效。

    6、JSP


    6.1、什么是JSP?

    java server pages:java服务器端界面,也和servlet一样,用于动态web技术 最大的特点:

    • 写JSP就像写HTML
    • 区别
    • HTML只给用户提供静态数据
    • JSP页面中可以嵌入JAVA代码,为用户提供动态数据

    6.2、JSP原理

    • 代码层面没有任何问题

    • 服务器内部工作

    tomcat中有一个work目录

    IDEA中使用tomcat开发会在idea中生成一个work目录

    • 浏览器向服务端发送请求,不管访问什么请求,其实都是在访问servlet

    • JSP最终会转换为java类

    • JSP本质还是一个servlet

    1. 判断请求
    2. 内置一些对象 java final javax.servlet.jsp.PageContext pageContext; // 页面上下文 javax.servlet.http.HttpSession session = null; // session final javax.servlet.ServletContext application; // applicationcontext final javax.servlet.ServletConfig config; //配置 javax.servlet.jsp.JspWriter out = null; // out final java.lang.Object page = this; // page当前页
    1. 输出页面前增加的代码

      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;  
      
      1. 以上这些对象我们在JSP页面中直接使用
      • 在JSP页面中:

      如果是JAVA代码就会被原封不动的输出

      如果是HTML代码就会被转换为out.write("

      ")这样的格式渲染到前端

      • 原理图 image-20211114185115260

      6.3、JSP基本语法

      任何语言都有自己的语法,JPS作为java的一种应用,它拥有自己的扩充语法(了解即可),并且支持所有的java语法

      1. JSP表达式
      <%--JSP表达式
      作用:用来将程序的输出到客户端
      <%= 变量或者表达式%>
      --%>
      <%= new java.util.Date()%>
      
  3. JSP脚本片段

  <%
    int sum = 0;
    for (int i = 0; i < 100; i++) {
      sum += i;
    }
    out.println("<h1>Sum=" + sum + "</h1>");
  %>
  <%--JSP脚本片段--%>
  <%
    int sum = 0;
    for (int i = 0; i < 100; i++) {
      sum += i;
    }
    out.println("<h1>Sum=" + sum + "</h1>");
  %>

  <%
    for (int i = 0; i < 5; i++) {
  %>
    <h1>Hello,World <%=i%></h1>
  <%
    }
  %>
  1. jsp声明:会被编译到JSP生产JAVA类中!其他的,就会被生产到_jspservice方法中!
  <%!
    static {
      System.out.println("Loading Servlet!");
    }
    private int g = 0;
    public void test() {
      System.out.println("in test method");
    }
  %>
  1. jsp的注释无法显示在html中

6.4、JSP指令

<%@page%>
<%--g--%>

<%@include file=""%>
这个与上面的区别:下面的本质还是三个页面而上面是三个部分拼接成一个
jsp:include page="index.jsp"/

6.5、9大内置对象

  • Pagecontext 存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application 存东西
  • Config
  • out
  • page
  • Exception
// 保存的数据只在一个页面有效
pageContext.setAttribute("name1", "1");
// 保存的数据只在一次请求中有效,请求转发(重定向无效)会携带这个数据
request.setAttribute("name2", "2");
// 保存的数据只在一次会话有效
session.setAttribute("name3", "3");
// 保存的数据只在服务器中有效,从打开服务器到关闭服务器
application.setAttribute("name4","4");

6.6、JSP标签、JSTL标签、EL表达式

        <!--JSTL表达式依赖-->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-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 page="index.jsp"/>
<%--转发--%>
<jsp:forward page="/jsptag2.jsp">
    <jsp:param name="a" value="a"/>
    <jsp:param name="b" value="b"/>
</jsp:forward>

JSTL标签

JSTL标签库的使用就是为了弥补HTML标签的不足;他自定义许多标签,可以供我们使用,标签的功能和java代码一样!

  • 核心标签(要求掌握部分) image-20211116155018740
  • 格式化标签
  • SQL 标签
  • XML 标签
  • ```jsp <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> /c:if
  • 
    ## 7、JavaBean
    
    ***
    
    实体类
    JavaBean有特点的写法:
    * 必须定义无参构造
    * 属性必须私有化
    * 必须有对应的get/set方法
    
    一般用来和数据库字段做映射ORM;
    ORM:对象关系映射
    
    * 表->类
    * 字段->属性
    * 行记录->对象
    
    People表
    | id   | name | age  | address |
    | ---- | ---- | ---- | ------- |
    | 1    | tom  | 10   | 西安    |
    | 2    | lin  | 19   | 西安    |
    | 3    | pet  | 13   | 西安    |
    
    ```java
    public class People {
        private int id;
        private String name;
        private int age;
        private String address;
    }
    
    <jsp:useBean id="people" class="com.entity.People" scope="page"/>
    
    <jsp:setProperty name="people" property="address" value="西安"/>
    <jsp:setProperty name="people" property="id" value="1"/>
    <jsp:setProperty name="people" property="age" value="3"/>
    <jsp:setProperty name="people" property="name" value="tom"/>
    
    <jsp:getProperty name="people" property="address"/>
    <jsp:getProperty name="people" property="id"/>
    <jsp:getProperty name="people" property="age"/>
    <jsp:getProperty name="people" property="name"/>
    

    8、MVC三次架构


    什么是MVC:model view controller 模型、 视图、 控制器

    8.1、早些年

    image-20211116171819380 用户直接访问控制层,控制层直接操作数据库;

    servlet--CRUD--->数据库
    弊端:程序十分臃肿,不利于维护  
    servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
    

    8.2、MVC三层架构

    image-20211116172558256

    Model

    • 业务处理:业务逻辑(Service)
    • 数据持久层:CRUD(Dao)

    View

    • 展示数据
    • 提供链接发起Servlet请求(a,form, img)

    Controller(Servlet)

    • 接受用户的请求:req,参数和session信息
    • 交给业务层处理响应的代码
    • 控制视图的跳转

      登录----》接受用户的请求---》处理用户的请求(获取参数:username,password)----》交给业务层处理登录业务(判断用户名密码是否正确:事务)-----》Dao层查询用户名和密码是否正确----》数据库
      

    9、Filter(重点)


    Filter:过滤器,用来过滤网站的数据;

    • 处理中文乱码
    • 登录验证 image-20211116174340271

    Filter开发步骤:

    1. 导包 image-20211117161407452
    2. 编写过滤器 ```java public class CharacterEncodingFilter implements Filter { // 初始化:web服务器启动就已经初始化了,随时等待监听 @Override public void init(FilterConfig filterConfig) throws ServletException {

      System.out.println("init CharacterEncodingFilter");
      

      }

      // chain:链

      /**

      • 1.过滤器中的所有代码,在过滤特定请求的时候都会执行
      • 2.必须要让过滤器继续通行 */ @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("CharacterEncodingFilter执行前"); // 让我们的请求继续走,如果不写,程序在这里就被拦截 chain.doFilter(request,response); System.out.println("CharacterEncodingFilter执行后"); }

      // 销毁:web服务器关闭的时候,过滤器会销毁 @Override public void destroy() {

      System.out.println("destroy CharacterEncodingFilter");
      

      } }

      3. 在web.xml中配置
      ```xml
      <filter>
          <filter-name>CharacterEncodingFilter</filter-name>
          <filter-class>com.filter.CharacterEncodingFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>CharacterEncodingFilter</filter-name>
          <!--只要是/servlet的任何请求,都会经过这个过滤器-->
          <url-pattern>/servlet/*</url-pattern>
      </filter-mapping>
      

    10、监听器


    实现一个监听器的接口;(有n种)

    1. 重写方法

      public class OnlineCountListener implements HttpSessionListener {
      // 创建session监听,一旦创建一个session就会触发这个事件
      @Override
      public void sessionCreated(HttpSessionEvent se) {
          ServletContext context = se.getSession().getServletContext();
          Integer onlineCount = (Integer) context.getAttribute("OnlineCount");
          if (onlineCount == null) {
              onlineCount = new Integer(1);
          } else {
              int value = onlineCount.intValue();
              onlineCount = new Integer(value + 1);
          }
          context.setAttribute("OnlineCount", onlineCount);
      }
      
      // 销毁session监听,一旦销毁一个session就会触发这个事件
      @Override
      public void sessionDestroyed(HttpSessionEvent se) {
          ServletContext context = se.getSession().getServletContext();
          Integer onlineCount = (Integer) context.getAttribute("OnlineCount");
          if (onlineCount == null) {
              onlineCount = new Integer(0);
          } else {
              int value = onlineCount.intValue();
              onlineCount = new Integer(value - 1);
          }
          context.setAttribute("OnlineCount", onlineCount);
      }
      }
      
      1. 配置web.xml xml <!--注册监听器--> <listener> <listener-class>com.listener.OnlineCountListener</listener-class> </listener>

    11、过滤器监听器常见应用


    用户登陆之后才能进入主页!用户注销就不能进入主页!

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            // 转换过来才能过去session
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    
    
            if (httpServletRequest.getSession().getAttribute("USER_SESSION") == null) {
                httpServletResponse.sendRedirect("/f/error.jsp");
            }
    
    
            chain.doFilter(request,response);
        }
    

    12、JDBC


    什么是JDBC:Java连接数据库

    • 加载驱动
    • 连接数据库,代表数据库
    • 向数据库发送SQL的对象Statement : CRUD
    • 编写SQL (根据业务,不同的SQL)
    • 执行SQL
    • 关闭连接(先开的后关) image-20211117192533110
    1. 导入驱动

          <!--连接数据库-->
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>8.0.19</version>
          </dependency>
      
      1. java语句

        String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";
        
        
        // 加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);
        // 想数据库发送SQL的对象Statement:CRUD
        Statement statement = connection.createStatement();
        // 编写SQL
        String sql = "select * from users";
        // 执行SQL,返回结果集
        ResultSet resultSet = statement.executeQuery(sql);
        
        while (resultSet.next()) {
            System.out.println("id" + resultSet.getObject("id"));
        }
        resultSet.close();
        connection.close();
        statement.close();
        

    事务 要么都成功,要么都失败! ACID原则:保证数据的安全

    开启事务
    事务提交	commit
    事务回滚	rollback
    关闭事务