JavaWeb入门

Vuejs、Springboot入门

Posted by whaler404 on January 25, 2024

Web开发流程

黑马课程链接

web网站的工作流

  • 浏览器:输入域名

  • 前端服务器:运行前端程序,页面展示

  • 后端服务器:运行Java程序,数据的逻辑处理

  • 数据库服务器:数据的存储管理

  • 工作流程:

    1. 浏览器通过域名请求前端服务器,前端程序响应,返回前端代码
    2. 浏览器通过解析引擎解析前端代码,显示基本结构
    3. 前端代码显示数据获取路径,浏览器通过路径请求后端Java程序
    4. 后端Java程序继续请求数据库,数据库响应后端服务器
    5. 后端服务器将数据返回浏览器,浏览器将数据填充在前端页面中

    image-20230811192653685

  • 开发模式

    • 前后端分离开发:前后端程序开发和部署都是分开的

    • 混合开发:前后端不分离,数据和前端代码一并发送给客户端

      image-20230811193151033

  • 前端web开发:

    • HTML、CSS、JavaScript
    • Vue(基于js封装的高级技术)、Element、Nginx(前端程序服务器部署程序)
  • 后端web开发:

    • maven(Java项目构建工具)
    • spring boot web基础、开发、进阶
    • MySQL
    • spring boot mybatis(通过Java操作数据库)

HTML

web前端基础

  • 浏览器内核:前端代码通过浏览器解析渲染
  • 不同的浏览器内核,对前端代码的解析效果存在差异
  • web标准:由三部分组成:
    • HTML:网页结构(页面元素和内容)
    • CSS:网页的表现(页面元素的外观、位置等页面样式)
    • JavaScript:网页的行为(交互效果)
  • 高级框架:
    • vue.js:基于js封装
    • element:基于vue封装的桌面组件库
    • Axios:异步交互技术
  • 学习路线:
    • HTML、CSS
    • JavaScript、Vue
    • Ajax、Axios、ElementUI、Nginx
  • 官方文档:https://www.w3school.com.cn/

HTML

  • 超文本标记语言hypertext markup language

  • 标记语言:由标签label构成的语言

    • 标签预定义好的,由浏览器解析
    • xml的标签由程序员定义解析规则
  • 实现标题排版——以新浪新闻为例

    <!-- 文档类型为HTML -->
    <!doctype html5>
    <html>
        <header>
            <!-- 字符集为utf-8 -->
            <meta charset="UTF-8">
            <title>焦点访谈:中国底气 新思想夯实大国粮仓 </title>
            <!-- 内嵌样式 -->
            <!-- <style>
                h1{
                    color: red;
                }
            </style> -->
            <!-- 引用样式 -->
            <link rel="stylesheet" href="css/news.css">
        </header>
        <body id="content">
                <div>
                <!-- 
                img标签:
                    src:资源路径
                        绝对路径、相对路径、网络路径、磁盘路径
                    width、height:px,像素|%,相对于父元素的百分比
                -->
                <img src="http://image2.sina.com.cn/home/head/sinalogo.gif" width="" height="">
                <a href="https://gov.sina.com.cn/" target="_blank">新浪政务</a>
                >正文
      
                <!-- 行内样式 -->
                <!-- <h1 style="color: red;">焦点访谈:中国底气 新思想夯实大国粮仓</h1> -->
                <h1>焦点访谈:中国底气 新思想夯实大国粮仓</h1>
                <hr>
                <!--
                    行内元素使用没有语义的标签
                    用来区分行内的不同文本
                -->
                <!-- id选择器 -->
                <span id="sid">2023年3月2日 21:50</span> 
                <!-- 类选择器 -->
                <span class="cls">
                    <a href="https://www.cctv.com/">央视网</a>
                </span>
                <hr>
      
                <!-- 正文 -->
                <!-- 视频 -->
                <video class="resize" src="video/1.mp4" controls width="950px"></video>
      
                <p>        
                    <b>央视网消息</b>(焦点访谈):党的十八大以来,以习近平同志为核心的党中央始终把解决粮食安全问题作为治国理政的头等大事,重农抓粮一系列政策举措有力有效,我国粮食产量站稳1.3万亿斤台阶,实现谷物基本自给、口粮绝对安全。我们把饭碗牢牢端在自己手中,为保障经济社会发展提供了坚实支撑,为应对各种风险挑战赢得了主动。连续八年1.3万亿斤,这个沉甸甸的数据是如何取得的呢?
                </p>
      
                <img class="resize" src="https://p1.img.cctvpic.com/photoworkspace/contentimg/2023/03/02/2023030221282825411.jpg" >
      
                <p>
                    人勤春来早,春耕农事忙。立春之后,由南到北,我国春耕春管工作陆续展开,春天的田野处处生机盎然。
                </p>
                  
                <img class="resize" src="https://p1.img.cctvpic.com/photoworkspace/contentimg/2023/03/02/2023030221300552541.jpg">
      
                <p>
                    中国式现代化一个重要的中国特色是人口规模巨大的现代化。我们粮食生产的发展,意味着我们要立足国内,解决14亿多人吃饭的问题。仓廪实,天下安。保障粮食安全是一个永恒的课题,任何时候都不能放松。在以习近平同志为核心的党中央坚强领导下,亿万中国人民辛勤耕耘、不懈奋斗,我们就一定能够牢牢守住粮食安全这一“国之大者”,把中国人的饭碗牢牢端在自己手中,夯实中国式现代化基础。
                </p>
      
                <p id="plast">编辑:刘珊 责任编辑:刘亮</p>
        </div>
        </body>
    </html> 
    
  • 实现标题超链接——以新浪新闻为例

    • <span>无意义标签,可用在同一行中

    • <a href=”…” target=”…“>央视网</a>

      • href:指定资源链接

      • target:在何处打开连接

        • _self:当前页面打开,默认值
        • _blank:空白页面打开
  • 实现正文排版——以新浪新闻为例

    • <audio>、<video>音视频
    • <br>换行、<p>段落

    • <b>和<strong>加粗

    • &nbsp空格占位符
  • 实现布局——以新浪新闻为例

    • 布局标签<div>和<span>,无意义
    • <div>
      • 独占一行
      • 宽度默认父元素宽度,高度默认内容撑开
      • 可设置宽高
    • <span>
      • 一行显示多个
      • 宽度高度默认由内容撑开
      • 不可以设置宽高
  • 表格标签和表单标签

    • 表格标签:

      • <table>定义表格整体,可包裹多个<tr>
        • border规定表格边框高度
        • width规定表格宽度
        • cellspacing规定表格单元之间的空间
      • <tr>table row表格的行,可包裹多个<td>table data cell
      • <td>表格单元格,包裹内容,表头单元格可换为<th>table head
      <body>
          <table border="1px" cellspacing="0" width="600px">
              <tr>
                  <th>序号</th>
                  <th>品牌logo</th>
                  <th>品牌名称</th>
                  <th>企业名称</th>
              </tr>
              <tr>
                  <th>1</th>
                  <th><img src="https://www-file.huawei.com/-/media/corporate/images/home/logo/huawei_logo.png" alt=""></th>
                  <th>华为</th>
                  <th>华为技术有限公司</th>
              </tr>
              <tr>
                  <th>2</th>
                  <th><img src="https://www.mediatek.cn/dist/mediatek-logo.svg" alt=""></th>
                  <th>阿里</th>
                  <th>阿里巴巴控股有限公司</th>
              </tr>
          </table>
      </body>
      
    • 表单标签:

      • 在网页中负责数据采集功能=,如注册、登录等数据采集

      • 标签<form>

      • 表单项:不同类型的input元素、下拉列表、文本域

        • <input>:表单项,通过type属性控制输入形式

          • type取值

            text默认单行输入字段、password密码、radio单选按钮、checkbox复选框、file文件上传、date/time/datetime-local日期/时间/日期时间、number数组、email邮件、hidden隐藏域、submit/reset/button提交/重置/可点击按钮就

        • <select>:定义下拉列表

        • <textarea>:定义文本域

      • 属性:

        • action:规定当表单提交时向何处发送表单数据,url,默认提交到当前页面
        • method:规定发送表单数据的方式
          • get:在rul后面拼接表单数据,比如?username=xx&age=xx,url有长度限制,默认值
          • post:在消息体(请求体)中传递,参数大小无限制
      <body>
          <form action="" method="post">
              姓名:<input type="text" name="username"><br><br>
              密码:<input type="password" name="password"><br><br>
          
              性别:<label><input type="radio" name="gender" value="1"></label>
                  <label><input type="radio" name="gender" value="2"></label><br><br>
                  
              爱好:<label><input type="checkbox" name="hobby" value="java">java</label>
                  <label><input type="checkbox" name="hobby" value="c#">c#</label>
                  <label><input type="checkbox" name="hobby" value="python">python</label><br><br>
          
              图像:<input type="file" name="image"><br><br>
              生日:<input type="date" name="birthday"><br><br>
              时间:<input type="time" name="time"><br><br>
              邮箱:<input type="email" name="email"><br><br>
              年龄:<input type="number" name="age"><br><br>
                  
              学历:<select name="degree" id="">
                  <option value="">---------------请选择---------------</option>
                  <option value="1">大专</option>
                  <option value="2">本科</option>
                  <option value="3">硕士</option>
                  <option value="4">博士</option>
              </select><br><br>
          
              描述:<textarea name="description" id="" cols="30" rows="10"></textarea><br><br>
              <input type="hidden" name="id" value="1">
          
              <input type="submit" value="提交">
              <input type="reset" value="重置">
              <input type="button" value="按钮">
              <br>
          </form>
      </body>
      

CSS

  • 层叠样式表cascading style sheet,控制页面的样式style

  • css引入方式:

    • 行内样式:标签style属性中(不推荐)

      <h1 style="xxx;xxx;xxx">中国新闻网</h1>
      
    • 内嵌样式:style标签中(可以写在页面任何位置中,但通常写在head标签中)

      <style>
      	h1{
      		xxx:xxx;
      		xxx:xxx;
      	}
      </style>
      
    • 外联样式:单独的.css文件中(通过link标签在网页中引入

      h1{
      	xxx:xxx;
      	xxx:xxx:
      }
      <link rel="stylesheel" href="css/news.css">
      
  • 颜色表示:

    • 关键字
    • rgb:rgb(255,0,0)
    • 十六进制:#ff0000(红色,每两位表示一种颜色)
  • css选择器:用来选取需要设置样式的元素或标签

    • 元素选择器

      元素名称{
      	color:red;
      }
      h1{
      	color:red;
      }
      <h1>中国新闻网</h1>
      
    • id选择器

      #id属性值{
      	color:red;
      }
      #hid{
      	color:red;
      }
      <h1 id="hid">中国新闻网</h1>
      
    • 类选择器

      .class属性值{
      	color:red;
      }
      .cls{
      	color:red;
      }
      <h1 class="cls">中国新闻网</h1>
      
  • 实现正文排版——以新浪新闻为例

    • line-height设置行高
    • text-indent定义行内容缩进
    • text-align定义文本水平对齐方式
  • 盒子模型

    • 页面中所有元素(标签),都可以看作是一个盒子,盒子将页面元素包含在矩形区域内,通过盒子视角对页面布局

    • 盒子模型组成

      • 内容区域content
      • 内边距区域padding
      • 边框区域bound
      • 外边距区域margin

      image-20230813113216377

    h1{
        /* color: rgb(255, 0, 0); */
        color:#000000;
    }
    #sid{
        color: #7f7f7f;
        font-size: 14px;
    }
    .cls{
        color: #7f7f7f;
    }
    a{
        color: #000000;
        /* 去掉超链接下划线 */
        text-decoration: none;
    }
    p{
        text-indent: 35px;
        line-height: 40px;
    }
    .resize{
        margin: 0% auto;
        width: 100%;
    }
      
    #plast{
        text-align: right;
    }
    #content{
        width: 65%;
        margin: 0% auto;
    }
    

JS

JavaScript

  • 跨平台、面向对象的脚本语言(无需经过编译),控制网页行为、页面交互
  • 和Java是完全不同的语言,但是基础语法相似

js引入方式

  • 内部脚本:js代码定义在html网页中
    • 放在<script></script>之间
    • 一般放在body元素底部
  • 外部脚本:js代码定义在外部js文件中,引入到html页面中
    • <script>标签不能自闭合

js基础语法

  • 输出语句:
    • window.alert()写入警告框
    • document.write()写入HTML输出
    • console.log()写入浏览器控制台
  • 变量
    • var关键字variable声明变量:作用域大,全局变量;可以重定义
    • js是弱类型语言,变量可存放不同类型的值
    • let关键字声明变量:作用域代码块内有效;不允许重复定义
  • 数据类型、运算符、流程控制符
    • 数据类型:
      • 原始类型:number(整数、小数、NaN——not a num)、string、boolean、null(对象的占位符)、undefined
        • typeof运算符:获取数据类型
      • 引用类型:
    • 运算符:==和===都是全等,==会进行类型转换,===不会进行类型转换
    • 类型转换:
      • 字符串类型转数字,字面值不是数字,转为NaN,采用parseInt
      • 其他类型转boolean
        • number:0或NaN转false,其他转true
        • string:空字符转false,其他转true
        • null和undefined:均转为false

js函数

  • 通过关键字function定义
    • function functionName(参数1,参数2,...)
    • var functionName = function(参数1,参数2,...)
  • 形参不需要类型,返回值也不需要定义类型

js对象

  • 基础对象模型

    • Array

      • 定义:var arr=new Array(ele_list)var arr=[ele_list]

      • 访问:var ele=name[idx]

      • js数组长度可变、类型可以混合

      • 属性:length返回元素的数量

      • 方法:forEach(function(){})遍历每个defined的元素并调用一次传入的函数、push(ele_list)添加到末尾、splice(start,cnt)删除元素

        var arr=[1,2,3];
        arr[5]="你好";
        arr[7]=NaN;
        console.log(arr);
        console.log(arr.length);
        arr.forEach(function(e){
            console.log(e);
        })//也可以用箭头函数表示()=>{}
        
    • String
      • 定义:var str=“...”
      • 属性:length
      • 方法:charAt()返回指定位置的字符、indexOf()检索字符串、trim()取出字符串两边的空格、substring()提取两个指定索引之间的字符
    • JSON

      • js自定义对象:

        • 定义格式:var obname={attri1:val1,attri2:val2,attri3:function(arg[]){}};
        • 调用格式:obname.attributeobname.func()
      • json:JavaScript object notation,JavaScript对象标记法,描述js对象的文本

      • 语法简单,层次结构鲜明,多用于数据载体,在网络中数据传输

      • json的key必须用双引号

      • value的数据格式:数组、字符串、逻辑值、数组(方括号)、对象(花括号)、null

      • json字符串转为js对象var jsObject=JSON.parse(jsStr)

      • js对象转为json字符串var jsStr=JSON.stringify(jsObject)

        <script>
            // 定义json
            var jsonStr='{"name":"tom","age":18,"addr":["beijing","tokyo"],"son":{"name":"lee","age":7}}';
            document.writeln(jsonStr,"&nbsp&nbsp&nbsp");
            var jsObject=JSON.parse(jsonStr);
            document.writeln(jsObject.son.age);
        </script>
        
  • BOM浏览器对象模型

    • 概念:browser object model浏览器对象模型,允许JavaScript与浏览器对话,JavaScript将浏览器的各个组成部分封装成对象

    • 组成

      • window浏览器窗口对象:

        • 属性:
          • history对history对象只读引用

          • location用于串口或框架的location对象

          • navigator:对navigator对象只读引用

        • 方法:
          • alert()显示带有消息和确认按钮的警告框(print
          • confirm()显示带有消息、确认按钮和取消按钮的对话框
          • setInterval()按照指定毫秒级周期调用函数或计算表达式(计时器
          • setTimeout()指定毫秒数后调用函数或计算表达式
        var flag=window.confirm("您确认删除吗?")
        alert(flag);
        var i=0;
        setInterval(function(){
            i++;
            console.log(i);
        },2000);
        setTimeout(() => {
            alert(js);
        }, timeout);
        
      • location地址栏对象:

        • 使用window.location或location获取
        • 属性:href设置或返回完整的url
        alert(location.href);
        setTimeout(() => {
            location.href="https://www.baidu.com";
        }, 5000);
        
      • navigation浏览器对象、screen屏幕对象、history历史对象

  • DOM文档对象模型

    image-20230814110520197

    • 概念:document object model文档对象模型

    • 标记语言的各个组成部分封装成对应的对象(core DOM)

      • document整个文档对象
      • element元素对象
      • attribute属性对象
      • text文本对象
      • comment注释对象

      HTML DOM(对img和button封装)、XML DOM

    • JavaScript通过DOM,对HTML进行操作

      • 改变HTML元素的内容
      • 改变HTML元素的样式(css)
      • 对HTML DOM事件做出反映
      • 添加和删除HTML
    • document对象获取element元素对象的函数

      • id属性获得:var h1=document.getElemtnById('h1');
      • 标签名称获得:var divs=document.getElementByTagName('div')
      • name属性组获取:var hobbys=document.getElementByName('hobby')
      • class属性获取:var clss=document.getElementByClassName('cls')
      var ins=document.getElementsByName('hobby');
      alert(ins);
      var divs=document.getElementsByTagName('div');
      alert(divs);
      var h=document.getElementById('h');
      alert(h);
      
    • document属性

      • innerHTMLL:设置或返回元素内容,可以添加标签
      var cls=document.getElementsByClassName('cls');
      var cls0=cls[0];
      setTimeout(()=>{cls0.innerHTML="<h1>404 Not Found</h1>";},5000);
      
    • DOM实例

      通过getElement方法获取DOM对象,调用对象的属性

      var bool=true;
      var h;
      h=document.getElementById('h');
      var title;
      title=document.getElementById('title');
      var hobby;
      hobby=document.getElementsByName('hobby');
      setInterval(function(){
          bool=!bool;
          if(bool){
              h.src="https://www-file.huawei.com/-/media/corporate/images/home/logo/huawei_logo.png";
              for(let i=0;i<hobby.length;i++){
                  let t=hobby[i];
                  t.checked=true;
              }
              title.innerHTML="<h1><font color=#ff0000>调查问卷</font></h1>"
          }else{
              h.src="https://www.mediatek.cn/dist/mediatek-logo.svg";
              for(let i=0;i<hobby.length;i++){
                  let t=hobby[i];
                  t.checked=false;
              }
              title.innerHTML="<h1><font color=#ffff9f>调查问卷</font></h1>"
          }
      },3000)
      

js事件监听

  • 事件:HTML事件是发生在HTML元素上的“事情”,比如:

    • 按钮被点击
    • 鼠标移动到元素上
    • 按下键盘按钮
  • 事件监听:JavaScript可以在事件被侦测到时执行代码

    • 事件绑定

      • 通过HTML标签中事件属性绑定

        <input type="button" onclick="on()" value="btn1">
        <script>function on(){alert("clicked");}</script>
        
      • 通过DOM元素属性绑定

        <input type="button" id="btn" value="btn1">
        <script>
        var btn=getElementById('btn');
        btn.onclick=function(){alert("clicked");};
        </script>
        
    • 常见事件

      • onclick鼠标单击事件
      • onblur元素失去焦点
      • onfocus元素获得焦点
      • onload某个页面或图像加载完成
      • onsubmit当表单提交时触发该事件
      • onkeydown某个键盘的键被按下
      • onmouseover鼠标被移到某元素之上
      • onmouseout鼠标从某元素移开
    • 案例

      <div>
          <div id="title">
              <h1>
                  <font color=#000000>调查问卷</font>
              </h1>
          </div>
          <img id="h" onmouseover="overfun()" onmouseout="outfun()" 
               src="https://www-file.huawei.com/-/media/corporate/images/home/logo/huawei_logo.png" width="" height="">
          <br><br>
          <form action="" method="post" onsubmit="submitfun()">
              姓名:<input type="text" name="username" onblur="bfn()"  onfocus="ffn()" onkeydown="kydn()"><br><br>    
              <input type="submit" value="提交">
              <br>
          </form>
      </div>
      <script src="js/demon.js"></script>
      
      var overfun=function(){
          title.innerHTML="<h1><font color=#ff0000>调查问卷</font></h1>"
          console.log("over");
      }
      var outfun=function(){
          title.innerHTML="<h1><font color=#000000>调查问卷</font></h1>"
          console.log("out");
      }
      var submitfun=function(){
          alert("submit");
      }
      var bfn=function(){
          console.log("blur");
      }
      var ffn=function(){
          console.log("focus");
      }
      var kydn=function(){
          console.log("keydown");
      }
      

Vue

Vue2 文档

Vue2 API

  • 框架:半成品软件,可重用、通用的软件基础代码,基于框架开发,更加快捷、更加高效

  • Vue:前端框架,免除JavaScript中的DOM文档对象操作,简化书写

  • 基于MVVM(model-view-view_model)思想,决定数据的双向绑定,将变成的终点放在数据上

    image-20230814160420050

    model:数据模型,包含业务数据和数据处理方法

    view:视图层,只负责数据的展示,就是HTML的标签,或者说时DOM元素

    view_model:进行model和view的数据绑定,自动变化

  • image-20230814163542282

    <head>
        //引入vue.js文件
        <script src="js/vue.js"></script>
    </head>
    <body>
        //编写视图
        <div id="app">
            <input type="text" v-model="message"><br><br>//v-model绑定数据
            //插值表达式
        </div>
    </body>
    <script>
        //在js代码区域,创建vue核心对象,定义数据模型
        new Vue({
            el:"#app",
            data:{
                message:"hello vue"
            }
        })//插值的两个括号来自于vue对象的创建,第一层是vue对象的括号,第二层是data对象的括号,嵌套的很厉害
    </script>
    
    • 插值表达式

      • 形式:
      • 内容:变量、三元运算符、函数调用、算术运算
    • Vue的常用指令

      HTML标签上带有v-前缀的特殊属性,实现数据的自动绑定关联

      • v-bind:为HTML标签绑定属性值,如设置href、css样式等
      • v-model:在表单元素上创建双向的数据绑定
      • v-on:为HTML标签绑定事件

      • v-if、v-else-if、v-show:条件性渲染某元素
      • v-show:根据条件展示某元素,去辨别在于切换的时display属性的值

      • v-for:列表渲染,遍历容器的元素或者对象的属性
      <body>
          <div id="app">
              <!-- url绑定 -->
              <input type="text" v-model="url"><br>
              <a v-bind:href="url">百度</a><br><br>
              <!-- <a :href="url">百度</a> -->
          
              <!-- methods绑定 -->
              <input type="button" name="button" v-on:click="handle()"><br><br>
              <!-- <input type="button" name="btn" @click="handle()"> -->
          
              <!-- age绑定 -->
              <input type="text" v-model="age"><br>
              <span v-if="age<20">小于20</span>
              <span v-else-if="age**20">等于20</span>
              <span v-else="age>20">大于20</span><br>
          
              <span v-show="age**20">等于20</span><br><br>
          
              <!-- addrs绑定 -->
              <div v-for="addr in addrs"></div><br>
              <div v-for="(addr,indx) in addrs">:</div>
              <br><br>
          </div>
          
      </body>
      <script>
          new Vue({
              el:"#app",//标签id名
              data:{
                  age:20,
                  url:"https://www.baidu.com",
                  addrs:["北京","上海","广州","深圳","成都","杭州"]
              },//数据对象
              methods:{
                  handle:function(){
                      alert("clicked");
                  }
              }//方法对象
          })
      </script>
      
    • 通过vue完成表格渲染

      <body>
          <div id="app">
              <table border="1" cellspacing="0" width="60%">
                  <tr>
                      <th>编号</th>
                      <th>姓名</th>
                      <th>年龄</th>
                      <th>性别</th>
                      <th>成绩</th>
                      <th>等级</th>
                  </tr>
          
                  <tr align="center" v-for="(user,index) in users">
                      <td></td>
                      <td></td>
                      <td></td>
                      <td>                
                          <span v-if="user.gender**1"></span>
                          <span v-else="user.gender**2"></span>
                      </td>
                      <td></td>
                      <td>
                          <span v-if="user.score<60"><font color="red">不及格</font></span>
                          <span v-else if="user.score>=85">优秀</span>
                          <span v-else>及格</span>
                      </td>
                  </tr>
              </table>
          </div>
              
      </body>
      <script>
          new Vue({
              el:"#app",
              data:{
                  users:[
                      {name:"tom",age:20,gender:1,score:78},
                      {name:"rose",age:18,gender:2,score:86},
                      {name:"jerry",age:26,gender:1,score:90},
                      {name:"tony",age:30,gender:1,score:52}
                  ]//array对象
              }
          })
      </script>
      
  • vue的生命周期

    每触发一个生命周期事件,会自动执行一个生命周期方法(钩子)

    image-20230814195536862

    • beforeCreate创建前

    • created创建后

    • beforeMount载入前

    • mounted挂载完成后

      挂载完成后,Vue初始化成功,HTML页面渲染成功,发送请求到服务端,加载数据

      <body>
          <div id="app">
              <span></span>
          </div>
      </body>
      <script>
          new Vue({
              el:"#app",
              methods:{
                  handler:function(){alert("handler")}
              },
              mounted(){
                  alert("vue mounted")
              }//生命周期对象,当触发时执行
          })
      </script>
      
    • beforeUpdate更新前

    • updated更新后

    • beforeDestroy销毁前

    • destroyed销毁后

Ajax

  • asynchronous JavaScript and xml异步的js和xml

  • 作用:

    • 数据交换:通过Ajax可以个服务器发送请求,并获取服务器响应的数据
    • 异步交互:在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术
  • 原生Ajax

    <body>
        <input type="button" value="获取数据" onclick="getData()">
        <div id="div1">&nbsp</div>
    </body>
    <script>
        var getData=function(){
            // 创建xml的http请求
            var xmlHttpRequest=new XMLHttpRequest();
            // 发送异步请求
            xmlHttpRequest.open(
                'GET','http://127.0.0.1:3000/note.xml'
            );
            xmlHttpRequest.send();
            // 获取服务响应数据
            xmlHttpRequest.onreadystatechange=function(){
                if(xmlHttpRequest.readyState**4&&xmlHttpRequest.status**200){
                    document.write(xmlHttpRequest.responseText);
                }
            }
        }
    </script>
    
    1. 准备数据地址
    2. 创建XMLHttpRequest对象,用于和服务器交换数据
    3. 向服务器发送请求
    4. 获取服务器响应数据
  • Axios

    • 对原生Ajax封装,简化书写,快速开发

    • axios入门
      1. 引入axios.js文件
      2. 使用axios发送请求,并获取响应结果
      <body> 
          <input type="button" value="get" id="get" onclick="get()">
          <input type="button" value="post" id="post" onclick="post()">
      </body>
      <script>
          var get=()=>{
              axios({
                  methods:"get",
                  url:"http://127.0.0.1:3000/note"
              }).then((result)=>{
                  console.log(result);
              })//创建axios对象,生命对象的方法、url,执行回调函数
          }
          var post=()=>{
              axios({
                  methods:"post",
                  url:"http://127.0.0.1:3000/note",
                  data:"id=1"
              }).then((result)=>{
                  console.log(result);
              })//then成功回调函数
          }
      </script>
      
    • axios请求方式别名

      • axios.get(url[,config])
      • axios.delete(url[,config])
      • axios.post(data[,config])
      • axios.put(data[,config])

      后跟成功回调函数

    • axios案例

      动态加载表格,在vue对象挂载的时候触发钩子函数,发送axios请求

      <script>
          new Vue({
              el:"#app",
              data:{
                  users:[]
              },
              mounted(){
                  axios.get("http://127.0.0.1:3000/note").then(result=>{
                      this.users=result.data;
                  })
              }//当vue挂载时,触发js异步加载
          })
      </script>
      

前端工程化

接口文档:业务功能文档

image-20230815112133425

YApi:高效的api管理平台,为开发、产品、测试人员提供接口管理服务

  • API接口管理
  • Mock服务:模拟真实接口,生成接口模拟测试数据用于前端工程测试

前端开发

  • 模块化:js、css(模块化将html、js、css放在一个文件中,作为一个模块,分层嵌套组织)
  • 组件化:ui结构、样式、行为
  • 规范化:目录结构、编码、接口
  • 自动化:构建、部署、测试

vue-cli

  • vue-cli:vue提供的脚手架,快速生成vue的项目模板,使用

  • vue-cli功能:

    • 统一的目录结构
    • 本地调试
    • 热部署
    • 单元测试
    • 集成打包上线
  • 依赖环境:nodejs(类似于jdk对于java,conda对于python)

    • 下载nodejs,配置全局安装路径npm set prefix
    • 设置nodejs系统变量
    • 配置taobao镜像源后,安装包依赖npm install下载vue-cil包
    • 使用vue ui创建vue项目
  • vue项目-目录结构

    project-root/
    │
    ├── public/
    │   ├── index.html                 # 主页面HTML文件
    │   ├── favicon.ico                # 网站图标
    │   └── ...
    │
    ├── src/
    │   ├── assets/                    # 资源文件目录 (图片、样式等)
    │   ├── components/                # Vue组件目录
    │   ├── views/                     # 页面视图目录
    │   ├── App.vue                    # 应用根组件
    │   └── main.js                    # 应用入口文件
    │
    ├── static/                        # 静态文件目录 (不会被webpack处理)
    │
    ├── node_modules/                  # 依赖模块目录 (自动生成)
    │
    ├── package.json                   # 项目配置文件
    ├── babel.config.js                # Babel配置文件
    ├── vue.config.js                  # Vue CLI配置文件
    └── README.md                      # 项目说明文件
      
    
    • node_modules整个项目的依赖包

    • public存放项目的静态文件
      • index.html默认首页

        <noscript>
            <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app"></div>//调用vue的id
        
    • src存放项目的源代码
      • assets静态资源

      • components可重用组件

      • router路由配置

      • views视图组件(页面)

        • main.js入口js文件

          import Vue from 'vue'
          import App from './App.vue'//引入vue文件
          import router from './router'
          import ElementUI from 'element-ui'
          import 'element-ui/lib/theme-chalk/index.css'
                  
          Vue.config.productionTip = false
          Vue.use(ElementUI)
                  
          new Vue({
            router,
            render: h => h(App)//连接App.vue
          }).$mount('#app')//将vue挂载到#标签上
          
        • App.vue入口页面,根组件

          • template模板部分,生成HTML代码
          • script脚本部分,控制模板的数据来源和行为
          • style样式部分
          <template>//template后一定要打上div标签
            <div>//相当于省略的<div #filename>
              <h1></h1>//引用data
              <element-view></element-view>
          //引入ElementView.vue,将html结构模块化
            </div>
          </template>
                  
          <script>
          //使用到element-view后自动importElementView
          import ElementView from './views/element/ElementView.vue'
          export default {//默认导出vue对象
              //一个完整的vue.js对象
              //省略了ele,因为在单个文件中已经默认
            	components: { ElementView },
              //声明当前vue组成包含ElementView,ElementView实现具体在其vue文件中
              data () {
                  return {
                      data1 : "",
                      data2 : ""
                  }
              },
              //声明返回数据,相当于data:{},作用域局限于当前vue
              methods : {
                  function1 : function(){},
                  function2 : function(){}
              }//声明返回方法,作用域局限于当前vue
          }//默认导出vue,相当于new vue({ele:"",data:{},methods:{}})
          </script>
                  
          <style>
          </style>
          
    • package.json模块基本信息,项目开发所需要的模块、版本信息

    • vue.config.js保存vue配置文件,如代理、端口代理

    index.html=>main.js=>App.vue=>ElementView.vue

    js=>.$mount=>render=>compnent

  • vue项目运行:npm run server

element

  • 使用npm在vue-project目录下安装element
  • 在main.js中引入包
  • 在src/views目录下新建element文件夹,管理element.vue,三部分组成
    • template、script(export default)、style
  • 常用组件:https://element.eleme.io/#/zh-CN/component/installation
    • 直接在vue文件中粘贴就可以用
    • button、table、pagination分页(通过分页触发事件)、dialog对话框(button触发syn信号)、form表单(使用v-model将input绑定到data中的form)
  • element案例
    1. 创建页面,完成页面的整体布局规划
    2. 布局各个部件的组件实现
    3. 列表数据的异步加载,并渲染展示

vue路由

  • 前端路由:url中的hash(#号)与组件之间的对应关系

  • vue router

    • vue的官方路由

    • 组成:

      • vueRouter:路由器类,根据路由请求,在路由视图中动态渲染选中的组件

        1. 在/src/router/index.js中声明routes数组
        2. 并一次创建router对象,并导出
      • <router-link>:请求连接组件,浏览器会解析成<a>

        在组件中引用,类似于超链接

      • <router-view>:动态视图组件,用来渲染展示与路由路径对应的组件

        在App.vue中引用

      image-20230816154745833

打包部署

  • nginx是一款轻量级的web服务器/反向代理服务器/电子邮件(IMAP/POP3),占用内存少,并发能力强
  • nginx目录结构:
    • conf:配置文件目录,可以修改端口号
    • html:静态资源文件目录,将/disk下的文件放入该目录
    • logs:日志文件目录
    • temp:临时文件目录
    • nginx.exe:默认本机80号端口,netstat -ann | findStr 80

maven

  • apache(最大的开源软件基金会)下的一个开源项目,用于管理和构建Java项目的工具

  • 基于项目对象模型POM的概念,利用一小段信息来管理项目的构建

    image-20230816210024542

  • 仓库:用于存储资源,管理jar包

    • 本地仓库
    • 中央仓库:maven团队维护
    • 远程仓库:私服
  • maven作用

    • 依赖管理:管理项目依赖的jar包,避免版本冲突问题,xml配置文件+联网
    • 统一项目结构:提供标准统一的项目结构,适配各种类型的ide
    • 项目构建:标准跨平台的自动化项目构建方式,从清理、编译、测试、打包、发布标准化,只需要使用maven命令
  • maven项目目录结构:

    project-root/
    │
    ├── src/
    │   ├── main/
    │   │   ├── java/                  # 主要Java源代码目录
    │   │   ├── resources/             # 主要资源文件目录
    │   │   └── webapp/                # Web应用资源目录 (仅适用于Web项目)
    │   │
    │   └── test/
    │       ├── java/                  # 测试用例Java源代码目录
    │       └── resources/             # 测试用例资源文件目录
    │
    ├── target/                        # 构建输出目录 (自动生成)
    │
    ├── pom.xml                        # Maven项目配置文件
    ├── README.md                      # 项目说明文件
    └── .gitignore                     # Git版本控制忽略文件列表
    
  • maven安装步骤:

    1. 解压
    2. 配置本地仓库、配置阿里云私服配置环境变量
    3. 安装maven插件,创建maven项目,配置maven标识

    maven目录:

    1. bin:mvn运行脚本
    2. boot:maven类加载器框架
    3. conf:配置文件
    4. lib:maven运行需要的java类库

    创建maven项目:name项目名称、location项目路径、groupId组织名、artifactId模块名、version版本号

  • maven坐标:资源的唯一标识,通过该坐标唯一确定资源位置

    • groupId定义当前maven隶属组织名称,域名反写,com.itheima
    • artifactId定义当前maven项目名称,通常是模块名称,order-service
    • version定义当前项目版本号
  • 依赖管理

    • 依赖配置:编写标签,引入模块maven坐标

    • 依赖传递

      image-20230817152805912

    • 排除依赖:在标签中引入标签,中断传递依赖

    • 依赖范围:依赖的jar包,默认情况下可以在任何地方使用,通过设置其作用范围

      • 主程序范围有效main
      • 测试程序范围有效test
      • 是否参与打包运行package

      image-20230817154200318

    • 生命周期

      maven有三套项目独立的生命周期

      • clean:清理工作

      • default:核心工作,同一套生命周期,运行后面的会运行前面的,

        这些生命周期依赖插件plugin,如:

        • 编译compile:移除上一次构建生成的文件
        • 测试test:编译项目源代码
        • 打包package:使用适合的单元测试框架运行测试juint
        • 安装install:将编译后的文件打包,如jar、war
        • 部署deploy:安装项目到本地仓库
      • site:生成报告、发布站点

Web入门-SpringBootWeb

  • Spring发展到今天已经形成了一种开发生态圈,Spring提供了若干个子项目,每个项目完成特定的功能

    image-20230817162455324

  • Spring Boot可以非常快速的构建应用程序,简化开发,提高效率

  • Spring Boot安装:

    1. jdk、maven先在vscode中安装对应插件并配置好
    2. 安装spring boot插件,选择>spring initializr,创建maven项目
    3. 设置springboot版本、语言、maven标识、打包方式、jdk版本、依赖
  • Spring BootWeb快速入门

    1. 创建请求处理类HelloController,添加请求处理方法hello,并添加注解

      package com.springboot.springboottest.controller;
           
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
           
      @RestController//标识请求处理类
      public class HelloController {
          @RequestMapping("/hello")//标识处理的请求
          public String hello(){
              System.out.println("hello world");
              return "hello world";
          }
      }
      
    2. 运行启动类,打开浏览器测试

      package com.springboot.springboottest;
           
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
           
      @SpringBootApplication//启动类 --启动springboot工程
      public class SpringbootTestApplication {
           
      	public static void main(String[] args) {  
      		SpringApplication.run(SpringbootTestApplication.class, args);
      	}
           
      }
      

Web入门-HTTP协议

  • HTTP概述:浏览器和服务器传输数据的协议

    特点:

    1. 基于TCP:面向连接,安全
    2. 基于请求响应模型:一次请求对应一次响应
    3. 无状态协议:对事务处理没有记忆能力,每次请求响应都是独立的
      • 优点:速度快
      • 缺点:多次请求间不能共享数据
  • HTTP请求协议

    请求头:

    GET / HTTP/1.1	//请求方式 请求路径 协议和协议版本
    Host: www.example.com	
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    
    POST /api/login HTTP/1.1
    Host: www.example.com
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
    Accept: application/json
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Content-Type: application/json
    Content-Length: 46
    Connection: keep-alive
      
    {
      "username": "user123",
      "password": "password123"
    }
    
    请求头字段 含义
    Accept 告诉服务器客户端可以接受的媒体类型。
    Accept-Encoding 告诉服务器客户端支持的内容编码方式,如gzip、deflate等。
    Accept-Language 告诉服务器客户端首选的语言,以便服务器返回合适的语言版本。
    Cache-Control 控制缓存行为,如no-cache、max-age等。
    Connection 控制是否保持连接,如keep-alive、close。
    Content-Length 请求体的长度,以字节为单位。
    Content-Type 请求体的媒体类型,如application/json、text/html等。
    Cookie 包含之前由服务器设置的cookie信息。
    Host 请求的主机名,用于虚拟主机的情况下。
    If-Modified-Since 与服务器上资源的最后修改时间比较,用于条件性请求。
    Referer 表示请求的来源URL,用于跟踪用户导航。
    User-Agent 标识客户端的用户代理,如浏览器名称和版本。
    Authorization 在进行身份验证时,包含用户凭据。
    Origin 表示请求的源,用于跨域请求。
    Upgrade-Insecure-Requests 告诉服务器将非安全连接升级为安全连接,用于HTTPS转换。

    请求体:

    • GET请求参数在请求行,没有请求体
    • POST请求参数在请求体,请求大小没有限制
  • HTTP响应协议

    HTTP/1.1 200 OK //传输协议和版本 状态码
    Date: Mon, 16 Aug 2023 12:00:00 GMT
    Server: Apache/2.4.41 (Unix)
    Content-Length: 1234
    Content-Type: text/html; charset=UTF-8
      
    <!DOCTYPE html>
    <html>
    <head>
      <title>示例页面</title>
    </head>
    <body>
      <h1>Hello, World!</h1>
      <p>This is an example response.</p>
    </body>
    </html>
    
    状态码 含义
    1xx 响应中
    2xx 成功
    3xx 重定向
    4xx 客户端错误
    5xx 服务器错误
    响应头字段 含义
    Content-Type 响应主体的媒体类型。
    Content-Length 响应主体的长度,以字节为单位。
    Date 响应发送的日期和时间。
    Server 服务器软件的名称和版本信息。
    Last-Modified 资源最后修改的日期和时间。
    ETag 资源的标识符,用于缓存控制。
    Cache-Control 控制缓存行为,如no-cache、max-age等。
    Expires 指定资源的过期时间。
    Set-Cookie 在响应中设置Cookie。
    Location 重定向时指定新的URL。
    Content-Encoding 响应主体的内容编码方式,如gzip、deflate等。
    Content-Disposition 指示浏览器如何显示响应主体。
    Access-Control-Allow-Origin 允许跨域请求的源。
    WWW-Authenticate 要求客户端提供认证凭据。
    X-Powered-By 指定服务器技术信息。
  • HTTP协议解析

    • 在服务端解析HTTP请求,并做出响应
    public class Server {
        public static void main(String[] args) throws IOException {
            ServerSocket ss = new ServerSocket(8080);
            System.out.println("server is running...");
            while (true) {
                Socket sock = ss.accept();
                System.out.println("conected from"+sock.getRemoteSocketAddress());
                Thread t=new Handler(sock);
                t.start();
            }
        }
    }
      
    class Handler extends Thread {
        Socket sock;
      
        public Handler(Socket sock){
            this.sock=sock;
        }
      
        public void run(){
            try(InputStream input=this.sock.getInputStream();OutputStream output =this.sock.getOutputStream()){
                handle(input,output);
            }catch(IOException e){}
            System.out.println("client disconnected.");
        }
      
        private void handle(InputStream input,OutputStream output)throws IOException{
            BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
            boolean requestOk=false;
            String first=reader.readLine();
            if(first.startsWith("GET / HTTP/1.")){
                requestOk=true;
            }
            for(;;){
                String header=reader.readLine();
                if(header.isEmpty()){
                    break;
                }
                System.out.println("header");
            }
            System.out.println(requestOk?"response ok":"response error");
      
            if(!requestOk){
                writer.write("HTTP/1.0 404 Not Found");writer.write("Content-Length: 0\r\n");writer.write("\r\n");
                writer.flush();
            }else{
                InputStream is=Server.class.getClassLoader().getResourceAsStream("static/GET-POST.html");
                BufferedReader br=new BufferedReader(new InputStreamReader(is));
                StringBuilder data=new StringBuilder();
                String line=null;
                while((line=br.readLine())!=null){
                    data.append(line);
                }
                br.close();
                int length=data.toString().getBytes(StandardCharsets.UTF_8).length;
                writer.write("HTTP/1.1 200 OK\n\r");writer.write("Connection: keep-alive\r\n");writer.write("Content-Type: text/html\r\n");writer.write("Content-Length: "+length+"\r\n");writer.write("\r\n");writer.write(data.toString());
                writer.flush();
            }
        }
    }
    

Web入门-Tomcat

  • web服务器:软件程序,对HTTP协议的操作进行封装,使得程序员不用对协议进行操作,让Web开发更加便捷,主要功能是“提供往上信息浏览服务”

  • Tomcat

    • apache软件基金会的一个核心项目,开源免费的轻量级web服务器
    • 支持servlet、jsp和少量JavaEE规范
    • Java EE:java企业版,包含13项技术规范:JDBC、JNDI、EJB、RMI、JSP、Servlet、XML、JMS、Java IDL、JTS、JTA、JavaMail、JAF
    • tomcat也称为web容器、servlet容器,servlet程序依赖tomcat才能运行
    tomcat/
    │
    ├── bin/            # 可执行脚本和命令文件
    │   ├── startup.sh   # 启动Tomcat的脚本 (Linux/Unix)
    │   ├── shutdown.sh  # 停止Tomcat的脚本 (Linux/Unix)
    │   ├── catalina.bat # 启动Tomcat的脚本 (Windows)
    │   └── shutdown.bat # 停止Tomcat的脚本 (Windows)
    │
    ├── conf/           # 配置文件
    │   ├── server.xml  # Tomcat服务器配置
    │   ├── web.xml     # 全局Web应用配置
    │   └── ...         # 其他配置文件
    │
    ├── lib/            # Tomcat和Web应用的共享类库
    │
    ├── logs/           # 日志文件目录
    │
    ├── temp/           # 临时文件目录
    │
    ├── webapps/        # Web应用目录
    │   ├── ROOT/       # 默认的ROOT应用
    │   ├── myapp1/     # 自定义的Web应用1
    │   ├── myapp2/     # 自定义的Web应用2
    │   └── ...         # 其他Web应用目录
    │
    ├── work/           # JSP编译和临时文件目录
    │
    └── logs/           # Tomcat日志文件目录
    
  • tomcat安装:

    解压即用,需要修改字符编码,修改端口号,使用netstat | findstr 配合web服务器日志查看端口占用的情况

  • http默认端口号80

  • tomcat部署项目:将项目放到webapps目录下

  • SpringBootWeb入门程序解析

    • spring-boot-start-parent包含了启动父依赖
    • spring-boot-start-web包含web应用开发需要的常见依赖
    • spring-boot-start-test包含了单元测试需要的常见依赖
    • 基于springboot开发的web程序,使用了内嵌的tomcat服务器

请求响应

image-20230818140435644

image-20230818140303713

  • 请求对象HttpServletRequest:获取请求数据
  • 响应对象HttpServletResponse:设置响应数据、
  • BS架构(browser/server)浏览器/服务器架构模式,客户端只需要浏览器,应用程序的逻辑和数据存储在服务端
  • CS架构(client/server)客户端/服务器架构模式

请求

  • postman:网页调试与发送网页HTTP请求的chrome插件

    作用:后端接口测试 ,对于本地测试

  • 使用方法:需要下载desktop,web版使用云端代理,创建workplace

  • 简单参数的请求

    • 原始方式:在web程序中,通过HttpServletRequest对象及其getParam(paramName)方法手动获取get请求参数
    • springboot方法:springboot自动对get请求参数进行转化,只需要保证请求参数名和函数形参名相同
      • @RequestController请求处理类、@RequestMapping()请求映射方法、
      • @RequestParam()指定映射的参数,请求参数名和函数形参名不同
  • 实体参数的请求

    • 简单实体对象:请求参数名和形参对象属性名相同,定义POJO接收
    • 复杂实体对象:请求参数名用dot来区分多层次的对象
    • 负责接收的实体对象,需要定义get方法并重写toString方法,属性名相同,即可通过POJO接收
  • 数组集合参数的请求

    • 请求参数名和形参数组名称相同,且请求参数多个,定义数组类型形参即可接收参数
    • 数组:请求参数和形参名称相同,直接使用数组封装
    • 集合list:请求参数和形参名称相同,通过@RequestParam注解绑定参数关系
  • 日期参数的请求

    • 使用@DateTimeFormat注解完成日期格式的转换
  • Json参数

    • json数据键名和形参对象的属性名相同,定义POJO类型即可接收参数
    • 使用@RequestBody注解
  • 路径参数

    • 通过URL直接传递参数,使用{…}来标识路径参数,使用@PathVariable获取路径参数
// 原始方式
// @RequestMapping("/sampleParam")
// public String sampleParam(HttpServletRequest request){
// String name=request.getParameter("name");
// String ageStr=request.getParameter("age");
// int age=Integer.parseInt(ageStr);
// System.out.println(name+":"+age);
// return "OK";
// }

// springboot方式
@RequestMapping("/sampleParam")
public String sampleParam(@RequestParam(name = "name", required = true) String usrname, Integer age) {
    System.out.println(usrname + ":" + age);
    return "OK";
}
// 实体请求简单方式
@RequestMapping("/samplePojo")
public String samplePojo(User user) {
    System.out.println(user);
    return "OK";
}
// 数组请求简单方式
@RequestMapping("/arrayParam")
public String arrayParam(String[] hobby) {
    System.out.println(Arrays.toString(hobby));
    return "OK";
}
// 集合请求简单方式
@RequestMapping("/listParam")
public String listParam(@RequestParam List<String> hobby) {
    System.out.println(hobby);
    return "OK";
}
// 日期请求简单方式
@RequestMapping("/dateParam")
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime) {
    System.out.println(updateTime);
    return "OK";
}
// json请求简单方式
@RequestMapping("/jsonPojo")
public String jsonPojo(@RequestBody User user) {
    System.out.println(user);
    return "OK";
}
// 路径请求简单方式
@RequestMapping("/path/{id}/{name}")
public String pathParam(@PathVariable Integer id, @PathVariable String name) {
    System.out.println(id + ":" + name);
    return "OK";
}

响应

  • @ResponseBody

    • 类型:方法注解、类注解
    • 位置:Controller方法上/类上
    • 作用:将方法返回值直接响应,如果返回值类型是实体对象/集合,将会转换为JSON格式响应
    • 说明:@RestController = @Controller + @ResponseBody;组合注解
  • 统一响应结果

    result:{"code":1,"msg":"success","data":"hello"}

    image-20230818193239298

  • 请求响应案例

    1. 在pol.xml中引入dom4j依赖,用于解析xml
    2. 引入解析xml的工具类xmlParserutils、实体类emp、xml文件emp.xml
    3. 引入静态页面文件
    4. 编写controller程序,处理请求,响应数据
  • 响应中出现的跨域请求问题CORS

    • 跨域,是因为受到了同源策略的限制,同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致
    • 浏览器出于安全的考虑,使用XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略
    • SpringBoot跨域请求处理方式
      • Controller层在需要跨域的类或者方法上加上注解@CrossOrigin
      • 增加一个配置类,CrossOriginConfig.java

分层解耦

  • 三层架构(面向接口)

    • controller控制层:接收前端请求、对请求处理、响应数据
    • service业务逻辑层:具体事务逻辑
    • dao数据访问层(data access object持久层):数据访问操作,增删改查

    image-20230818213748161

  • 分层解耦

    • 内聚:软件各个功能模块内部的功能联系(高内聚–增加功能联系)
    • 耦合:衡量软件中各个层/模块之间的依赖、关联程度(低耦合–降低依赖关联)

    image-20230818214836047

    • 实现高内聚低耦合:
      • 控制反转inversion of control(IOC):对象的创建控制权从程序自身转移到外部(容器)
      • 依赖注入dependency injection(DI):容器为应用程序提供运行时,所依赖的资源,称为依赖注入
      • Bean对象:IOC容器中创建、管理的对象,称为bean对象
  • IOC & DI入门

    • service层和Dao层的实现类,交给IOC容器管理,在对象声明前使用注解@Component

    • 为Controller层和service层注入运行时,依赖的对象,在成员对象前使用注解@Autowired

    • 运行测试,对于需要解耦的对象注释掉@Component

  • IOC详解

    • @Controller,衍生注解,标注在控制器controller类上

    • @Service,标注在业务类Service类上

    • @Repository,标注在数据访问类Dao上,由于和mybatis整合,用的少

    • @Component,工具类

      • 通过click@注解可以看到注解标注层次
  • DI详解

    • @Autowired注解默认按照类型进行,如果存在多个相同类型的bean,报错
    • 通过以下注释解决:
      • @Primary,在被依赖的对象声明之前(被使用者)
      • @Qualifier,在依赖注入的对象的成员之前,加载@Autowired上(使用者)
      • @Resource,不用和@Autowired一起用
        • @Autowired是spring提供给的,按照类型注入
        • @Resource是JDK提供的,按照名称注入

MySQL

Mybatis

https://mybatis.net.cn/

  • 持久层Dao框架,用于简化JDBC开发,也属于apache的开源项目,目前集成在springboot中

  • Mybatis使用流程

    • 准备工作:创建springboot工程、数据库表user、实体类User

    • 引入mybatis依赖,配置application的properties,四要素

      • 引入mysql驱动器
      • 数据库连接url(主机ip、端口号、数据库名)
      • 连接用户名、密码(连不上就重置密码)
    • 编写SQL语句(注解/XML)

      • 运行时@Mapper,自动生成接口的实现类对象(代理对象),并将对象交割IOC容器管理,这时候接口可以直接被依赖注入的方式调用生成对象
      • @Select(“sql语句”)声明查询语句,查询结果传递给实体对象
      @Mapper
      public interface EmpMapper {
          @Delete("delete from emp where id = #{id}")
          public int delete(Integer id);
          
          @Select("select * from emp")
          public List<Emp> select();
          
          @Options(keyProperty = "id",useGeneratedKeys = true)
          @Insert("insert into emp(username,password) values(#{username},#{password})")
          public void insert(Emp emp);
          
          @Update("update emp set gender = #{gender},deptId = #{deptId } where id = 6")
          public void update(Emp emp);
      }
          
      @SpringBootTest
      class SpringbootTestApplicationTests {
      	@Autowired
      	private EmpMapper empMapper;
              
      	@Test
      	public void testList2() {
      		int delete = empMapper.delete(4);
      		System.out.println(delete);
      		List<Emp> empList = empMapper.select();
      		empList.stream().forEach(user -> {
      			System.out.println(user);
      		});
      	}
          
      	@Test
      	public void testList3() {
      		Emp e = new Emp();
      		e.setUsername("joe512");
      		e.setPassword("356pass");
      		empMapper.insert(e);
      		System.out.println(e.getId());
      	}
          
      	@Test
      	public void testList4() {
      		Emp e = new Emp();
      		e.setGender("Male");
      		e.setDeptId(6);
      		empMapper.update(e);
      		//System.out.println(e.getId());
      }
      
  • 配置idea的sql提示,将数据库连接到idea上

  • JDBC

    • java database connectivity,使用java语言操作关系型数据库的API
    • sun公司定义的一套操作所有关系型数据库的规范,即接口
    • 各个数据库厂商实现接口,提供数据库驱动jar包,比如之前的mysql-connector-java包
    • 用户使用这套接口JDBC编程,底层实现是驱动jar包中的实现类
  • JDBC使用流程

    1. 注册驱动,声明使用的数据库类型
    2. 获取连接对象Connection,封装url、usrname、password
    3. 获取执行sql的对象Statement,执行SQL,返回结果
    4. 封装结果数据,返回值以字段存在
  • JDBC缺点:硬编码、封装繁琐、多次请求释放造成资源浪费和性能下降

    硬编码:将数据直接写死到程序或者其他可执行对象的源代码中

    Springboot+Mybatis:application.properities和mapper接口,对JDBC封装的框架

    • 驱动连接写入配置文件
    • 自动化封装对象

    • spring.datasource使用数据库连接池技术管理连接,连接复用,类似于线程池
  • 数据库连接池

    • 容器,分配、管理数据库连接(connection),对连接复用
    • 释放空闲时间超过最大空闲时间的连接,避免持续占有连接造成数据库连接遗漏
    • 标准接口:
      • DataSource,官方sun提供的数据库连接池接口,第三方组织实现接口
      • 功能:获取链接
    • 有多种连接池产品:Hikari(springboot默认)、Druid(ali开源,添加依赖可用)
  • Lombok

    • 使用的java类库,通过注解的形式自动生成构造器、gettr/setter、equals、hashcode、toString等方法,可以自动化生成日志变量,简化Java开发,提高效率

    • @Data提供了综合的代码生成功能(包含了@Setter/@Getter/@ToStrings)

      @NoArgsConstructor为实体类生成无参构造器方法

  • Mybatis配置SQL语句——基于注解@

    ——按照业务需求划分

    • 参数占位符

      • #{…}替换成?,生成预编译sql,传递参数使用
      • ${…}直接拼接,存在注入风险,对表名、列表动态设置使用
    • 日志查看:在application.properties中,指定mybatis日志输出到控制台

      • =>输出预编译SQL,性能更高、防止SQL注入
      • SQL注入:通过操作输入数据修改原先定义好的sql语句
        1. java --jar xxx.jar启动jar包,打开对应的网页
        2. 通过增加select条件的方式sql注入' or '1' = '1
        3. 预编译的语句将传参作为String,而不是字符串拼接,避免注入
      • mysql预编译:对语法检查、语法优化、编译的过程缓存
    • 数据封装

      • 实体类属性名和数据库表查询返回的字段名一致,mybatis自动封装、

        • 在@注解的sql中给字段起别名

        • 通过@Results注解手动映射封装

          @Result({
          	@Result(column="",propetry=""),
          	@Result(column="",propetry=""),
          	@Result(column="",propetry="")
          })
          
        • 开启mybatis驼峰命名映射自动开关

    • 删除:sql语句,接口方法@Delete()

    • 插入:@Insert,传入对象

    • 主键返回:数据添加成功后,需要获取插入数据库数据的主键

      @Options(keyProperty=”id”,useGeneratedKeys=true),插入后主键封装回对象中

    • 更新:

      • 获取主键,实现回显@Selectselect * from emp where xxx
      • 根据回显id,修改信息@Updateupdate emp set .. where id = #{id}
    • 查询:

      • 使用like进行模糊查询,用concat进行字符串拼接,避免${..}的使用
      • springboot 1.x中,使用@Param(““)实现参数名映射为字段名
  • Mybatis配置SQL语句——基于XML映射配置文件

    • 规范

      • 映射文件名称和mapper接口名称一致,映射文件和接口放在相同包下(同胞同名,接口放java,配置文件放resource)
      • 映射文件的namespace属性为mapper接口一致
      • 映射文件的sql语句id和mapper接口的方法名一致,返回类型一致

      image-20230822191311110

  • 动态SQL——基于标签实现

    • 随着用户输入或者外部条件变化而变化的SQL语句

    • <if test != null>如果条件成立,则拼接SQL

      • 在select中,字段有值则判断
      • 在update中,字段有值则更新
    • <where>只有在子元素有内容的情况下才插入where子句,自动去除子句开头的AND或OR

      <set>动态地在行首插入SET关键字,并删掉额外的逗号

    • <foreach>批量处理,属性包括collection、item、separator、open、close

    • <sql><include>前者通过属性id定义可重用的SQL片段,后者通过属性refid指定包含SQL片段

@Test
public void testList5() {
	List<Emp> empList = empMapper.list();
	empList.stream().forEach(emp -> {
		System.out.println(emp);
	});
}

@Test
public void testList6() {
	Emp e = new Emp();
	e.setName("");
	e.setGender("Male");
	List<Emp> empList = empMapper.list2(e);
	empList.stream().forEach(emp -> {
		System.out.println(emp);
	});
}

@Test
public void testList7() {
	List<Integer> ids = Arrays.asList(8, 7, 6);
	empMapper.list3(ids);
}
<mapper namespace="com.springboot.springboottest.pojo.EmpMapper">
  <!-- select有返回类型,记录单条记录返回值 -->
  <select id="list" resultType="com.springboot.springboottest.pojo.Emp"> 
    select * from emp 
  </select>

  <select id="list2" resultType="com.springboot.springboottest.pojo.Emp"> 
    select * from emp 
    <where>
    <if test="name!=null">
      name like concat('%',#{name},'%')
    </if> 
    <if test="gender!=null">
      and gender = #{gender}
    </if>
    </where>
  </select>

  <select id="list3"> 
    delete from emp where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
      #{id}
    </foreach>
  </select>
</mapper>