首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MVC 三层架构案例详细讲解

MVC 三层架构案例详细讲解

原创
作者头像
RainbowSea
发布于 2023-05-17 11:43:45
发布于 2023-05-17 11:43:45
2.4K0
举报

MVC 三层架构案例详细讲解

在这里插入图片描述
在这里插入图片描述

@toc

每博一文案

代码语言:text
AI代码解释
复制
多读书,书中有,你对生活,困难所解不开的答案
比如:《杀死一只是更鸟》中提到的
对应我们:我们努力中考,高考,升本,考研,每天都在努力学习,但是某天突然想到万一没有考上的话,那现在的努力又有什么意义呢?
答案:在《杀死一只是更鸟》里有这样一段话:
> 勇敢是,当你还未开始,你就知道自己会输,可你依然要去做,而且无论如何都要把它坚持到底,你很少能赢,但有时也会。努力的这个过程本身就是有意义,能够获得理想的结果当然很好,但如果失败了也没关系。因为你的勇敢,从未辜负你的青春,而黎明的光亮,总有一刻,会照亮穿梭于黑暗之中的自己。况且,你还不一定会输呢。

1. MVC 概述

MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。 1-2

模型-视图-控制器(MVC)是Xerox PARC在二十世纪八十年代为编程语言Smalltalk-80发明的一种软件设计模式,已被广泛使用。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusionPHP的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。

2. MVC设计思想

MVC(Model View Controller)软件工程中的一种软件架构模式,它把软件系统分为模型视图控制器三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

img
img

MVC 主要的核心就是:分层:希望专人干专事,各司其职,职能分工要明确,这样可以让代码耦合度降低,扩展力增强,组件的可复用性增强

MVC 从字面意思我们就可以看到:是分为了三层的,M(Mode 模型),V(View 视图),C(Controller 控制器)

img
img

M即model模型:是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性

V即View视图:是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操作的方式。

C即controller控制器:是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。

M(Model :数据/业务) V (View :视图/展示) C (Controller : 控制层)

C(是核心,是控制器,是司令官)

M(处理业务/处理数据的一个秘书)

V(负责页面展示的一个秘书)

MVC(一个司令官,调度两个秘书,去做这件事),仅仅只做事务上的调度,而不做其他的操作

在这里插入图片描述
在这里插入图片描述
JavaBean
JavaBean

优点:

  1. 耦合性低,方便维护,可以利于分工协作
  2. 重用性高

缺点:

  1. 使得项目架构变得复杂,对开发人员要求高

3. 三层架构

三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层表示层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。

区分层次的目的即为了“高内聚低耦合” 的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三层架构每层之间的逻辑关系:

在这里插入图片描述
在这里插入图片描述

三层架构的优点

  1. 开发人员可以只关注整个结构中的其中某一层;
  2. 可维护性高,可扩展性高
  3. 可以降低层与层之间的依赖;
  4. 有利于标准化;
  5. 利于各层逻辑的复用

三层架构的缺点:

  1. 降低了系统的性能。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成
  2. 有时会导致级联的修改,这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码
  3. 增加了开发成本

4. MVC 与 三层架构的关系:

MVC的也可以被说成是 MVC三层架构,说白了,它们其实都是一个东西,只是在一些细节上有稍微的不同,大致设计思想都是一样的:“高内聚,低耦合”。

在这里插入图片描述
在这里插入图片描述

其实,无论是MVC还是三层架构,都是一种规范,都是奔着"高内聚,低耦合"的思想来设计的。三层中的UI和Servlet来分别对应MVC中的View和Controller,业务逻辑层是来组合数据访问层的原子性功能的。

5. 案例举例:用户账户转账

如下我们,实现一个用户账户转账操作的一个案例:

准备工作:创建表,创建数据

代码语言:sql
AI代码解释
复制
CREATE DATABASE mvc;

USE mvc;

SHOW TABLES;

CREATE TABLE t_act (
   id BIGINT PRIMARY KEY AUTO_INCREMENT,
   actno VARCHAR(255) NOT NULL,
   balance DECIMAL(10,2) 
);



INSERT INTO t_act(actno,balance)
VALUES('act001',50000.00),('act002',0.00);

SELECT *
FROM t_act;

5.1 M(Model :数据/业务处理层)

javaBean :Account 封装数据

账户实体类,封装账户信息的

  • 一般是一张表一个。
  • pojo 对象
  • 有的人也会把这种专门封装数据的对象,称为:"bean对象" (javabean对象,咖啡豆)
  • 有的人也会把这种专门封装数据的对象,称为领域模型对象,domain对象
  • 不同的程序员不同的习惯
代码语言:java
AI代码解释
复制
package com.RainbowSea.bank.mvc;

import java.io.Serializable;
import java.util.Objects;


/**
 * 账户实体类,封装账户信息的
 * 一般是一张表一个。
 * pojo 对象
 * 有的人也会把这种专门封装数据的对象,称为:"bean对象" (javabean对象,咖啡豆)
 * 有的人也会把这种专门封装数据的对象,称为领域模型对象,domain对象
 * 不同的程序员不同的习惯。
 */
public class Account implements Serializable {  // 这种普通的简单的对象被成为pojo对象
    // 注意我们这里定义的数据类型,使用引用数据类型
    // 因为我们数据库中可能存在 null 值,而基本数据类型是不可以存储 null值的

    private Long id = null;  // id
    private String actno;  // 账号
    private Double balance; // 余额

    // 反序列化
    private static final long serialVersionUID = 1L;

    public Account() {
    }


    public Account(Long id, String actno, Double balance) {
        this.id = id;
        this.actno = actno;
        this.balance = balance;
    }


    public Long getId() {
        return id;
    }

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

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Account)) return false;
        Account account = (Account) o;
        return Objects.equals(getId(), account.getId()) && Objects.equals(getActno(), account.getActno()) && Objects.equals(getBalance(), account.getBalance());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId(), getActno(), getBalance());
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", actno='" + actno + '\'' +
                ", balance=" + balance +
                '}';
    }
}

DB连接数据库的工具:

代码语言:text
AI代码解释
复制
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mvc
user=root
password=MySQL
代码语言:java
AI代码解释
复制
package com.RainbowSea.bank.utils;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ResourceBundle;

public class DBUtil {

    // resourceBundle 只能读取到 properties 后缀的文件,注意不要加文件后缀名
    private static ResourceBundle resourceBundle = ResourceBundle.getBundle("resources/jdbc");
    private static String driver = resourceBundle.getString("driver");
    private static String url = resourceBundle.getString("url");
    private static String user = resourceBundle.getString("user");
    private static String password = resourceBundle.getString("password");


    // DBUtil 类加载注册驱动
    static {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
           e.printStackTrace();
        }

    }


    // 将构造器私有化,不让创建对象,因为工具类中的方法都是静态的,不需要创建对象
    // 为了防止创建对象,故将构造方法私有化
    private DBUtil() {

    }

    /**
     * 这里没有使用数据库连接池,直接创建连接对象
     */
    public static Connection getConnection()  {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return  connection;
    }


    /**
     * 资源的关闭
     * 最后使用的最先关闭,逐个关闭,防止存在没有关闭的
     */
    public static void close(Connection connection , PreparedStatement preparedStatement, ResultSet resultSet) {

        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }


        if (preparedStatement!=null) {
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }


        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

对应Account数据表的DAO操作工具类

AccountDao 是负责Account 数据的增上改查

什么是DAO ?

  • Data Access Object (数据访问对象)
  • DAO实际上是一种设计模式,属于 JavaEE的设计模式之一,不是 23种设计模式
  • DAO只负责数据库表的CRUD ,没有任何业务逻辑在里面
  • 没有任何业务逻辑,只负责表中数据增上改查的对象,有一个特俗的称谓:DAO对象

为什么叫做 AccountDao 呢?

  • 这是因为DAO是专门处理t_act 这张表的
  • 如果处理t_act 表的话,可以叫做:UserDao
  • 如果处理t-student表的话,可以叫做 StudentDao

主要定义如下:增删改查方法()

代码语言:java
AI代码解释
复制
int insert() ;
int deleteByActno();
int update() ;
Account selectByActno();
List<Account> selectAll();
代码语言:java
AI代码解释
复制
package com.RainbowSea.bank.mvc;


import com.RainbowSea.bank.utils.DBUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;

/**
 * AccountDao 是负责Account 数据的增上改查
 * <p>
 * 1. 什么是DAO ?
 * Data Access Object (数据访问对象)
 * 2. DAO实际上是一种设计模式,属于 JavaEE的设计模式之一,不是 23种设计模式
 * 3.DAO只负责数据库表的CRUD ,没有任何业务逻辑在里面
 * 4.没有任何业务逻辑,只负责表中数据增上改查的对象,有一个特俗的称谓:DAO对象
 * 5. 为什么叫做 AccountDao 呢?
 * 这是因为DAO是专门处理t_act 这张表的
 * 如果处理t_act 表的话,可以叫做:UserDao
 * 如果处理t-student表的话,可以叫做 StudentDao
 * <p>
 * int insert() ;
 * int deleteByActno();
 * int update() ;
 * Account selectByActno();
 * List<Account> selectAll();
 */
public class AccountDao {


    /**
     * 插入数据
     *
     * @param account
     * @return
     */
    public int insert(Account account) {
        Connection connection = DBUtil.getConnection();
        PreparedStatement preparedStatement = null;
        int count = 0;
        try {
            String sql = "insert into t_act(actno,balance) values(?,?)";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, account.getActno());
            preparedStatement.setDouble(2, account.getBalance());
            count = preparedStatement.executeUpdate();


        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, null);
        }


        return count;

    }


    /**
     * 通过Id删除数据
     *
     * @param id
     * @return
     */
    public int deleteById(String id) {
        Connection connection = DBUtil.getConnection();
        int count = 0;
        PreparedStatement preparedStatement = null;
        try {
            String sql = "delete from t_act where id = ?";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, id);
            count = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, null);
        }

        return count;

    }


    /**
     * 更新数据
     *
     * @param account
     * @return
     */
    public int update(Account account) {
        Connection connection = DBUtil.getConnection();
        PreparedStatement preparedStatement = null;
        int count = 0;

        try {
            String sql = "update t_act set balance = ?, actno = ? where id = ?";
            preparedStatement = connection.prepareStatement(sql);

            //注意设置的 set类型要保持一致。
            preparedStatement.setDouble(1, account.getBalance());
            preparedStatement.setString(2, account.getActno());
            preparedStatement.setLong(3, account.getId());

            count = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, null);
        }

        return count;
    }


    /**
     * 通过 actno 查找账户信息
     *
     * @param actno
     * @return
     */
    public Account selectByActno(String actno) {
        Connection connection = DBUtil.getConnection();
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Account account = new Account();

        try {
            String sql = "select id,actno,balance from t_act where actno = ?";
            preparedStatement = connection.prepareStatement(sql);

            //注意设置的 set类型要保持一致。
            preparedStatement.setString(1, actno);

           resultSet = preparedStatement.executeQuery();

            if (resultSet.next()) {
                Long id = resultSet.getLong("id");
                Double balance = resultSet.getDouble("balance");
                // 将结果集封装到java 对象中
                account.setActno(actno);
                account.setId(id);
                account.setBalance(balance);

            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, resultSet);
        }

        return account;
    }


    /**
     * 查询所有的账户信息
     *
     * @return
     */
    public List<Account> selectAll() {
        Connection connection = DBUtil.getConnection();
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        List<Account> list = null;

        try {
            String sql = "select id,actno,balance from t_act";
            preparedStatement = connection.prepareStatement(sql);

            resultSet = preparedStatement.executeQuery();

            while (resultSet.next()) {
                String actno = resultSet.getString("actno");
                Long id = resultSet.getLong("id");
                Double balance = resultSet.getDouble("balance");
                // 将结果集封装到java 对象中
                Account account = new Account(id,actno,balance);

                // 添加到List集合当中
                list.add(account);

            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            DBUtil.close(connection, preparedStatement, resultSet);
        }

        return list;
    }


}

对指定的数据表的数据进行service 业务逻辑处理操作:

service 翻译为:业务。

  • AccountService 专门处理Account业务的一个类
  • 在该类中应该编写纯业务代码。(只专注域业务处理,不写别的,不和其他代码混合在一块)
  • 只希望专注业务,能够将业务完美实现,少量bug.
  • 业务类一般起名:XXXService,XXXBiz...
代码语言:java
AI代码解释
复制
package com.RainbowSea.bank.mvc;


/**
 * service 翻译为:业务。
 * AccountService 专门处理Account业务的一个类
 * 在该类中应该编写纯业务代码。(只专注域业务处理,不写别的,不和其他代码混合在一块)
 * 只希望专注业务,能够将业务完美实现,少量bug.
 * <p>
 * 业务类一般起名:XXXService,XXXBiz...
 */
public class AccountService {

    // 这里的方法起名,一定要体现出,你要处理的是什么业务:
    // 我们要提供一个能够实现转账的业务的方法(一个业务对应一个方法)
    // 比如:UserService StudentService OrderService

    // 处理Account 转账业务的增删改查的Dao
    private AccountDao accountDao = new AccountDao();

    /**
     * 完成转账的业务逻辑
     *
     * @param fromActno 转出账号
     * @param toActno   转入账号
     * @param money     转账金额
     */
    public void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, AppException {
        // 查询余额是否充足
        Account fromAct = accountDao.selectByActno(fromActno);
        if (fromAct.getBalance() < money) {
            throw new MoneyNotEnoughException("对不起,余额不足");
        }

        // 程序到这里说明余额充足
        Account toAct = accountDao.selectByActno(toActno);

        // 修改金额,先从内存上修改,再从硬盘上修改
        fromAct.setBalance(fromAct.getBalance() - money);
        toAct.setBalance(toAct.getBalance() + money);


        // 从硬盘数据库上修改
        int count = accountDao.update(fromAct);
        count += accountDao.update(toAct);

        if(count != 2) {
            throw new AppException("账户转账异常,请联系管理员");
        }

    }
}

异常处理类:

代码语言:java
AI代码解释
复制
package com.RainbowSea.bank.mvc;


/**
 * 余额不足异常
 */
public class AppException extends Exception{

        public AppException() {

        }

        public AppException(String msg) {
            super(msg);
        }

}
代码语言:java
AI代码解释
复制
package com.RainbowSea.bank.mvc;


/**
 * 余额不足异常
 */
public class MoneyNotEnoughException extends Exception{
    public MoneyNotEnoughException() {

    }

    public MoneyNotEnoughException(String msg) {
        super(msg);
    }
}

5.2 C (Controller : 控制层)

仅仅负责调度 M业务处理层,V视图显示层,而不做其他操作。

代码语言:java
AI代码解释
复制
package com.RainbowSea.bank.mvc;

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 java.io.IOException;


/**
 * 账户小程序
 * AccountServlet 是一个司令官,他负责调度其他组件来完成任务。
 *
 */
@WebServlet("/transfer")
public class AccountServlet extends HttpServlet { // AccountServlet 作为一个 Controller 司令官

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {

        // 获取数据
        String fromActno = request.getParameter("fromActno");
        String toActno = request.getParameter("toActno");
        double money = Double.parseDouble(request.getParameter("money"));

        // 调用业务方法处理业务(调度Model处理业务,其中是对应数据表的 CRUD操作)
        AccountService accountService = new AccountService();
        try {
            accountService.transfer(fromActno,toActno,money);
            // 执行到这里说明,成功了,
            // 展示处理结束(调度 View 做页面展示)

            response.sendRedirect(request.getContextPath()+"/success.jsp");
        } catch (MoneyNotEnoughException e) {
            // 执行到种类,说明失败了,(余额不足
            // 展示处理结束(调度 View 做页面展示)
            response.sendRedirect(request.getContextPath()+"/error.jsp");

        } catch (AppException e) {
            // 执行到种类,说明失败了,转账异常
            // 展示处理结束(调度 View 做页面展示)
            response.sendRedirect(request.getContextPath()+"/error.jsp");

        }

        // 页面的展示 (调度View做页面展示)


    }
}

5.3 V (View :视图/展示)

index.jsp 转账页面:

代码语言:java
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>银行账号转账</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/transfer" method="post">
  转出账户: <input type="text" name="fromActno" /> <br>
  转入账户: <input type="text" name="toActno" /> <br>
  转账金额: <input type="text" name="money" /><br>
  <input type="submit" value="转账" />
</form>
</body>
</html>

success转账成功的页面显示:

代码语言:java
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>转账成功</title>
</head>
<body>

<h3>转账成功</h3>
</body>
</html>

error 转账失败的页面显示:

代码语言:java
AI代码解释
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>转账失败</title>
</head>
<body>
<h3>转账失败</h3>
</body>
</html>
在这里插入图片描述
在这里插入图片描述

虽然上述:代码成功实现的了用户转账的操作,但是并没有进行事务的处理。

如下是运用 TreadLocal 进行事务的处理:🔜🔜🔜 https://blog.csdn.net/weixin_61635597/article/details/130728394?csdn_share_tail

6. 总结:

  1. MVC 从字面意思我们就可以看到:是分为了三层的,M(Mode 模型),V(View 视图),C(Controller 控制器)
  2. M(Model :数据/业务) V (View :视图/展示) C (Controller : 控制层)

C(是核心,是控制器,是司令官)

M(处理业务/处理数据的一个秘书)

V(负责页面展示的一个秘书)

MVC(一个司令官,调度两个秘书,去做这件事),仅仅只做事务上的调度,而不做其他的操作

  1. 三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层表示层(User Interface layer)、业务逻辑层(Business Logic Layer)、数据访问层(Data access layer)。
  2. 无论是MVC还是三层架构,都是一种规范,都是奔着"高内聚,低耦合"的思想

7. 最后:

⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐ 感谢如下博主的分享: ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

【1】https://blog.csdn.net/weixin_43232955/article/details/104963392?ops_request_misc

【2】https://blog.csdn.net/weixin_42694511/article/details/120690083?ops_request_misc

限于自身水平,其中存在的错误,希望大家,给予指教,韩信点兵——多多益善,谢谢大家,江湖再见,后会有期!!!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
BRAIN脑电研究:使用快速球方法评估阿尔茨海默病识别记忆
早期诊断阿尔茨海默病需要对相关结构和功能变化敏感的生物标志物。虽然在结构生物标记物的开发方面已经取得了相当大的进展,但早期识别变化的功能性生物标记物仍然是需要的。我们提出了快速球(Fastball),一种新的脑电测量被动和客观的识别记忆的方法,不需要行为记忆反应或对任务的理解。年轻人、老年人和老年痴呆症患者(每组20人)完成了快速球任务,持续时间不到3分钟。参与者被动地观看快速呈现的图像,EEG评估他们根据先前的暴露程度(即旧/新)自动区分图像的能力。参与者没有被要求注意之前看到的图像,也没有做出任何行为反应。在快速球任务之后,参与者完成了一个有两个选项的强制选择(2AFC)任务,以测量他们对先前看到的刺激的显性行为识别。快球EEG检测到,与健康老年人相比,阿尔茨海默病患者的识别记忆明显受损,而行为识别在阿尔茨海默病患者和健康老年人之间没有显著差异。使用快速球识别记忆测量方法,阿尔茨海默病患者与健康老年人对照者的识别准确率较高,而使用行为2AFC准确性的识别性能较差。健康老龄化没有显著影响,老年人和年轻人在快速球任务和行为2AFC任务中的表现相当。阿尔茨海默病的早期诊断提供了早期治疗的可能性。快速球提供了一种检测识别反应的替代方法,有望在行为表现缺陷尚不明显的阶段作为疾病病理的功能标记。它是被动的,无创的,快速和使用廉价的,可扩展的EEG技术。快速球为痴呆的识别评估提供了一种新的强有力的方法,并为早期诊断工具的开发打开了一扇新的大门。本文发表在BRAIN杂志。
用户1279583
2022/02/28
5300
BRAIN脑电研究:使用快速球方法评估阿尔茨海默病识别记忆
视觉字符串大脑左半球皮层特异化预测学龄前儿童基本字符-声音关联认知能力
本项研究通过记录左半球视觉区域内2分钟电生理反应的方法,在5岁学龄前儿童群体中发现了稳定且独特的对文本信息敏感的脑电信号。这一脑电信号与学龄前儿童的基本字符认知能力(一项独立采取的行为测量)有显著相关性,说明存在除了视觉熟悉之外的特异化神经回路,这些发现还强调了高度灵敏客观的非行为测量方法对发展中个体字符认知能力(阅读能力的前身)评估的潜力。本研究由比利时鲁汶大学心理科学研究所和神经科学研究所的Aliette Lochya, Marie VanReybroecka, 和Bruno Rossion发表在PNAS上。
用户1279583
2019/11/14
8760
思影科技眼动数据处理服务
眼动数据看似简单,但其数据结构紧密结合了平面空间特性和时间特性。单纯的感兴趣分析,不仅难以挖掘出数据中有用的隐含信息,在文章发表的过程中,也会由于分析手段简单而不易引起审稿人的重视,难以发出高质量的文章。因此,思影科技结合最新的眼动数据处理技术,为客户的认知科学研究保驾护航。
用户1279583
2020/05/11
1.3K0
脑电研究:冥想提高年轻人的持续注意
来自加利福利亚大学的DavidA. Ziegler等人在Nature Human Behaviour杂志上发表了关于冥想与年轻人持续性注意关系的研究。该研究使用了一款冥想训练软件(MediTrain)来研究冥想对持续性注意以及工作记忆的影响。
用户1279583
2019/09/17
1K0
脑电研究:冥想提高年轻人的持续注意
Neuron:空间注意中的Alpha同步和神经反馈控制
以往研究表明,Alpha同步的降低与注意增强相关,然而alpha同步的增加却与注意无关。为了验证alpha同步是否与注意存在因果关系,来自麻省理工学院的研究者使用MEG手段进行了研究,相关成果发表在著名期刊Neuron上。
用户1279583
2020/02/13
9190
Neuron:空间注意中的Alpha同步和神经反馈控制
北大心理与认知学院院长方方:人类注意力图和动态机制
6月22日,北京智源大会举行了认知神经基础专题论坛,来自北京师范大学认知神经科学与学习国家重点实验室的毕彦超教授、北京大学心理与认知科学学院的方方教授、北京师范大学心理学部的刘嘉教授、北京大学计算机系的吴思教授、中国科学院自动化研究所的余山教授分别做了报告,共同探究认知神经科学能为AI带来什么启发。
脑机接口社区
2020/07/15
4580
北大心理与认知学院院长方方:人类注意力图和动态机制
成人β-地中海贫血患者的注意、反应抑制和ERP变化
在β地中海贫血(β-TM)领域的ERP研究很少,且局限于儿童。SivanRaz,Ariel Koren和Carina Levin在British Journal of Haematology的文章指出,采用ERPs探讨成年β地中海贫血(beta thalassaemia major, β-TM)患者与健康对照者的认知神经功能差异。本研究采用停止信号任务(stop-signal task)测量注意力和反应抑制功能(二者是执行控制的指标),并将行为任务表现、ERPs和血红蛋白水平进行相关分析。结果显示,β-TM患者的认知能力受损、反应时间比对照组长、血红蛋白水平与Go刺激反应时负相关。β-TM患者的神经活动明显改变,反映在几个任务相关的ERP成分(P1、N1、P3)峰值增大。可能的解释是,β-TM患者在应对认知挑战时需要调用更多的认知资源。血红蛋白水平与各ERP成分存在显著相关性,血红蛋白越低,ERP波幅越高。
用户1279583
2019/07/10
6760
Nature Neuroscience:经颅交流电刺激(tACS)有助于老年人工作记忆的恢复
来自波士顿大学的研究者Reinhart 和Nguyen最近在Nature Neuroscience的发文揭示了认知功能衰退的核心特征——工作记忆缺陷:来源于局部脑回路与远程脑回路间的失连,通过颞叶皮层中的θ-γ相位-振幅耦合和跨额颞叶皮层的θ相位同步来实例化。研究者使用非侵入性的刺激程序调节60~76岁成人远程θ波间的相互作用。25分钟的刺激后,将频率调谐至个体脑网络的动力学特征。结果不仅观察到神经同步模式的优先增加,而且也观察到了信息流的发送者与接收者在额叶皮层内、颞叶皮层内以及两皮层间的返回关系。该操作能迅速提升工作记忆能力,且持续时间超过50分钟。该结果能帮助研究者深入了解与年龄相关的认知损害的生理基础,并为今后针对认知衰退方面的非药理学干预奠定了基础。
用户1279583
2019/06/06
3K0
Nature Neuroscience:经颅交流电刺激(tACS)有助于老年人工作记忆的恢复
Science advances:正念疗法矫正阿片类药物使用者的享乐失调
请点击上面“思影科技”四个字,选择关注我们,思影科技专注于脑影像数据处理,涵盖(fMRI,结构像,DTI,ASL,EEG/ERP,FNIRS,眼动)等,希望专业的内容可以给关注者带来帮助,欢迎留言讨论,也欢迎参加思影科技的其他课程。(文末点击浏览)
用户1279583
2019/11/25
7220
Nature子刊 | ChineseEEG: 一个基于中文语料刺激的高通道EEG数据集
研究人员意识到,目前主流的语言处理研究和认知神经科学研究多集中在英语等西方语言上,但全球有数亿人使用其他语言,特别是中文。中文具有独特的语法结构、丰富的字符系统和复杂的语义网络,这使得它在认知处理上可能有着不同于英语的特点。因此,深入研究中文语言的神经机制不仅有助于全面理解人类语言处理的普遍规律,还能为跨文化、跨语言的认知科学研究提供重要的理论依据和数据支持。
脑机接口社区
2024/06/21
8260
Nature子刊 | ChineseEEG: 一个基于中文语料刺激的高通道EEG数据集
用于追踪认知任务期间的亚秒级脑动态的高密度脑电
这项工作为社区提供了高密度脑电图(HD-EEG, 256个通道)数据集,这些数据集是在无任务和任务相关范式下收集的。它包括43名健康的参与者执行视觉命名和拼写任务,视觉和听觉命名任务和视觉工作记忆任务,以及静息状态。HD-EEG数据以脑成像数据结构(bid)格式提供。这些数据集可以用来(i)追踪大脑网络动力学和在不同条件下(命名/拼写/其他)的次秒级时间尺度,和模态(听觉、视觉)的快速重新配置和相互比较,(ii)验证几个方法中包含的参数,这些方法是用来通过头皮脑电图估计大脑皮层网络,例如最优通道数量和感兴趣区域数量的问题,以及(iii)允许到目前为止使用HD-EEG获得的结果的再现性。我们希望,这些数据集的发布将推动新方法的发展,可以用来评估大脑皮层网络,并更好地了解大脑在休息和工作时的一般功能。 数据可从https://openneuro.org免费获取。 1.1.背景和概要 新的证据表明,来自于空间上遥远的大脑区域之间的通信导致大脑功能(失能)。尽管在过去的几十年里,功能性磁共振成像已经给神经科学带来了革命性的变化,但其固有的时间分辨率较差,这是限制其用于跟踪快速大脑网络动态的主要缺陷,而这种网络动态是多个大脑(认知和感知运动)过程执行的基础。脑电图/脑磁图(EEG/MEG)是一种独特的非侵入性技术,能够在毫秒的时间尺度上跟踪大脑动态。 在无任务范式和任务相关范式下,已经有一些研究使用脑电图/脑磁图源连通性方法来跟踪大脑皮层网络。然而,尽管人类连接组项目(HCP)和几个脑电图数据集的MEG数据集模型得到了人们的称赞,但只有很少的数据可以同时用于休息和任务,并且在不同任务中开放获取的高密度脑电图(HD-EEG, 256个通道)数据仍然缺失。 HD-EEG与复杂的信号处理算法相结合,正日益将EEG转变为一种潜在的神经成像模式。最近的脑电图研究揭示了在休息和认知任务期间跟踪快速功能连接动态的可能性。此外,一些研究报告了HD-EEG数据(与低脑电通道密度相比)在某些病理条件下的潜在应用,如癫痫网络的定位和神经退行性疾病中认知功能下降的检测。此外,新出现的证据表明,在一定程度上,使用HD-EEG可以捕获皮层下的结构。在这种背景下,无任务和任务相关的可用性开放HD-EEG数据库正在快速成为强制性的(i)解读(次秒级)重组的脑功能网络在认知,(ii)开发新的信号处理方法,充分估计大脑皮层网络和(iii)允许使用HD-EEG到目前为止结果的再现性。 在此,我们提供了第一个开放获取的HD-EEG(256通道)数据集,在休息状态和4种不同的任务(视觉命名、听觉命名、视觉拼写和工作记忆)下记录。部分数据已经被用于开发和分析各种信号处理方法。 特别地,我们的努力集中在对休息和图片命名期间的脑功能网络的估计上。然而,这些研究都没有描述数据集的细节,而且到目前为止的工作只用了小部分数据。在这项工作中,我们提供了所有必要的细节和一个开放的数据库,以便国际科学界能够在无任务和与任务相关的范式中自由地产生对大脑功能的更好的理解。这也将有助于新方法的开发,以提高目前使用的HD-EEG评估皮质脑网络的技术的准确性,并通过比较结果和未来的meta分析来使得这些技术互相面对。我们希望这个数据集将有助于使脑电图源空间网络分析成为一种成熟的技术,以解决认知和临床神经科学中的一些问题。 1.2 方法 1.2.1 数据采集 数据是2012年至2017年在法国雷恩进行的两项不同实验中收集的。第一数据集包括视觉对象名字的命名和拼写(图1)。第二个数据集包括静息状态、视觉/听觉命名和视觉工作记忆任务(图2)。同样的设备中使用的数据集和录音都在同一个地方(雷恩大学医院中心)。采用HD-EEG系统(EGI,256个电极)以1 KHz采样率记录脑活动,电极阻抗保持在50 k ω以下。两项研究的参与者是不同的。他们提供了参与的书面知情同意,并完成了一些纳入/排除标准问卷(总结见表1)。参与者坐在法拉第结构房间的扶手椅上。房间由百叶窗减弱的自然光照亮。我们的参与者的头大约位于屏幕前1米。图像以白色背景上的黑色图画的形式集中呈现,没有任何尺寸修改(10厘米x 10厘米)。这种设置对应于从注视点的最大靠近度2.86度的视角,从而使整个图像处于参与者的中心凹视野内。声音通过50瓦的罗技扬声器显示,没有任何音频隔离的可能性。
悦影科技
2021/05/01
6660
用于追踪认知任务期间的亚秒级脑动态的高密度脑电
Biological Psychiatry ERP结合fMRI研究:精神分裂症(SZ)和自闭症患者(ASD)视感觉识别的模式差异
文献导读:不同疾病在临床症状上的相同表现往往会引起研究者对其成因的探究,因为相似的临床表现可能是由于类似的神经基础导致的,而不同病理成因又会对这种相似的神经机制产生特异性的影响,明确不同疾病在相似临床特征表现背后的神经机制的相似性和特异性可能能够为临床治疗提供更加针对性的建议。
用户1279583
2019/08/01
1K0
Biological Psychiatry ERP结合fMRI研究:精神分裂症(SZ)和自闭症患者(ASD)视感觉识别的模式差异
使用时空-频率模式分析从脑电数据的一些试验中提取N400成分
关于高小榕教授的介绍,可以查看本社区之前分享的《第1期 | 国内脑机接口领域专家教授汇总》
脑机接口社区
2020/07/28
9010
BRAIN:额颞叶痴呆患者情绪加工的任务态功能磁共振研究
情绪信息加工受损是额颞叶痴呆综合征的一个核心特征,但其潜在的神经机制却很难被描述和测量。要想在该领域取得进展有赖于对大脑活动中的功能进行测量,以及对情绪加工中诸成分,如感觉解码、情绪分类和情绪传染等进行有效的分离。在功能测量方面,task-fMRI有着极强的优势,它可以通过观察受试者在加工任务时所产生的血氧水平变化来反映受试者在加工该任务时大脑中的活跃区域,从而来达到对大脑特定功能加工区域的观察目的。但是,task-fMRI实验中也存在着相当多的噪声影响,除去静息态也会面对的头动噪声和机器噪声外,情绪识别类的任务对被试的心理生理状况(如心跳)和眼动状况(如瞳孔大小变化)会产生额外的噪声影响,因此,对这部分信息进行收集并将其考虑进统计模型中,对于数据的精细解释是有必要的。
用户1279583
2019/10/10
1.4K0
BRAIN:额颞叶痴呆患者情绪加工的任务态功能磁共振研究
伪影校正时选择脑电图的独立成分的实用指南
背景:脑电图数据很容易受到非神经来源信号的污染。独立分量分析(ICA)可以帮助EEG数据对这些伪影进行校正。伪迹的独立成分(ICs)可以由专家通过目测识别。但是伪迹特性有时是模糊的或难以注意到的,甚至专家也可能不同意如何对特定伪迹进行分类。因此,将伪迹属性告知用户,并给他们机会进行干预是很重要的。
用户1279583
2022/02/28
2.7K2
伪影校正时选择脑电图的独立成分的实用指南
注视眼动的控制和功能
人类和其他物种通过每秒两到三次的快速眼球运动(扫视)来探索视觉场景。虽然在扫视的短暂间隔中,眼睛可能看起来不动,但在快速照相机下可以观察到眼球运动始终存在,甚至当观察者注视一个单一点时也是如此。这些运动发生在获取和处理视觉信息的特定时期,它们的功能一直是争论不休的话题。最近在控制正常眼动活动期间的视网膜刺激方面的技术进展,已经阐明了注视眼动的视觉贡献以及这些运动可以被控制的程度。在本文中回顾的大量证据表明,注视眼动是视觉系统处理精细空间细节策略的重要组成部分;它们既能精确定位视网膜上的刺激,又能将空间信息编码到关节的时空域中。本文发表在Annual Review of Vision Science杂志。
用户1279583
2020/07/14
1.4K0
注视眼动的控制和功能
Neuroimage:准备电位是否只在运动前出现?
2019年10月,伦敦大学认知神经科学研究所的Travers团队在Neuroimage期刊上发表了一篇关于准备电位(RP)是否只发生在运动前的研究,其研究结果支持经典的RP解释,即RP只发生在运动行动之前。    准备电位RP是自主运动之前缓慢上升的负电位,传统观点认为RP发生在辅助运动区和前辅助运动区,当大脑无意识的决定运动时RP开始出现,RP在运动命令通过主运动区传送出去后达到峰值,RP主要反映了运动准备过程。经典的RP解释包含两层假设,一是RP是针对自主运动(voluntary actions)的,它应该发生在自主运动之前,而不是在非自主运动之前;二是当被试可能产生运动但并没有运动时RP不应该出现。由于RP的测量方法,第二个假设很难验证。由于脑电图记录固有的信噪比低的特点,因此在单个trial中很难识别出自主运动之前的RP。RP研究通常基于运动的时刻提取trials,然后将大量的试次平均在一起。任何与RP波形相似但不会导致动作的单次试验脑电图都将被忽略(下文称:RP-like events),因为在它们之后并没有发生运动,根据提取trials的规则,并没有提取这些数据段。因此,研究者认为自主运动前的RP是基于有偏差的抽样得到到的, RP-likeevents很可能一直在发生,但是并没有被研究者注意到。   最近,Schurger和他的同事们提出了随机决策模型,它的一个重要结论是,在整段数据中都应该出现RP-like events,只是当RP-like events的幅值超过决策阈值时,就会产生运动,反之,不产生运动,一般提取的RP属于前者的叠加结果。   在该文的研究中,Travers团队使用模板匹配的方法来研究RP-like evets出现的时间点,研究其是否只在自主运动之前出现。
悦影科技
2020/11/18
7360
Neuroimage:准备电位是否只在运动前出现?
EEG微状态:注意力缺陷多动症ADHD新的功能生物标记物
背景:ADHD的EEG研究历来都集中于EEG频谱或者事件相关电位上。本研究中,我们探讨了一种替代性框架——EEG微状态(MS)作为一种检查ADHD大尺度皮层动态性的新方法,MS是重复出现地形图模式的聚类。
悦影科技
2022/11/07
5930
静息态EEG微状态:现状及未来发展方向
EEG具有高时间分辨率,是研究大脑电活动的有力工具。已有研究提出数种从EEG信号中提取信息的方法,微状态分析是其中一种,它认为多通道EEG记录是一系列准稳态的微状态,每个微状态的特征是整个通道独特的地形图拓扑结构。该方法同时考虑整个大脑皮层区域的信号,能评估大尺度脑网络功能,并且这些网络的损坏与数种神经精神障碍有关。来自哈佛医学院Berenson-Allen无创脑刺激中心和多伦多大学Temerty大脑治疗干预中心的Arjun Khanna、Faranak Farzan等人在Neuroscience & Biobehavioral Reviews发表文章。包含几方面内容:
用户1279583
2019/09/03
1.5K0
静息态EEG微状态:现状及未来发展方向
Current Biology脑电研究:自闭症患者双眼竞争较慢
请点击上面“思影科技”四个字,选择关注我们,思影科技专注于脑影像数据处理,涵盖(fMRI,结构像,DTI,ASL,EEG/ERP,FNIRS,眼动)等,希望专业的内容可以给关注者带来帮助,欢迎留言讨论,也欢迎参加思影科技的其他课程。(文末点击浏览)
用户1279583
2019/11/01
1.2K0
Current Biology脑电研究:自闭症患者双眼竞争较慢
推荐阅读
相关推荐
BRAIN脑电研究:使用快速球方法评估阿尔茨海默病识别记忆
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • MVC 三层架构案例详细讲解
    • 每博一文案
    • 1. MVC 概述
    • 2. MVC设计思想
    • 3. 三层架构
    • 4. MVC 与 三层架构的关系:
    • 5. 案例举例:用户账户转账
      • 5.1 M(Model :数据/业务处理层)
      • 5.2 C (Controller : 控制层)
      • 5.3 V (View :视图/展示)
    • 6. 总结:
    • 7. 最后:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档