【Java】代码结构设计思考

代码设计:设计模式:10个结构型设计模式 以顺序表结构为基础,在表中传递数据或事件 举例:Java/Android的类加载机制以树状结构为基础,树中传递数据或事件 举例:Android的ViewTreeA->Mediator->B(->代表依赖)Mediator作为中介者,实现间接的A调用B的方法Adapter作为中介者,负责复用旧代码,完成新功能装饰器作为中介者,负责扩展旧的功能,在旧的功能的基础上添加新的代码代理器作为中介者,负责对旧功能是否能实现进行 阅读详情

背景

这篇博文是博主在做数据图形统计相关接口工作过程中对代码结构设计的一些思考总结,仅代表个人观点。

1.需求简述

提供资金关系数据图形统计,根据不同菜单地址跳转至对应图形页面显示相关业务统计数据。

2.开发设计过程

2.1 在开发的初期,考虑到各个数据图形统计具体实现细节的不同,以及代码的可扩展性(非全面),博主是这样设计的(忽略网络请求的复杂细节以及框架细节)。



图1 初期结构设计图

服务端提供不同的请求地址给客户端调用,如图中的 /a, /b, /c, 每种请求地址对应一种数据图形的统计。后续各自的service实现各自图形统计的具体逻辑,互不干扰。当我们新增一种图形统计的类型时,只要对应的增加请求地址/d、图形D Controller、图形D Service,不会影响其他图形数据的统计。后续的增加以此类推。

2.2 初期开发完成后,博主发现虽然各图形service的具体实现逻辑不同,但是对于提供给对应controller的api都是一样的,而且只需对外提供一个请求链接并用特定字段标记就可以区分,于是对于图1中的结构进行修改。



图2 改进结构设计图

服务端仅提供一个请求入口地址/statistics,同时用type字段来进行区分当前我们所需要处理的是哪种图形数据的统计,并调用对应的service服务进行统计处理。

这种设计与图1的设计相比而言有以下好处:

  1. 减少了不同种类的图形Controller,减少了请求入口地址
  2. 在图形Controller与各个图形Service之间新增了一层图形抽象Service(可以是抽象类、接口),统一了对外提供访问的api

到这一步,其实就有点我们设计模式当中策略模式的意思了。图2中的图形抽象Service可以理解为策略模式当中的抽象策略类,而我们具体的图形A Service、图形B Service、图形C Service也可以与策略模式中的具体策略类等同。从而使得图形统计的逻辑可以独立于调用方变化。

接下来在看看上层图形Controller的方法该如何写。我们需要根据type值的不同来调用我们的对应的图形Service的方法,这又不得不使用我们的工厂模式,因为我们先要根据type值来获取对应的图形Service的对象。大致的伪代码如下(这里忽略Controller方面的细节):

	.....
	图形抽象Service;
	switch (type) {
		case "a":
			图形抽象Service = 图形AService对象;
			break;
		case "b":
			图形抽象Service = 图形BService对象;
			break;
		case "c":
			图形抽象Service = 图形CService对象;
			break;
		default:
			// 异常
			break;
	}
	图形抽象Service.公共api;
	.....

设计改进

当然, 2.2 设计中创建对象的操作我们完全可以交由spring去执行(通过xml或者注解的方式注入),也就是让spring来管理bean,但我们仍无法摆脱使用switch或者if else来区分类型。新增或者减少类型,我们需要改动原有方法:增加或者减少对应switch或者if else分支。

举个例子,针对 2.2 中的代码,假如我们要新增一类图形D的数据统计,那怎么办?
我们当然会这样做:在实现图形D Service数据统计逻辑的同时,再在上述代码中新增case "d"的分支。

新增图形D的数据统计类是没什么问题的,但是对于getResult这个方法来说就有点违背设计模式六大原则中的开闭原则,因为其不仅对扩展开放了,而且对修改也开放了。

所以博主针对这块,再做一小改进。

回到前面spring管理bean上,看过spring源码的同学应该会更加清楚:在我们的spring容器当中,bean是存储在我们的map当中的,并以id为key值,bean实例为value值。那也就是说,假如我们拥有这样一个map:以标记字段值为key值,bean实例为value值,那我们就可以通过传入的标记字段值(2.2中的type)直接获取实例bean并调用对应的公共方法。

代码实现

由于上述例子涉及相关业务,相对繁琐,为简单起见,博主以计算几种几何图形为周长面积为例,用square、triangle、circular作为标记字段type的值,分别对应正方形、全等三角形、圆。

以下列出实现的主要代码。

1.几何图形Service服务管理类

主要用来自己管理bean,指定规则key的值。

/**
 * 几何图形Service服务管理类
 * Created by Hilox on 2018/12/11 0011.
 */
@Service
public class GeometryServiceManager {

    /**
     * 管理实现类
     */
    private static Map<String, Class<?>> initialCategories = new ConcurrentHashMap<>();

    private static Map<String, GeometryAbstractService> categoryMap = new ConcurrentHashMap<>();

    /**
     * 默认构造方法
     */
    public GeometryServiceManager() {}

    /**
     * 子类自注册方法
     */
    public GeometryServiceManager(String name, Class<?> serviceName) {
        initialCategories.put(name, serviceName);
    }

    /**
     * 根据传入标记字段值获取对应的几何图形服务
     * @param name
     * @return
     */
    public GeometryAbstractService getServiceByName(String name) {
        if (StringUtils.isEmpty(name)) {
            throw new IllegalArgumentException("Type不能为空!");
        }

        // 扫描预置的实现类
        scanForService();

        if (categoryMap.containsKey(name)) {
            return categoryMap.get(name);
        } else {
            throw new IllegalArgumentException("对应几何图形服务未注册!");
        }
    }

    /**
     * 扫描几何图形服务注册实现类
     * 为确保获取正确服务, 需要调用scanForService方可正确注册
     */
    private void scanForService() {
        initialCategories.forEach((key, value) -> registryService(key, (GeometryAbstractService) ApplicationContextHelper.getApplicationContext().getBean(value), true));
    }

    /**
     * 几何图形服务注册方法
     * 新增几何图形服务方法, 则将其注入到集合中
     * @param name
     * @param geometryAbstractService
     * @param replace 同名是否替换现有的服务, 默认为false:不替换
     */
    private void registryService(String name, GeometryAbstractService geometryAbstractService, boolean replace) {
        if (!categoryMap.containsKey(name) || replace) {
            categoryMap.put(name, geometryAbstractService);
        }
    }

    /**
     * 根据名称卸载几何图形服务方法
     * @param name
     */
    private void unRegistryService(String name) {
        if (categoryMap.containsKey(name)) {
            categoryMap.remove(name);
        }
    }

    /**
     * 根据方法卸载几何图形服务方法
     */
    private void unRegistryService(GeometryAbstractService geometryAbstractService) {
        if (categoryMap.containsValue(geometryAbstractService)) {
            categoryMap.remove(geometryAbstractService);
        }
    }
}

2.几何图形Service抽象父类

作为所有几何图形Service的抽象父类,继承了我们自己定义的服务管理类。在这个抽象类中,主要用来写一些对外提供的api,以及所有子类涉及到的公共方法。

/**
 * 所有几何图形Service抽象父类
 * Created by Hilox on 2018/12/11 0011.
 */
public abstract class GeometryAbstractService extends GeometryServiceManager {

    /**
     * 默认构造方法
     */
    public GeometryAbstractService() {}

    /**
     * 子类自注册方法
     */
    public GeometryAbstractService(String name, Class<?> serviceName) {
        super(name, serviceName);
    }

    /**
     * 获取几何图形周长
     * @param condition
     * @return
     */
    public abstract Object getPerimeter(GeometryCondition condition);

    /**
     * 获取几何图形面积
     * @param condition
     * @return
     */
    public abstract Object getArea(GeometryCondition condition);
}

3.具体图形的Service实现

具体图形Service继承了几何图形Service抽象父类,实现了其中的抽象方法的具体内容(当前也可以覆盖父类方法达到目的)。这里最主要的一点就是自注册,通过构造方法调用父类的构造方法,在通过父类构造方法的处理注册到我们的服务管理器类的静态容器当中,以便后续通过标记字段值提取指定服务。

3.1正方形
/**
 * 正方形Service
 * Created by Hilox on 2018/12/11 0011.
 */
@Service
public class SquareService extends GeometryAbstractService {

    /**
     * 自注册
     */
    public SquareService() {
        super(GeometryTypeConstant.SQUARE, SquareService.class);
    }

    @Override
    public BigDecimal getPerimeter(GeometryCondition condition) {
        BigDecimal side = condition.getSide();
        if (side == null) {
            throw new IllegalArgumentException("正方形边长不能为空!");
        }
        // 4 * side
        BigDecimal result = side.multiply(new BigDecimal(4));
        return result;
    }

    @Override
    public BigDecimal getArea(GeometryCondition condition) {
        BigDecimal side = condition.getSide();
        if (side == null) {
            throw new IllegalArgumentException("正方形边长不能为空!");
        }
        // side * side
        BigDecimal result = side.pow(2);
        return result;
    }

}
3.2等边三角形
/**
 * 全等三角形Service
 * Created by Hilox on 2018/12/11 0011.
 */
@Service
public class TriangleService extends GeometryAbstractService {

    /**
     * 自注册
     */
    public TriangleService() {
        super(GeometryTypeConstant.TRIANGLE, TriangleService.class);
    }

    @Override
    public BigDecimal getPerimeter(GeometryCondition condition) {
        BigDecimal side = condition.getSide();
        if (side == null) {
            throw new IllegalArgumentException("全等三角形边长不能为空!");
        }
        // 3 * side
        BigDecimal result = side.multiply(new BigDecimal(3));
        return result;
    }

    @Override
    public Double getArea(GeometryCondition condition) {
        BigDecimal side = condition.getSide();
        if (side == null) {
            throw new IllegalArgumentException("全等三角形边长不能为空!");
        }

        // 30°
        double radians = Math.toRadians(30);
        // 计算cos30°
        double cos = Math.cos(radians);
        double sideDouble = side.doubleValue();
        // 高
        double high = sideDouble * cos;
        return high * sideDouble / 2;
    }
}
3.3圆形
/**
 * 圆形Service
 * Created by Hilox on 2018/12/11 0011.
 */
@Service
public class CircularService extends GeometryAbstractService {

    /**
     * 自注册
     */
    public CircularService() {
        super(GeometryTypeConstant.CIRCULAR, CircularService.class);
    }

    @Override
    public Double getPerimeter(GeometryCondition condition) {
        BigDecimal radius = condition.getRadius();
        if (radius == null) {
            throw new IllegalArgumentException("圆形半径不能为空!");
        }
        // 2 * π * r
        double radiusDouble = radius.doubleValue();
        return 2 * Math.PI * radiusDouble;
    }

    @Override
    public Double getArea(GeometryCondition condition) {
        BigDecimal radius = condition.getRadius();
        if (radius == null) {
            throw new IllegalArgumentException("圆形半径不能为空!");
        }
        // π * r * r
        double radiusDouble = radius.doubleValue();
        return Math.PI * radiusDouble * radiusDouble;
    }
}

4.请求地址入口Controller

通过以下代码可以看到,我们只需要通过标记字段type值来获取对应的服务进行后续的处理,摆脱了使用switch或者if else来区分类型。

/**
 * 几何图形Controller
 * Created by Hilox on 2018/12/11 0011.
 */
@Controller
public class GeometryController {

    @Autowired
    private GeometryServiceManager geometryServiceManager;

    /**
     * 获取几何图形周长
     * @param condition
     * @return
     */
    @RequestMapping("/getPerimeter")
    @ResponseBody
    public Object getPerimeter(@RequestBody GeometryCondition condition) {
        GeometryAbstractService service = geometryServiceManager.getServiceByName(condition.getType());
        return service.getPerimeter(condition);
    }

    /**
     * 获取几何图形面积
     * @param condition
     * @return
     */
    @RequestMapping("/getArea")
    @ResponseBody
    public Object getArea(@RequestBody GeometryCondition condition) {
        GeometryAbstractService service = geometryServiceManager.getServiceByName(condition.getType());
        return service.getArea(condition);
    }
}

源码传送门

【源码地址】:struct-design-one

效果展示

以计算图形周长为例:



图3 正方形计算结果图



图4 全等三角形计算结果图



图5 圆形计算结果图

【架构篇】代码组织结构设计 本文以Java项目为例,解析后端代码组织的标准化结构,涵盖模块划分原则、依赖管理策略及实际应用场景。通过模块化设计提升代码可维护性、团队协作效率及系统扩展能力。 阅读详情

相关推荐

Java网络编程——UDP聊天室(可能是全网最良心的聊天室了吧)

Java网络编程——UDP聊天室(1) 自从将要考试以来就没时间写过文章了,终于熬到了放假,闲着没事干就和小伙伴一起写了个聊天室玩玩。 本来是打算用TCP来作为通信协议的,但是呢,我这么菜,就换成简单的UDP通信协议了。 闲话就先说到这里。正文要紧。 UDP协议的基础内容: <from 百度百科> 算了我还是太懒了,直接附上链接吧: 传送门 UDP的基础类: 话不多说直接贴代码: ...

小小白的成长之路 1850

代码结构

前言 说起应用分层,大部分人都会认为这个不是很简单嘛 就controller,service, mapper三层。看起来简单,很多人其实并没有把他们职责划分开,在很多代码中,controller做的逻辑比service还多,service往往当成透传了,这其实是很多人开发代码都没有注意到的地方,反正功能也能用,至于放哪无所谓呗。这样往往造成后面代码无法复用,层级关系混乱,对后续代码的维护非常麻烦。 的确在这些人眼中分层只是一个形式,前辈们的代码这么写的,其他项目代码这么写的,那么我也这么跟着写。但是在真正的

大黄蜂的博客 1374

对于游戏服务器的一些思考和研究

客户端已经写了五六年了,但是并没有写过服务器。现在有相关的需求,希望能够以比较省时省力的方式完成服务器的开发。经验比较浅,所以以下言论只是个人观点和吐槽。             我对服务器技术的理解是这样的。做到京东、阿里这么大的规模的时候,对数据一致性、容灾、安全性、稳定性、并发性等等都有非常高的要求。这个很依赖于经验,没有足够的经验,学的再多也是纸上谈兵。 web服务器跟游戏服务器有所区

langresser的专栏 1万+

部分设计模式的典型代码结构

下面对一些设计模式的典型代码结构总结,个人认为这是在已经写过一些代码之后熟悉设计模式的最好方式

twi_twi的博客 467

程序员的思维操作系统:用programming.log实现技术思考留痕

编程日志(programming log)是一种面向工程师认知成长的轻量级知识管理实践,其本质是将碎片化、非线性的代码思考过程结构化为可追溯、可复盘、可迭代的文本记录。它基于纯文本+Git的极简技术栈,强调问题推演与证伪逻辑,而非结论堆砌;通过时间线主干结构和手动索引,规避分类强迫症,强化每日复盘习惯。相比通用笔记工具,它更聚焦‘技术判断力’的肌肉记忆训练——每一次git commit都是对思考质量的交付验收。典型应用场景包括调试溯源、API设计反思、性能临界点突破与技术债量化评估。作为程序员的外部缓存硬盘

天下无双 414

基于Javaweb+MySQL实现学生选课系统

idea:IDEA 编译器的配置文件,系统默认生成,无序关心lib 和 libs:自己下载的驱动包和第三方 jar 包,包括数据库驱动和 jstlout:字节码文件,为 Java 虚拟机实际运行的文件,编译之后生成,无需关心。SQL:数据库备份文件,完整的数据表结构和部分数据。src:Java 代码编写处DB:存放有关数据库操作的类model:存放数据表结构相关的 Java bean 类servlet:存放业务逻辑处理的 servlet 类app:放所有的 JSP 网页模板。

神仙别闹的自留地 885

主流代码设计架构的探究(MVC架构)·附C++代码实现

本文进行MVC架构的设计探究,附C++代码实现

Tzy1024的博客 2431

软件架构设计代码

软件架构设计代码软件架构设计代码

Eclipse插件结构设计思考

在进行插件开发,构建软件产品的过程中,往往涉及到很多个插件。这些插件应该如何设计?我基于自己的经验提供以下插件结构的想法: 对于整个产品,可以将产品划分为四大模块:业务无关核心层、业务相关核心层、可插拔业务层、功能与产品定制。其中业务无关核心层和业务相关核心层,共同组成了系统核心层。 系统核心层,我认为需要遵循以下原则: 每一个大版本,可增加,但不应删除核心层之中的API,以保证核心层稳...

zhangzhigong123的博客 614

DB2__基本概念——联邦

建立联邦 优点:优点是数据仍然保留在原来的存储位置,而不必建立一个集中的式数据仓储。  缺点:数据联邦查询反映会慢,不适合频繁查询,而且容易出现锁争用和资源冲突等问题 建立联邦表步骤 前提条件:知道两个数据库的ip,用户名,密码及被连数据库的版本 eg:  数据库  qqdb  ip: 22.5.225.225   端口:50000    密码:123456        数据库   ...

qq_38569524的博客 1257

让 AI 学会“慢思考”:MCP Sequential Thinking 深度部署与使用指南

摘要: MCP Sequential Thinking 是一种让AI具备"慢思考"能力的技术,通过动态调整思维路径解决复杂问题。本文详细介绍了在Windows、macOS和Linux系统下的部署方法,包括环境准备、配置文件修改等步骤。该技术通过"产生想法-评估需求-修正路径"的循环机制,显著提升AI在代码设计、数学证明等复杂任务中的表现。文章还提供了验证安装方法、使用示例和常见问题解答,帮助开发者解锁AI的深层思考能力。(149字)

weixin_43236925的博客 1914

java语言的Dao层设计(一)—— Dao层基本结构设计

Dao层——数据访问层 Dao层是具体到每个操作,每个表的增删查改。那怎么写这个数据访问层呢? 我认为有几个是必要的点,IBean、IDao这两个接口。 IBean接口 IBean接口是为了标识数据库表实体类而生的接口。继承IBean接口可以降低代码重复率,减少代码耦合。 import java.io.Serializable; public interface IBean extends Serializable { //继承序列化接口 } IDao接口 IDao接口是为了具体操作而设立的接口,继承

nicesiri的博客 4744

线阵相机标定必看:如何用Halcon实现亚毫米级精度测量(以HC050标定板为例)

本文以HC050标定板为例,详细阐述了如何利用Halcon实现线阵相机的高精度标定,以达到亚毫米级测量。文章深入剖析了线阵相机标定的核心原理、面临的独特挑战,并提供了从硬件搭建、图像采集到Halcon软件实操的完整路径,重点解析了运动参数设置、精度验证及常见问题排错,为精密测量应用提供系统解决方案。

weixin_29213655的博客 314

java关于泛型的实验代码_[ Java学习 ] 泛型类的应用实验

成文原因:这篇文章是我这周所做的 Java 实验题的一个小总结。这次实验让我深刻赞同了我们 Java 老师在这节实验课前告诉我们的话:最重要的是把问题想明白,它要怎么拆分成几个类,每个类里究竟需要哪些方法,具体细节怎么实现。当你真正把这些问题想清楚了以后,剩下的编程,其实就是很简单的事情了。难度往往不是难在编程,而是分解问题为一个个小问题后,逐一解决它们的能力。做完实验以后再来看老师这句话,觉得不...

weixin_34470566的博客 374

STM32H750xx【QSPI】轮询方式读写GD25Q64E

本文详细介绍了GD25Q64E其特性、引脚定义及功能说明,重点阐述了在STM32H750平台上通过CubeMX配置QuadSPI接口的步骤,包括时钟设置、参数优化等。文章提供了完整的BSP驱动开发流程,涵盖写使能、四线模式使能、ID读取、解除保护、扇区擦除、整片擦除、页编程和数据读取等关键功能实现,并通过读写测试验证了DummyCycles参数对数据准确性的影响。

honmy18的博客 1424

EB配置输入捕获ICU模块----基于S32K3

基于S32K311芯片,EB配置ICU输入捕获(Emios 和Siul)

weixin_43586400的博客 1772

大模型提示词工程宝典:从链式思考到智能体设计,建议收藏学习

本文详细介绍大模型提示词工程方法与结构,包括链式提示、链式思考、少样本提示等技巧,以及系统提示词的身份、目标、信息、要求等构成要素。通过构建结构化提示词,可创建专业智能体实现特定任务精准处理,并强调需结合实际场景不断测试优化以发挥大模型最大效能。

2401_85375186的博客 1360

用Obsidian搭建个人知识库:AI时代如何构建你的第二大脑

AI 时代,真正有价值的不只是获取知识,而是沉淀属于自己的知识体系。本文从 Obsidian 安装、目录设计、双向链接、插件推荐到 AI 联动、多端同步,手把手教你打造高效、可持续进化的个人知识库,让知识真正为你所用。🧠

XiaoqiangClub的博客 473

Java编程当逻辑思维遇见代码艺术

从变量的定义到方法的封装,从条件判断到循环控制,每一个环节都需要清晰的逻辑支撑。恰当的命名规范、合理的代码分层、恰到好处的注释,都是这种艺术的具体体现。在软件开发的广阔领域中,Java以其严谨的结构和强大的跨平台能力,成为无数开发者钟爱的语言。然而,真正优秀的Java编程不仅仅是语法的堆砌,更是一场逻辑思维与代码艺术的完美邂逅。当严谨的逻辑遇见灵动的艺术,代码便拥有了生命,在0和1的世界里绽放出独特的光芒。开发者需要保持开放的心态,在掌握核心原理的基础上,不断吸收新的编程范式和设计理念。

UavvMdik的博客 246

Windows - Intel(R) Wireless-AC 9462 该设备无法启动(代码 10)笔记本网卡出现感叹号无法连 wifi 解决方案

前言 一台华硕笔记本,出现了网卡无法启动,导致 wifi 无法连接问题。 如下图所示,电脑突然断网,wifi 图标变为地球,无法搜索与连接: 查看设备 首先右键 此电脑 → 管理,按如下图所示依次展开: 展开后发现出现了感叹号,说明无线设备驱动存在问题: 双击查看状态如下: 解决方案 注意:以下有 4 种解决方案,请以此按照顺序尝试解决。 一、点击驱动程序的标签页,先点击禁用设备,然后再启用设备,观察是否解决: 请选择你有问题的网卡(图片仅示例) 二、在驱动程序的标签页点击卸载设备(不

🏆 前端领域优质创作者 7万+

“快速掌握Vivado FPGA开发流程“——详解Vivado开发流程及实例

快速掌握Vivado FPGA开发流程”——详解Vivado开发流程及实例FPGA技术在现代电子领域中应用越来越广泛,而Vivado作为业界最流行的FPGA设计工具之一,也受到越来越多人的关注和使用。那么如何快速掌握Vivado FPGA开发流程呢?本文将详细介绍Vivado开发流程,并通过实例来加深您的理解。首先,我们需要了解Vivado开发流程的主要步骤:创建工程、设计电路、约束电路、生成比特流。接下来,让我们一步步了解这些步骤。

2301_78484069的博客 733

java封装/继承/多态深度思考

封装 概念:在程序中简单理解封装就是把代码整合到一起! 函数的封装:就是把一组操作整合到一起;类的封装:就是把属性和方法整合到一起;结构的封装:根据操作的性质(模型/控制操作/交互视图)进行结构设计封装. 继承解决程序的重用性的问题? 多态和抽象解决了拓展性的问题? ...

Bobwant的博客 202

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

气垫船的结构设计_我的气垫船充满了鳗鱼

气垫船的结构设计 我的“清洁代码”课程中的一个故事。 课堂练习围绕游戏井字游戏的不同方面展开。 我喜欢这款游戏作为练习平台:它似乎不需要任何需求说明。 人们了解游戏,并假设他们确切地知道他们需要如何编写代码。 他们中的大多数跳过设计阶段。 它每次都说明开发人员是如何急于“完成工作”,而不是思考,设计然后编写代码。 最初的练习之一是开始为游戏编写代码,主要侧重于名称和操作,而不...

danpu0978的博客 461

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【亲测免费】 Java编程思想 中文版 第4版

Java编程思想 中文版 第4版 去发现同类优质开源项目:https://gitcode.com/ 书籍简介 《Java编程思想(第4版)》是一本深受广大程序员喜爱的经典之作,以其深入浅出的讲解、丰富的实例和独到的见解,全面剖析了Java编程语言的核心概念和技术。此版本针对Java的最新迭代——JDK 5.0进行了全面更新,不仅涵盖了新的语言特性,还对原有的内容架构进行了精心调整。作者Bruce ...

gitblog_06647的博客 581

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

分享:Java架构技术进阶资料

从代码到架构,最大的跨度其实是关于抽象维度的。那架构到底是什么?我们知道架构是一种结构设计,但它同时可能存在于不同的维度和层次上:高维度:是系统、子系统或服务之间的切分与...

瞬息之间 483

java 雅思_基于JAVA的雅思考试管理系统的设计与实现(SSH,MySQL)(含录像)

基于JAVA的雅思考试管理系统的设计与实现(SSH,MySQL)(含录像)(任务书,毕业论文12000字,程序代码,MySQL数据库)本文分析了基于JAVA的雅思考试管理系统的设计与实现技术,结合实际提出了本系统的总体结构设计和主要模块的功能实现。本系统分为二个子系统:管理员子系统,考生子系统。管理员子系统包括考生信息管理、题库信息管理、试卷管理、科目管理、成绩统计等模块。考生子系统主要包括参加考...

weixin_33120053的博客 291
上一篇: 【Java】阿里云短信发送功能实现
下一篇: 【调试工具】ngrok的安装与使用
黑豪Horace
博客等级 码龄10年 85粉丝 74原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值