SpringAOP入门基础银行转账实例------------事务处理

news2024/11/23 2:20:36

SpringAOP入门基础银行转账实例------------事务处理

AOP为Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

AOP编程思想

AOP面向切面是一种编程思想,是oop的延续,是软件开发中的一个热点,也是Spring框架中的一个重要的内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部门进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP得应用场景:

事务管理

权限校验

日志记录

性能监控

Spring 中常用的术语

Joinpoint(连接点) :所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点

Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。真正增强的方法

Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。

通知的类型:前置通知,正常返回通知,最终通知,环绕通知

Introduction(引介,了解):引介是一种特殊的通知在不修改类代码的前提下,Introduction 可以在运行期为类动态地添加一些方法或Field.

Target(目标对象):代理的目标对象

Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类

Weaving(织入):是指把增强应用到目标对象来创建新的对香港的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期植入

Aspect(切面):是切入点和通知(引介)的结合,描述了 增强具体应用的位置。

AOP的作用及优势

作用:在程序运行期间,在不修改源代码的情况下对方法进行功能增强。体现了java语言的动态性(反射)

优势:减轻重复代码,提高开发效率,并且便于维护

Spring 实现转账案例

实现所需:

一个account表用于存储用户的信息和基本金额:

在这里插入图片描述

建立maven的项目模块文件:

在这里插入图片描述

注意:其中这里的工具类ConnectionUtil、TransactionUtil是后面做测试用的可以不用建立

entity:Accoun.java

package com.etime.entity;

import java.io.Serializable;

public class Account implements Serializable {
    private Integer id;
    private String name;
    private double money;

    public Account() {
    }

    public Account(Integer id, String name, double money) {
        this.id = id;
        this.name = name;
        this.money = money;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

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

dao:AccountDao.java

package com.etime.dao;

import com.etime.entity.Account;

import java.sql.SQLException;

public interface AccountDao {
    Account getByName(String name);
    int updateAccount(Account account);
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>7</source>
                    <target>7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <groupId>com.etime</groupId>
    <artifactId>day05</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <spring.version>5.2.5.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!--导入spring的context坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--导入Jdbc模块依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--   DBUtils    -->
        <!--        <dependency>-->
        <!--            <groupId>commons-dbutils</groupId>-->
        <!--            <artifactId>commons-dbutils</artifactId>-->
        <!--            <version>1.6</version>-->
        <!--        </dependency>-->

        <!-- 数据库相关 -->
        <!--        <dependency>-->
        <!--            <groupId>mysql</groupId>-->
        <!--            <artifactId>mysql-connector-java</artifactId>-->
        <!--            <version>5.1.6</version>-->
        <!--        </dependency>-->

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

        <!--c3p0-->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

<!--        添加测试依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

<!--        dbutils依赖的添加-->
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>

<!--        添加aop配置依赖-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>
    </dependencies>
</project>

SpringConfig.java

package com.etime.util;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;

//指定当前类的配置类相当于application.xml
@Configuration
@Import(DataSourceConfig.class)//导入连接数据
@ComponentScan("com.etime")//扫描文件
//@EnableAspectJAutoProxy//开启spring对注解AOP的支持
public class SpringConfig {
}

jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_school?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=h123456

DataSourceConfig.java

package com.etime.util;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

@PropertySource("classpath:jdbc.properties")
public class DataSourceConfig {
    @Value("${jdbc.driver}")
    private String driverClass;

    @Value("${jdbc.url}")
    private String jdbcUrl;

    @Value("${jdbc.username}")
    private String user;

    @Value("${jdbc.password}")
    private String password;

    public DataSource getDataSource(){
        ComboPooledDataSource ds= new ComboPooledDataSource();
        try {
            ds.setDriverClass(driverClass);
            ds.setJdbcUrl(jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return ds;
    }

    @Bean(name="jdbcTemplate")
    public JdbcTemplate getJdbcTemplate(){
        return new JdbcTemplate(getDataSource());
    }

//    @Bean(name ="connection")
//    public Connection getConnection() throws SQLException {
//        return getDataSource().getConnection();
//    }
//
//    @Bean(name = "queryRunner")
//    public QueryRunner getQueryRunner(){
//        return new QueryRunner();
//    }
}

dao.impl:AccountDaoImpl.java

package com.etime.dao.impl;

import com.etime.dao.AccountDao;
import com.etime.entity.Account;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.sql.Connection;
import java.sql.SQLException;

@Repository("ad")
public class AccountDaoImpl implements AccountDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
//    @Autowired
//    private Connection connection;
//
//    @Autowired
//    private QueryRunner queryRunner;

    public Account getByName(String name){
        Account account=null;
        String sql="select * from account where name=?";
        account=jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<>(Account.class),name);
        return account;
    }

    public int updateAccount(Account account){
        int rows=0;
        String sql="update account set money=? where id=?";
        rows=jdbcTemplate.update(sql,account.getMoney(),account.getId());
        return rows;
    }
}

service:AccountService.java

package com.etime.service;

import java.sql.SQLException;

public interface AccountService {
    void transferAccount(String name1,String name2,double money);
}

service:AccountServiceImpl.java

package com.etime.service.impl;

import com.etime.dao.AccountDao;
import com.etime.entity.Account;
import com.etime.service.AccountService;
import com.etime.util.TransactionUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.SQLException;

@Service("as")
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;

//    @Autowired
//    private TransactionUtil transactionUtil;

    //这里不能将此处的异常try,catch.spring只能捕捉throws的异常
    @Override
    public void transferAccount(String name1, String name2, double money){
//        try {
            //开启事务
            //transactionUtil.startTransaction();
            //收到的钱
            Account accountOne=accountDao.getByName(name1);
            accountOne.setMoney(accountOne.getMoney()+money);
            accountDao.updateAccount(accountOne);

            //钱转出
            Account accountTwo=accountDao.getByName(name2);
            accountTwo.setMoney(accountTwo.getMoney()-money);
            accountDao.updateAccount(accountTwo);

            //以上数据没有数据操作错误,就提交
            //transactionUtil.commitTransaction();
//        }catch (SQLException e){
//            //如果数据有误,进行数据回滚
//            //transactionUtil.rollBackTransaction();
//            e.printStackTrace();
//        }finally {
//            //如果服务结束,事务关闭(不管是否服务成功都进行最后的事务关闭)
//            //transactionUtil.closeTransaction();
//        }
    }
}

测试转账业务

正常的数据测试

AccountDemo.java

package com.etime.demo;

import com.etime.service.AccountService;
import com.etime.util.SpringConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.sql.SQLException;


@RunWith(SpringJUnit4ClassRunner.class)
//注意文件的配置,莫要写错
@ContextConfiguration(classes = {SpringConfig.class})
//@ContextConfiguration(locations = {"classpath:application.xml"})
public class AccountDemo {
    @Autowired
    private ApplicationContext context;

    @Test
    public void t01(){
        AccountService accountService=(AccountService)context.getBean("as");
        accountService.transferAccount("hh","hu",30000);
    }
}

运行结果:

没有事务异常的情况下正常运行:

在这里插入图片描述

数据异常会有事务异常需要处理,并且数据前后需要一致性:

异常情况下:即转账金额大于现有金额就会有事务处理异常
在这里插入图片描述

在这里插入图片描述

如图的转账明显不合理,本来没有金额,还把金额加上

处理事务问题

在DataSourceConfig中添加QueryRunner对象的初始化以及Connection对象的初始化

DataSourceConfig.java

package com.etime.util;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

@PropertySource("classpath:jdbc.properties")
public class DataSourceConfig {
    @Value("${jdbc.driver}")
    private String driverClass;

    @Value("${jdbc.url}")
    private String jdbcUrl;

    @Value("${jdbc.username}")
    private String user;

    @Value("${jdbc.password}")
    private String password;

    public DataSource getDataSource(){
        ComboPooledDataSource ds= new ComboPooledDataSource();
        try {
            ds.setDriverClass(driverClass);
            ds.setJdbcUrl(jdbcUrl);
            ds.setUser(user);
            ds.setPassword(password);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return ds;
    }

//    @Bean(name="jdbcTemplate")
//    public JdbcTemplate getJdbcTemplate(){
//        return new JdbcTemplate(getDataSource());
//    }

    @Bean(name ="connection")
    public Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    }

    @Bean(name = "queryRunner")
    public QueryRunner getQueryRunner(){
        return new QueryRunner();
    }
}

编写事务管理工具

TransactionUtil是管理事务的工具类,主要定义了和事务相关的方法,事务开启,事务提交,事务回滚等。该工具目前需要手动创建和管理,使用Spring进行事务管理后,该工具类由Spring提供,不需要手动编写和管理。所以该工具类重在理解,为Spring进行事务管理做好铺垫

TransactionUtil.java

package com.etime.util;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.SQLException;

@Component("transactionUtil")
//声明为切面
@Aspect
public class TransactionUtil {
    @Autowired
    private Connection connection;
//
//    @Pointcut("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")
//    private void point(){}
//
//    //把当前方法看成是前置通知
//    //@Before("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")
    @Before("point()")
    public void startTransaction(){
        try {
            System.out.println("开启事务");
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
//
//    //把当前方法看作是后置通知
//    //@AfterReturning("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")
//    //@AfterReturning("point()")
    public void commitTransaction(){
        try {
            System.out.println("事务提交");
            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
//
//    //把当前方法看作是异常通知
//    //@AfterThrowing("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")
//    //@AfterThrowing("point()")
    public void rollBackTransaction(){
        try {
            System.out.println("事务回滚");
            connection.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
//
//    //把当前的方法看作是运行结束通知的方法
//    //@After("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")
//    //@After("point()")
    public void closeTransaction(){
        try {
            System.out.println("释放资源");
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
//
//    //环绕通知方法
//    //把当前方法看成是环绕通知
//    //@Around("execution(public void com.etime.service.impl.AccountServiceImpl.transferAccount(..))")
//    @Around("point()")
//    public Object transactionAround(ProceedingJoinPoint pjp){
//        Object result = null;
//        try {
//            //获取调用切入点方法时传入的参数
//            Object[] args = pjp.getArgs();
//            //启动事务
//            startTransaction();
//            //运行切入点方法
//            result = pjp.proceed(args);
//            commitTransaction();
//        } catch (Throwable e) {
//            //运行有误需要回滚
//            rollBackTransaction();
//            e.printStackTrace();
//        }finally {
//            //运行结束释放资源
//            closeTransaction();
//        }
//        return result;
//    }
}

dao:AccountDao.java

package com.etime.dao;

import com.etime.entity.Account;

import java.sql.SQLException;

public interface AccountDao {
    Account getByName(String name) throws SQLException;
    int updateAccount(Account account) throws SQLException;
}

dao:AccountDaoImpl.java

package com.etime.dao.impl;

import com.etime.dao.AccountDao;
import com.etime.entity.Account;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.sql.Connection;
import java.sql.SQLException;

@Repository("ad")
public class AccountDaoImpl implements AccountDao {
//    @Autowired
//    private JdbcTemplate jdbcTemplate;
    @Autowired
    private Connection connection;

    @Autowired
    private QueryRunner queryRunner;

    public Account getByName(String name) throws SQLException {
        Account account=null;
        String sql="select * from account where name=?";
        account=queryRunner.query(connection,sql,new BeanHandler<>(Account.class),name);
        return account;
    }

    public int updateAccount(Account account) throws SQLException {
        int rows=0;
        String sql="update account set money=? where id=?";
        rows=queryRunner.update(sql,account.getMoney(),account.getId());
        return rows;
    }
}

service:AccountService.java

package com.etime.service;

import java.sql.SQLException;

public interface AccountService {
    void transferAccount(String name1,String name2,double money);
}

service:AccountServiceImpl.java

package com.etime.service.impl;

import com.etime.dao.AccountDao;
import com.etime.entity.Account;
import com.etime.service.AccountService;
import com.etime.util.TransactionUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.SQLException;

@Service("as")
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;

    @Autowired
    private TransactionUtil transactionUtil;

    //这里不能将此处的异常try,catch.spring只能捕捉throws的异常
    @Override
    public void transferAccount(String name1, String name2, double money){
        try {
            //开启事务
            transactionUtil.startTransaction();
            //收到的钱
            Account accountOne=accountDao.getByName(name1);
            accountOne.setMoney(accountOne.getMoney()+money);
            accountDao.updateAccount(accountOne);

            //钱转出
            Account accountTwo=accountDao.getByName(name2);
            accountTwo.setMoney(accountTwo.getMoney()-money);
            accountDao.updateAccount(accountTwo);

            //以上数据没有数据操作错误,就提交
            transactionUtil.commitTransaction();
        }catch (SQLException e){
            //如果数据有误,进行数据回滚
            transactionUtil.rollBackTransaction();
            e.printStackTrace();
        }finally {
//            //如果服务结束,事务关闭(不管是否服务成功都进行最后的事务关闭)
            transactionUtil.closeTransaction();
        }
    }
}

测试:

AccountDemo.java

package com.etime.demo;

import com.etime.service.AccountService;
import com.etime.util.SpringConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.sql.SQLException;


@RunWith(SpringJUnit4ClassRunner.class)
//注意文件的配置,莫要写错
@ContextConfiguration(classes = {SpringConfig.class})
//@ContextConfiguration(locations = {"classpath:application.xml"})
public class AccountDemo {
    @Autowired
    private ApplicationContext context;

    @Test
    public void t01(){
        AccountService accountService=(AccountService)context.getBean("as");
        accountService.transferAccount("hh","hu",30000);
    }
}

运行结果:

在这里插入图片描述

在这里插入图片描述

处理了事务,如果遇到抛出问题,数据库进行操作的不满足加连之前的操作全部回滚,这样才满足数据操作前后一致性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 字符串format()格式化 / 索引

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 为了确保字符串按预期显示&#xff0c;我们可以使用 format() 方法对结果进行格式化。 字符串 format() format() 方法允许您格式化字符串的选定部分。 有时文本的一部分是你无法控制的&#xff0c;也许它们来自数据库或…

更深度了解getchar和putchar现象

目录 前言&#xff1a; 1.getchar和putchar 1.1基本使用 1.2一些特殊打印 1.3putchar打印空格 2.深度了解现象 前言&#xff1a; 经过学习&#xff0c;总结getchar()函数和putchar()函数在搭配使用while循环的时候&#xff0c;控制台窗口光标位置的出现位置的由来。 1.…

JavaSE学习进阶day04_03 包装类

第五章 包装类&#xff08;重点&#xff09; 5.1 概述 Java提供了两个类型系统&#xff0c;基本类型与引用类型&#xff0c;使用基本类型在于效率&#xff0c;然而很多情况&#xff0c;会创建对象使用&#xff0c;因为对象可以做更多的功能&#xff0c;如果想要我们的基本类型…

蓝桥杯15单片机--超声波模块

目录 一、超声波工作原理 二、超声波电路图 三、程序设计 1-设计思路 2-具体实现 四、程序源码 一、超声波工作原理 超声波时间差测距原理超声波发射器向某一方向发射超声波&#xff0c;在发射时刻的同时开始计时&#xff0c;超声波在空气中传播&#xff0c;途中碰到障碍…

计算属性,watch和watchEffect

计算属性-computed 什么是计算属性&#xff1a; computed函数&#xff0c;是用来定义计算属性的&#xff0c;计算属性不能修改。 模板内的表达式非常便利&#xff0c;但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。 计算属性还可以依…

【目标检测论文阅读笔记】Extended Feature Pyramid Network for Small Object Detection

&#xff08;未找到代码&#xff0c;只有yaml文件&#xff09; Abstract. 小目标检测仍然是一个未解决的挑战&#xff0c;因为很难提取只有几个像素的小物体的信息。虽然特征金字塔网络中的尺度级对应检测缓解了这个问题&#xff0c;但我们发现各种尺度的特征耦合仍然会损害小…

百度飞桨paddlespeech实现小程序实时语音流识别

前言&#xff1a; 哈哈&#xff0c;这是我2023年4月份的公司作业。如果仅仅是简单的语音识别倒也没什么难度&#xff0c;wav文件直接走模型输出结果的事。可是注意标题&#xff0c;流式识别、实时&#xff01; 那么不得不说一下流式的优点了。 1、解决内存溢出的烦恼。 2、…

《论文阅读》Unified Named Entity Recognition as Word-Word Relation Classification

总结 将NER视作是word-word间的 Relation Classification。 这个word-word 间的工作就很像是TPlinker那个工作&#xff0c;那篇工作是使用token间的 link。推荐指数&#xff1a;★★★☆☆值得学习的点&#xff1a; &#xff08;1&#xff09;用关系抽取的方法做NER抽取 &…

佳明手表APP开发系列01——简单汉化英文版

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、佳明手表APP开发过程简介二、做个简单的个性化——在英文版写几个汉字1.MonkeyC 图形处理2.获得汉字点阵字模数据3.MonkeyC 汉字输出函数总结前言 佳明手表…

蓝海创意云应邀参与苏州市元宇宙生态大会

4月14日&#xff0c;苏州市软件行业协会元宇宙专委会成立大会暨元宇宙生态大会在苏成功举办。此次大会由苏州市工业和信息化局指导&#xff0c;苏州高新区&#xff08;虎丘区&#xff09;经济发展委员会、苏州市软件行业协会主办&#xff0c;蓝海彤翔集团作为协办单位参与此次大…

IDEA集成Git、GitHub、Gitee

一、IDEA 集成 Git 1.1、配置 Git 忽略文件 为什么要忽略他们&#xff1f; 与项目的实际功能无关&#xff0c;不参与服务器上部署运行。把它们忽略掉能够屏蔽 IDE 工具之间的差异。 怎么忽略&#xff1f; 创建忽略规则文件 xxxx.ignore&#xff08;前缀名随便起&#xff0c…

创建Google play开发者账号,并验证身份通过

一、注册前准备 最好准备一台没有怎么用过Google的电脑和&#x1fa9c;准备一个没有注册过Google的手机号准备一张信用卡或者借记卡&#xff08;需要支付$25&#xff09;&#xff0c;支持的类型如下图 这里还需注意&#xff1a;最后账号注册成功还需要验证身份也就是实名认证&…

关于Python爬虫的一些总结

作为一名资深的爬虫工程师来说&#xff0c;把别人公开的一些合法数据通过爬虫手段实现汇总收集是一件很有成就的事情&#xff0c;其实这只是一种技术。 初始爬虫 问题&#xff1a; 什么是爬虫&#xff1f; 网络爬虫是一种按照一定的规则&#xff0c;自动地抓取网络信息的程…

动态规划算法OJ刷题(3)

CC19 分割回文串-ii 问题描述 给出一个字符串s&#xff0c;分割s使得分割出的每一个子串都是回文串。计算将字符串s分割成回文串的最小切割数。例如:给定字符串s“aab”&#xff0c;返回1&#xff0c;因为回文分割结果[“aa”,“b”]是切割一次生成的。 解题思路 方法1&…

计算机操作系统(第四版)第四章存储器管理—课后习题答案

1.为什么要配置层次存储器&#xff1f; &#xff08;1&#xff09;设置多个存储器可以使存储器两端的硬件能并行工作。 &#xff08;2&#xff09;采用多级存储系统,特别是Cache技术,这是一种减轻存储器带宽对系统性能影响的最佳结构方案。 &#xff08;3&#xff09;在微处理机…

《Java8实战》第5章 使用流

上一章已经体验到流让你从外部迭代转向内部迭代。 5.1 筛选 看如何选择流中的元素&#xff1a;用谓词筛选&#xff0c;筛选出各不相同的元素。 5.1.1 用谓词筛选 filter 方法&#xff0c;该操作会接受一个谓词&#xff08;一个返回boolean 的函数&#xff09;作为参数&am…

MySQL数据库:聚合函数、分组查询、约束、默认值设置、自增属性

一、聚合函数 1.聚合函数 在MySQL数据库中预定义好的一些数据统计函数。 2.count(*) 功能&#xff1a;统计结果条数。 3.sum(字段名) 功能&#xff1a;对指定字段的数据求和。 4.avg(字段名) 功能&#xff1a;对指定字段的数据求平均值。 5.max(字段名) 和 min(字段名) …

正则化的基本认识

正则化(一) 拟合与欠拟合(二) 正则化的目的(三) 惩罚项&#xff08;3.1&#xff09;常用的惩罚项&#xff1a;&#xff08;3.2&#xff09;L-P范数&#xff1a;&#xff08;3.3&#xff09;L1与L2的选择&#xff1a;(一) 拟合与欠拟合 欠拟合&#xff1a; 是指测试级与训练集都…

docker目录映射

docker 常用命令 docker ps // 查看所有正在运行容器 docker stop containerId // containerId 是容器的ID docker ps -a // 查看所有容器 $ docker ps -a -q // 查看所有容器ID docker stop $(docker ps -a -q) // stop停止所有容器 docker rm $(docker ps -a -q) // remove删…

受害者有罪论——如何反驳

目录 一、那些「受害者有罪论」的说法 二、「受害者有罪论」的潜台词 三、如何反驳 反驳1&#xff1a;让受害者有罪论者感同身受 反驳2&#xff1a;说理 反驳3&#xff1a; 直接指出结论的错误 反驳4&#xff1a;与对方无关&#xff0c;不用多费唇舌 四、罪犯就是罪犯&…