JavaWeb 速通Ajax

目录

一、Ajax快速入门

        1.基本介绍 : 

        2.使用原理 : 

二、Ajax经典入门案例

        1.需求 : 

        2.前端页面实现 : 

        3. 处理HTTP请求的servlet实现

        4.引入jar包及druid配置文件、工具类 : 

        5.Domain层实现 : 

        6.DAO层实现 : 

        7.Service层实现 : 

        8.运行测试 : 

三、JQuery操作Ajax

        1 $.ajax({})函数 : 

        2 $.get()和$.post()函数 : 

        3 $.getJSON()函数 : 


一、Ajax快速入门

        1.基本介绍 : 

        (1) AJAX,全称"Asynchronous JavaScript And XML",指异步JavaScript和XML。Ajax是一种支持浏览器异步发起请求(可以指定发送的数据),以及页面局部更新的技术。

        (2) Ajax的常见应用场景如下——

                1> 搜索引擎根据用于输入的关键字,自动提示检索关键字。

                2> 动态加载数据,按需取得数据。(树形菜单、联动菜单......等,eg : 选择省份后自动加载出对应的市县)

                3> 电子商务应用。(购物车,邮件订阅)

                4> 改善用户体验。(输入内容前提示,带进度条的文件上传)

                5> 访问第三方服务。(访问搜索服务,rss阅读器)

                6> 页面局部刷新。(网站展示数据的实时刷新)

        2.使用原理 : 

                传统的web数据通信方式的弊端——
                表单提交数据时,默认提交将该表单的全部数据都提交给服务端,数据量大且无意义。
                在服务端未给出HTTP响应之前,浏览器前端会一直处于等待状态,或者被挂起。
                无法进行页面的局部刷新,用户体验感较差。

                使用Ajax的web数据通信方式的原理示意图如下——

                Ajax数据通信方式与传统通信方式最大的区别在于,浏览器端并不是直接向服务器端发送HTTP请求,而是要先经过Ajax引擎对象——XMLHttpRequest对象的处理(浏览器内置对象),再发出请求。服务器端仍然是接收数据并做出相应处理,之后再通过HTTP响应将数据返回给浏览器,返回的数据格式可以是XML,JSON,或者是普通文本。浏览器接收到服务端的响应后,Ajax会解析返回的数据,并将解析之后的数据渲染到页面的对应元素中,以实现页面的局部刷新。

                通过Ajax发送HTTP请求的优点——
                可以通过XMLHttpRequest对象,发送指定数据,数据量小且速度快。
                XMLHttpRequest对象是异步发送数据,在服务端没有回送HTTP响应之前,浏览器不需要等待,可以继续操作。
                实现了页面的局部刷新,提高了用户的体验。

                PS : XMLHttpRequest对象有几个重要的属性,如下表所示 : 

属性描述
onload定义接收到(加载)请求时要调用的函数。
onreadystatechange定义当 readyState 属性发生变化时调用的函数。
readyState

保存 XMLHttpRequest 的状态。

  • 0:请求未初始化
  • 1:服务器连接已建立
  • 2:请求已收到
  • 3:正在处理请求
  • 4:请求已完成且响应已就绪
responseText以字符串形式返回响应数据。
responseXML以 XML 数据返回响应数据。
status

返回请求的状态号

  • 200: "OK"
  • 403: "Forbidden"
  • 404: "Not Found"
statusText返回状态文本(比如 "OK" 或 "Not Found")

二、Ajax经典入门案例

        1.需求 : 

                界面效果如下:

                编写一个用户登录页面,要求对用户名进行校验 (对用户名校验的HTTP请求要借助Ajax来发送!),若用户名已经存在于MySQL数据库中的user_demo用户表中,提示用户名重复、不可用,并以JSON格式的字符串返回该用户的信息;反之,则提示用户名可用。
                要求按照“Domain层 --> DAO层 --> Service层”的三层结构来实现业务逻辑。
                要求编写一个servlet用于处理客户端的HTTP请求,在servlet中利用已经实现的三层结构来完成业务,并向前端页面返回处理后的数据;前端页面收到HTTP响应后,要根据业务需求实现页面的局部刷新。

        2.前端页面实现 : 

                login.html代码如下 : 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
    <style type="text/css">
        table, td, th {
            background-color: lightcyan;
            border:2px pink solid;
            border-collapse: collapse;
            padding: 5px
        }
    </style>
    <script type="text/javascript">
        window.onload = function () {
            var checkButton = document.getElementById("checkButton");
            checkButton.onclick = function () {
                //1.创建XMLHttpRequest对象 [AJax引擎对象]
                var xhr = new XMLHttpRequest();

                //2.获取用户提交的数据
                var uname = document.getElementById("uname").value;

                //3.利用open方法,规定请求的类型、URL、以及是否异步处理请求。
                    /*
                        (1) 第一个参数———请求方式。可以是GET/POST等。
                        (2) 第二个参数———URL。此处采用了拼接的形式。
                        (3) 第三个参数———true。true表示异步发送。
                     */
                xhr.open("GET", "/Ajax/checkUser?username=" + uname, true)

                /*  !!!
                    在调用send函数之前,给XMLHttpRequest对象绑定一个事件onreadystatechange
                    该事件表示,当readyState属性的数据发生变化时,
                    会触发onreadystatechange事件,并调用指定的函数
                 */
                xhr.onreadystatechange = function () {
                    //若请求已经完成,响应已经就绪,且响应状态码是200
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        //获取实际返回的数据
                        var responseText = xhr.responseText;
                        //若返回的字符串非null,说明该用户名重复,不可用
                        if (responseText.trim() != "") {
                            checkButton.value = "用户名不可用";
                            var div01 = document.getElementById("div01");
                            //!!!!!!
                            //由于是div元素,所以要更改的是innerText or innerHTML属性值
                            div01.innerHTML = responseText;
                            div01.removeAttribute("hidden");
                        } else {
                            checkButton.value = "用户名可用";
                        }
                    }
                }

                //4.调用send方法,真正发送请求
                    //如果是POST请求,需要调用xhr.send("content");
                xhr.send();
            }
        }
    </script>
</head>
<body>
<form action="/Ajax/checkUser" method="post">
<table width="625px">
    <tr>
        <th colspan="3"><h2>用户注册</h2></th>
    </tr>
    <tr>
        <td>Username:</td>
        <td><input type="text" name="username" id="uname"/></td>
        <td><input type="button" value="验证用户名" id="checkButton"/></td>
    </tr>
    <tr>
        <td>Password:</td>
        <td><input type="password" name="password"/></td>
    </tr>
    <tr>
        <td>e-mail:</td>
        <td><input type="text" name="email"/></td>
    </tr>
    <tr>
        <td><input type="submit" value="Submit"/></td>
        <td><input type="reset" value="Reset"/></td>
    </tr>
    <tr>
        <th colspan="3"><h2>返回的JSON数据如下:</h2></th>
    </tr>
    <tr>
        <td colspan="3"><div id="div01"></div></td>
    </tr>
</table>
</form>
</body>
</html>

        3. 处理HTTP请求的servlet实现

                CheckUserServlet类代码如下 : 

package servlet;

import com.google.gson.Gson;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import javabean.User;
import service.UserService;

import java.io.IOException;

@WebServlet(urlPatterns={"/checkUser"})
public class CheckUserServlet extends HttpServlet {
    //定义一个UserService属性
    UserService userService = new UserService();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //联系手写Tomcat底层机制中,HttpServletRequest中封装的用于存储参数的Map对象。
        String username = req.getParameter("username");
        System.out.println("username = " + username);

        //此处利用了已实现的"Domain---DAO---Service"三层结构
        User user = userService.getUserByName(username);
        if (user != null) {
            Gson gson = new Gson();
            String strUser = gson.toJson(user);

            resp.setContentType("text/html; charset=utf-8");
            resp.getWriter().print(strUser);
        } else {
            resp.getWriter().print("");
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

        4.引入jar包及druid配置文件、工具类 : 

                引入jar包如下图所示 : 

                druid.properties配置文件如下 : (src目录下)

# 驱动名称(连接MySQL)
driverClassName=com.mysql.cj.jdbc.Driver
# 参数?rewriteBatchedStatements=true表示支持批处理机制
url=jdbc:mysql://localhost:3306/a_ajax?rewriteBatchedStatements=true
# 用户名,注意这里是按“username”来读取的
username=root
# 用户密码(自己改)
password=RA9_Cyan
# 初始化连接数量
initialSize=10
# 最小连接数量
minIdle = 5
# 最大连接数量
maxActive=50
# 超时时间5000ms(在等待队列中的最长等待时间,若超过,放弃此次请求)
maxWait=5000

                注意druid.properties配置文件中要修改连接的数据库,以及登录用户的用户名和密码!

                负责德鲁伊连接池的工具类JDBCUtilsDruid,代码如下 : (尤其注意导入配置文件时和Java SE的使用区别)

package utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
    基于Druid连接池的工具类
 */
public class JDBCUtilsDruid {
    private static DataSource dataSource;

    static {
        Properties properties = new Properties();
        try {
            //properties.load(new FileInputStream("src/druid.properties"));

            //由于JavaWeb和JavaSE的实际工作路径不一样,web的实际工作路径是在out目录下,
            //因此要使用类加载器来获取文件的真实路径!!!
            properties.load(JDBCUtilsDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    public static void close(ResultSet resultSet, Statement statement, Connection connection) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

        5.Domain层实现 : 

                现在MySQL中创建一张表user_demo,代码如下 : 

CREATE TABLE IF NOT EXISTS `user_demo` (
	`id` MEDIUMINT UNSIGNED PRIMARY KEY,
	`username` VARCHAR(255) NOT NULL DEFAULT '',
	`password` CHAR(64) NOT NULL,
	`email` VARCHAR(255) NOT NULL DEFAULT ''
) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin ENGINE INNODB;

INSERT INTO user_demo
		VALUES
		(1, 'Cyan', MD5(233), 'WangwuEX@outlook.com'),
		(2, 'Rain', MD5(111), 'Rain@rain.com'),
		(3, 'Five', MD5(141), 'Five@five.com'),
		(4, 'Ice', MD5(555), 'Ice@ice.com'),
		(5, 'Kyrie', MD5(666), 'Kyrie@irving.com');

SELECT * FROM `user_demo`;

                user_demo表的效果如下 : 

                创建对应的User类(注意字段的顺序要和表中的保持一致),User类代码如下 : 

package javabean;

/**
 * @author : Cyan_RA9
 * @version : 21.0
 * @function : user_demo表对应的JavaBean类
 */
public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;

    public User() { //供反射使用
    }

    public User(Integer id, String username, String password, String email) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.email = email;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

        6.DAO层实现 : 

                BasicDAO代码如下 : 

package dao;

import utils.JDBCUtilsDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
    BasicDAO类,完成所有DAO通用的crud操作。
 */
public class BasicDAO<T> {
    private QueryRunner queryRunner = new QueryRunner();

    public int update(String sql, Object... params) {
        int affectedRows = 0;
        Connection connection = null;

        try {
            connection = JDBCUtilsDruid.getConnection();
            affectedRows = queryRunner.update(connection,sql,params);
            return affectedRows;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsDruid.close(null, null, connection);
        }
    }

    public List<T> queryMultiply(String sql, Class<T> clazz, Object... params) {
        Connection connection = null;

        try {
            connection = JDBCUtilsDruid.getConnection();

            List<T> query = queryRunner.query(connection,sql,new BeanListHandler<T>(clazz),params);
            return query;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsDruid.close(null, null, connection);
        }
    }

    public T querySingle(String sql, Class<T> clazz, Object... params) {
        Connection connection = null;

        try {
            connection = JDBCUtilsDruid.getConnection();
            return queryRunner.query(connection, sql, new BeanHandler<T>(clazz), params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsDruid.close(null, null, connection);
        }
    }

    public Object queryScalar(String sql, Object... params) {
        Connection connection = null;

        try {
            connection = JDBCUtilsDruid.getConnection();
            return queryRunner.query(connection, sql, new ScalarHandler<>(), params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsDruid.close(null,null,connection);
        }
    }
}

                UserDAO类代码如下 :

package dao;

import javabean.User;

/**
 * @author : Cyan_RA9
 * @version : 21.0
 */
public class UserDAO extends BasicDAO<User>{
}

        7.Service层实现 : 

                UserService类, 代码如下 : 

package service;

import dao.UserDAO;
import javabean.User;

public class UserService {
    private UserDAO userDAO = new UserDAO();

    public User getUserByName(String username) {
        String sql = "SELECT * FROM user_demo WHERE username = ?";

        User user = userDAO.querySingle(sql, User.class, username);

        return user;
    }
}

        8.运行测试 : 

                启动Tomcat,进行测试,测试结果如下GIF图所示 : 


三、JQuery操作Ajax

        1 $.ajax({})函数 : 

        $.ajax函数的常用参数如下——

        (1) url : 请求的地址

        (2) type : 请求的方式GET or POST

        (3) data : 发送到服务器端的数据,将自动转换为请求字符串格式

        (4) success : 成功的回调函数

        (5) dataType : 返回的数据类型,常用Json或text。

        PS : 注意$.ajax({}) 的使用格式,不可以直接写参数,需要属性名 : 来约束。

        2 $.get()和$.post()函数 : 

        $.get函数 和 $.post函数的常用参数如下——

        (1) url : 请求的地址       

        (2) data : 发送到服务器端的数据,将自动转换为请求字符串格式

        (3) success : 成功的回调函数

        (4) dataType : 返回的数据类型,常用Json或text。

        PS1 : $.get() 和 $.post() 底层还是使用$.ajax({})函数来实现异步请求。
        PS2 : $.get() 和 $.post() 可以直接传入参数,但要注意顺序问题!

        3 $.getJSON()函数 : 

        $.getJSON函数的常用参数如下——

        (1) url : 请求的地址       

        (2) data : 发送到服务器端的数据,将自动转换为请求字符串格式

        (3) success : 成功的回调函数

        PS : $.getJSON() 底层还是使用$.ajax()函数来实现异步请求。

        System.out.println("END------------------------------------------------");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/98599.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue使用qrcodejs2生成二维码

目录 概要 构建展示的vue组件qrcode.vue 组件的使用 概要 项目中用到需要展示二维码的样式&#xff0c;想到了qrcode 例如&#xff1a; 前提&#xff1a;安装包 npm install qrcodejs2 --save 构建展示的vue组件qrcode.vue <template><div style"width: …

Opencv基于文字检测去图片水印

做了一个简单的去水印功能&#xff0c;基于文字检测去图片水印。效果如下&#xff1a; 插件功能代码参考如下&#xff1a; using namespace cv::dnn; TextDetectionModel_DB *textDetector0; void getTextDetector() {if(textDetector)return;String modelPath "text_de…

拥抱储能新时代!科士达闪耀EESA第二届中国国际储能展览会

2023年8月30日&#xff0c;EESA第二届中国国际储能展览会在苏州国际博览中心拉开帷幕&#xff0c;科士达以“零碳光储数能未来”为主题&#xff0c;亮相G3-20展台&#xff0c;多维度展现户用光储、工商业储能、大型储能等解决方案&#xff0c;彰显安全、高效、可靠的产品性能和…

大数据时代下的精准营销

在大数据时代&#xff0c;人们的信息越来越透明&#xff0c;留在网络上的各种数据也是企业进行营销的一个重要的生产要素。一直以来&#xff0c;营销的科学性正是因为运用了自然科学中一级互联网中的数据收集手段&#xff0c;严谨的记录、搜集和分析消费者的各项数据和日常生活…

Java单元测试及常用语句 | 京东物流技术团队

1 前言 编写Java单元测试用例&#xff0c;即把一段复杂的代码拆解成一系列简单的单元测试用例&#xff0c;并且无需启动服务&#xff0c;在短时间内测试代码中的处理逻辑。写好Java单元测试用例&#xff0c;其实就是把“复杂问题简单化&#xff0c;建单问题深入化“。在编写的…

【核磁共振成像】相位差重建

目录 一、相位差map重建一般步骤和反正切函数主值范围二、反正切运算三、可预期相位误差和伴随场的校正四、图形变形校正 一、相位差map重建一般步骤和反正切函数主值范围 MRI是一个相敏成像模态&#xff0c;MR原始数据傅里叶变换后的复数图像中每个像素值有模和相位。标准模重…

Mysql高级语句

高级语句 1.按关键字排序 SELECT column1, column2, ... FROM table_name ORDER BY column1, column2, ... ASC|DESC ASC 是按照升序进行排序的&#xff0c;是默认的排序方式&#xff0c;即 ASC 可以省略。 SELECT 语句中如果没有指定具体的排序方式&#xff0c;则默认按 ASC…

【数据结构】——查找、散列表的相关习题

目录 一、选择填空判断题题型一&#xff08;顺序、二分查找的概念&#xff09;题型二&#xff08;分块查找的概念&#xff09;题型三&#xff08;关键字比较次数&#xff09; 二、应用题题型一&#xff08;二分查找判定树&#xff09; 一、选择填空判断题 题型一&#xff08;顺…

Leetcode328 奇偶链表

思路&#xff1a;分别处理奇偶&#xff0c;保存奇偶的第一个和最后一个节点&#xff0c;注意最后链接的时候需要把偶数的next去掉再拼接不然就成环了 class Solution:def oddEvenList(self, head: ListNode) -> ListNode:if not head or not head.next or not head.next.ne…

YOLOv5算法改进(10)— 替换主干网络之GhostNet

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。GhostNet是一种针对计算机视觉任务的深度神经网络架构&#xff0c;它于2020年由中国科学院大学的研究人员提出。GhostNet的设计目标是在保持高精度的同时&#xff0c;减少模型的计算和存储成本。GhostNet通过引入Ghost模块…

阿里云架构

负载均衡slb 分类以及应用场景 负载均衡slb clb 传统的负载均衡(原slb) 支持4层和7层(仅支持对uri(location),域名进行转发) 一般使用slb(clb) alb 应用负载均衡 只支持7层,整合了nginx负载均衡的各种功能,可以根据用户请求头,响应头 如果需要详细处理用户请求(浏…

【Dart】学习使用(二):基本类型

前言 基本类型是语言的基础。 Dart 语言支持以下基础类型&#xff1a;Numbers(int、double)&#xff0c; 整形Strings(String), 字符串Booleans(bool) , 布尔型Records((value1,value2)) 记录Lists(List ) 数组Sets(Set) 集合Maps(Map) 映射Runes(Runes,通常由 characters AP…

springBoot--终

目录 Web定制SpringMVC定制某些mvc配置定制mvc核心组件完全自定义mvc 静态资源静态资源映射静态资源缓存示例自定义静态资源规则配置方式代码方式 欢迎页Favicon&#xff08;网站图标&#xff09;路径匹配策略内容协商制定返回json类型数据制定返回xml类型数据制定返回自定义类…

2023年高教社杯 国赛数学建模思路 - 案例:ID3-决策树分类算法

文章目录 0 赛题思路1 算法介绍2 FP树表示法3 构建FP树4 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模…

本地部署体验LISA模型(LISA≈图像分割基础模型SAM+多模态大语言模型LLaVA)

GitHub地址&#xff1a;https://github.com/dvlab-research/LISA 该项目论文paper reading&#xff1a;https://blog.csdn.net/Transfattyacids/article/details/132254770 在GitHub上下载源文件&#xff0c;进入下载的文件夹&#xff0c;打开该地址下的命令控制台&#xff0c;…

Vue安装过程的困惑解答——nodejs和vue关系、vue的项目结构

文章目录 一、为什么在使用vue前要下载nodejs&#xff1f;二、为什么安装nodejs后就能使用NPM包管理工具&#xff1f;三、为什么是V8引擎并且使用C实现&#xff1f;四、为什么会安装淘宝镜像&#xff1f;五、什么是webpack模板&#xff0c;为什么需要他&#xff1f;六、vue项目…

深入探索C语言自定义类型:打造你的编程世界

一、什么是自定义类型 C语言提供了丰富的内置类型&#xff0c;常见的有int, char, float, double, 以及各种指针。 除此之外&#xff0c;我们还能自己创建一些类型&#xff0c;这些类型称为自定义类型&#xff0c;如数组&#xff0c;结构体&#xff0c;枚举类型和联合体类型。 …

Unreal5(虚幻5)学习记录 快捷键

虚幻5学习记录 快捷键 世界场景中漫游&#xff08;镜头移动): 按住鼠标右键 键盘的W(前) S(后) A(左) D(右) E(上) Q(下)键 透视 透视 ALTG 上部分 ALTJ 底视图ALTSHIFTJ 左视图 ALTK 右视图 ALTSHIFTK 前视图 ALTH 后视图 ALTSHIFTH 内容浏览器 Ctrl Space 内容浏览器…

stm32CubeMX HAL W5500芯片介绍 第一章

W5500芯片介绍 文章目录 W5500芯片介绍简单简绍以太网以太网分五层&#xff1a;第一层物理层&#xff1a;第二层&#xff1a;数据链路层&#xff1a;第三层&#xff1a;网络层&#xff1a;第四层&#xff1a;传输层&#xff1a;第五层&#xff1a;应用层&#xff1a;以太网应用…

Scala的特质trait与java的interface接口的区别,以及Scala特质的自身类型和依赖注入

1. Scala的特质trait与java接口的区别 Scala中的特质&#xff08;trait&#xff09;和Java中的接口&#xff08;interface&#xff09;在概念和使用上有一些区别&#xff1a; 默认实现&#xff1a;在Java中&#xff0c;接口只能定义方法的签名&#xff0c;而没有默认实现。而在…