【手摸手,带你搭建前后端分离商城系统】01 搭建基本代码框架、生成一个基本API

通过本教程的学习,将带你从零搭建一个商城系统。

当然,这个商城涵盖了很多流行的知识点技术核心

我可以学习到什么?

  • SpringBoot

    • 鉴权与认证、token、有关权限的相关的内容。
    • 优雅的利用OSS 上传文件
    • API 在线生成文档
  • Redis
    • Redis 基本使用
    • Redis 缓存存放用户token等
  • Docker
    • 容器技术的使用
    • SpringBoot 项目打包docker image
  • ElasticSearch
    • Elasticsearch 搜索引擎框架
  • RabbitMQ
    • 消息队列集成SpringBoot
  • Linux
    • 部署相关的Linux 命令的学习与使用

等等等。。。 不用犹豫了,和我一起来吧!

开始搭建

首先、当然以 maven 作为项目管理工具、以我们最熟悉的 SpringBoot 作为项目脚手架,帮助我们快速搭建起项目框架。

本小结需要了解的技术栈有:

  • maven 模块化的实现
  • 引入Mybatis-plus 简化CRUD
  • 设计基本的 权限三张表

创建一个maven 项目

我这里使用的是 IDEA ,希望朋友们也跟着我一起,当然其他优秀的集成开发工具也是很牛逼的,反正用着顺手就行!

创建一个新的项目、自定义项目名称,并且键入你自己的 group id 以及 artifactId

因为我们采用的是项目模块化的实现,父类就只是一个空壳,一般定义项目里面需要的所有 依赖信息 以及 版本信息 等。引入我们所有下面的子项目都会用到的 公共依赖包 这些。

定义我们将要使用的 Spring-boot 版本,我们这是使用 2.1.3

  1. <!-- springboot 2.3.0 -->
  2. <parent>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-parent</artifactId>
  5. <version>2.1.3.RELEASE</version>
  6. <relativePath/>
  7. </parent>

划分模块

这里依旧参考 mall 项目对于模块的规划,简单介绍一下。

  • mall-admin 后台管理模块
  • mall-common 公共包模块
  • mall-mbg mybatis-plus 生成 mapper、model 等
  • mall-security 鉴权、授权模块

暂时就先划分这么几个吧!等后面用到了我们再划分即可。

父类定义版本和基本模块

  1. <packaging>pom</packaging>

父类作为一个空壳,其最主要的目的是模块化的划分。它里面其实是不包含代码的,所以将它的打包方式改为 pom

就可以将父类下的 src 目录删掉了。

首先定义几个每个模块都会使用到的依赖。比如 aop切面 test 测试模块 等依赖信息。

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-actuator</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-aop</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.springframework.boot</groupId>
  12. <artifactId>spring-boot-starter-test</artifactId>
  13. <scope>test</scope>
  14. </dependency>
  15. <!-- 省略其他。。。 -->
  16. </dependencies>

使用 dependencyManagement

使用这个标签是为了我们依赖的 统一管理。防止两个模块引用不同版本的依赖,而导致打包冲突或者运行冲突等问题。

最大的好处也在于:父类定义好需要使用的依赖后、子类引用无需版本号。

  1. <!-- 变量定义,定义版本号 -->
  2. <properties>
  3. <java.version>1.8</java.version>
  4. <mybatis.plus.version>3.3.2</mybatis.plus.version>
  5. <hutool.version>5.4.0</hutool.version>
  6. <mysql.connector.version>8.0.20</mysql.connector.version>
  7. </properties>
  8. <!-- 父类定义的所有的包管理、子类统一使用、而不用写明版本号 -->
  9. <dependencyManagement>
  10. <dependencies>
  11. <!-- mybatis-plus -->
  12. <dependency>
  13. <groupId>com.baomidou</groupId>
  14. <artifactId>mybatis-plus-boot-starter</artifactId>
  15. <version>${mybatis.plus.version}</version>
  16. </dependency>
  17. <!--Hutool Java工具包-->
  18. <dependency>
  19. <groupId>cn.hutool</groupId>
  20. <artifactId>hutool-all</artifactId>
  21. <version>${hutool.version}</version>
  22. </dependency>
  23. <!--mysql 驱动-->
  24. <dependency>
  25. <groupId>mysql</groupId>
  26. <artifactId>mysql-connector-java</artifactId>
  27. <version>${mysql.connector.version}</version>
  28. </dependency>
  29. </dependencies>
  30. </dependencyManagement>

到这里,我们基本的父类已经构建完成了,我们可以开始构建 模块 了。

构建模块

直接在项目上右键 new model ,创建一个新的模块。

设计权限三张表

创建后台用户表、用来存储用户信息。

  1. CREATE TABLE `ums_admin` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '后台管理用户',
  3. `username` varchar(64) NOT NULL COMMENT '用户名',
  4. `password` varchar(64) NOT NULL COMMENT '密码',
  5. `icon` varchar(1024) NOT NULL COMMENT '头像',
  6. `lock` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0锁定1正常使用',
  7. `email` varchar(128) NOT NULL COMMENT '电子邮箱',
  8. `nick_name` varchar(32) NOT NULL COMMENT '昵称',
  9. `note` varchar(64) NOT NULL COMMENT '备注信息',
  10. `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  11. `login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
  12. `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '逻辑删除标记',
  13. PRIMARY KEY (`id`)
  14. ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;

创建后台角色信息表,存储角色信息。

  1. CREATE TABLE `ums_role` (
  2. `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色表',
  3. `name` varchar(64) NOT NULL COMMENT '角色名称',
  4. `description` varchar(128) NOT NULL COMMENT '角色描述',
  5. `admin_count` smallint(6) NOT NULL DEFAULT '0' COMMENT '后台用户数量',
  6. `lock` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0锁定 1正常使用',
  7. `sort` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序',
  8. `create_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  9. `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '逻辑删除状态0 1正常',
  10. PRIMARY KEY (`id`)
  11. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

创建后台菜单权限表,用于存储菜单关系。

  1. CREATE TABLE `ums_menu` (
  2. `id` int(11) NOT NULL COMMENT '菜单表',
  3. `parent_id` int(11) NOT NULL DEFAULT '0' COMMENT '父级ID',
  4. `title` varchar(11) NOT NULL COMMENT '菜单标题',
  5. `level` tinyint(1) NOT NULL DEFAULT '1' COMMENT '菜单级别',
  6. `sort` smallint(6) NOT NULL DEFAULT '0' COMMENT '菜单排序',
  7. `name` varchar(64) NOT NULL COMMENT '前端VUE 名称',
  8. `icon` varchar(32) NOT NULL COMMENT '图标',
  9. `hidden` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否隐藏 0隐藏 1展示',
  10. `create_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
  11. `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '逻辑删除',
  12. PRIMARY KEY (`id`)
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

我们的权限还是通过 用户-角色-权限 最经典的设计来进行了,这样的权限也适用大多数系统。

实现一个 REST API

因为是前后端分离项目,我们所有的请求需要经过 Controller , 这也是现在绝大多数系统所使用的架构、这一套系统依旧沿用Restful 风格的接口。并且按照 如下图的架构进行 API 的书写。

Restful 风格接口

  • POST /user/ 添加一个用户
  • GET /user/1 查询ID 为 1 的用户信息
  • GET /user/ 查询所有的用户信息
  • DELETE /user/1 删除ID 为 1 的用户信息
  • PUT /user/1 修改ID 为 1 的用户信息
  • POST /user/page 当然就是按照传入的条件进行分页了

Restful 架构设置

开始写代码吧

从上面的架构图,我们已经可以写出一个基本的CRUD Controller

包命名规则

一个合格的程序猿,写的代码不仅给人一种舒服的感觉。而且包名命名等也是一个可以学习的点。

  • mapper 当然就是mybatis mapper 放置的位置。
  • model 一款 ORM 框架对重要的就是:数据库对象与java对象的映射。
  • controller 接口api 的位置。
  • pojo 放置一些入参类、包装类等。
  • config 当然就是放置一些配置类。

Controller

我们以 ums_admin 后台用户表作为示例,其实这些都是可以生成的~ 具体看 开启偷懒模式

  • Controller 包含基本的 CRUD 接口。
  • Restful 风格接口信息,更加容易理解接口含义。
  • Swagger 生成基本的API 文档信息,以及测试接口。
  • 校验参数完整性!
  1. @Api(tags = "ApiUmsAdminController",description = "后台用户")
  2. @RestController
  3. @RequestMapping("/umsAdmin")
  4. @Validated
  5. public class ApiUmsAdminController {
  6. @Autowired
  7. private UmsAdminService umsAdminService;
  8. /**
  9. * <p>查询所有后台用户
  10. * <p>author: mrc
  11. *
  12. * @return xyz.chaobei.common.api.CommonResult
  13. * @since 2020-10-12 11:18:42
  14. **/
  15. @ApiOperation("查询所有后台用户")
  16. @GetMapping("/")
  17. public CommonResult getAll() {
  18. List<UmsAdminModel> allList = umsAdminService.findAll();
  19. return CommonResult.success(allList);
  20. }
  21. /**
  22. * <p>默认分页请求后台用户
  23. * <p>author: mrc
  24. *
  25. * @param pageAO 分页查询参数
  26. * @since 2020-10-12 11:18:42
  27. * @return xyz.chaobei.common.api.CommonResult
  28. **/
  29. @ApiOperation("默认分页请求后台用户")
  30. @PostMapping("/page")
  31. public CommonResult paging(@RequestBody @ApiParam("分页查询参数") UmsAdminPageAO pageAO) {
  32. Page<UmsAdminModel> allList = umsAdminService.findPage(pageAO);
  33. return CommonResult.success(allList);
  34. }
  35. /**
  36. * <p>保存一个后台用户
  37. * <p>author: mrc
  38. *
  39. * @param params 保存字段
  40. * @since 2020-10-12 11:18:42
  41. * @return xyz.chaobei.common.api.CommonResult
  42. **/
  43. @ApiOperation("保存一个后台用户")
  44. @PostMapping("/")
  45. public CommonResult save(@RequestBody @Valid @ApiParam("保存字段") UmsAdminSaveAO params) {
  46. boolean isSave = umsAdminService.save(params);
  47. return CommonResult.result(isSave);
  48. }
  49. /**
  50. * <p>修改一个后台用户
  51. * <p>author: mrc
  52. *
  53. * @param id 被修改的ID
  54. * @param params 被修改的字段
  55. * @since 2020-10-12 11:18:42
  56. * @return xyz.chaobei.common.api.CommonResult
  57. **/
  58. @ApiOperation("修改一个后台用户")
  59. @PutMapping("/{id}")
  60. public CommonResult update(@PathVariable("id") @ApiParam("被修改的ID") Integer id, @Valid @RequestBody @ApiParam("被修改的字段") UmsAdminSaveAO params) {
  61. boolean isUpdate = umsAdminService.updateById(params,id);
  62. return CommonResult.result(isUpdate);
  63. }
  64. /**
  65. * <p>删除一个后台用户
  66. * <p>author: mrc
  67. *
  68. * @param id 被删除的ID
  69. * @since 2020-10-12 11:18:42
  70. * @return xyz.chaobei.common.api.CommonResult
  71. **/
  72. @ApiOperation("删除一个后台用户")
  73. @DeleteMapping("/{id}")
  74. public CommonResult delete(@Valid @NotNull @PathVariable("id") @ApiParam("被删除的ID") Integer id) {
  75. boolean isDelete = umsAdminService.deleteById(id);
  76. return CommonResult.result(isDelete);
  77. }
  78. }

SaveAO

SaveAO 一般就是前端 填写表单入参的信息 ,当然我们能直接使用 DO 进行携带参数。那样不安全。AO 将参数从 Controller

携带后,通过 javax.validation.Valid 对字段进行校验后、方可进行下一步。

  • SaveAO 将参数从 Controller 传递到 Service 处理逻辑
  • Controller 入参的时候,检验 SaveAO 所包含的参数。
    • @NotBlank
    • @NotNull
    • 略...
  • @ApiModelProperty 说明参数注释信息
  1. @Getter
  2. @Setter
  3. public class UmsAdminSaveAO {
  4. /**
  5. * 用户名
  6. */
  7. @NotBlank
  8. @ApiModelProperty("用户名")
  9. private String username;
  10. /**
  11. * 密码
  12. */
  13. @NotBlank
  14. @ApiModelProperty("密码")
  15. private String password;
  16. /**
  17. * 头像
  18. */
  19. @ApiModelProperty("头像")
  20. private String icon;
  21. /**
  22. * 0锁定1正常使用
  23. */
  24. @NotNull
  25. @ApiModelProperty("0锁定1正常使用")
  26. private Integer lock;
  27. /**
  28. * 电子邮箱
  29. */
  30. @NotBlank
  31. @ApiModelProperty("电子邮箱")
  32. private String email;
  33. /**
  34. * 昵称
  35. */
  36. @ApiModelProperty("昵称")
  37. private String nickName;
  38. /**
  39. * 备注信息
  40. */
  41. @ApiModelProperty("备注信息")
  42. private String note;
  43. }

当然。这里的所有参数都是可以自定义的。你想要哪些,就生成哪些~

Service

  • Service 负责将 Controller 传递的 AO 复制到 DO(Database Object)
  • 调用 Mapper 的方法进行持久化。
  • Service 返回一个 成功或者失败的标志。
  • 逻辑异常,抛出一个异常信息【例如这个ID 找不到用户。。。】,全局捕获后,返回给前端进行提示。
  1. @Service
  2. public class UmsAdminServiceimpl implements UmsAdminService {
  3. @Autowired
  4. private UmsAdminMapper umsAdminMapper;
  5. @Override
  6. public List<UmsAdminModel> findAll() {
  7. return umsAdminMapper.selectList(null);
  8. }
  9. @Override
  10. public Page<UmsAdminModel> findPage(UmsAdminPageAO pageAO) {
  11. Page page = new Page(pageAO.getCurrent(),pageAO.getSize());
  12. QueryWrapper wrapper = new QueryWrapper();
  13. wrapper.eq("`username`", pageAO.getUsername());
  14. wrapper.eq("`lock`", pageAO.getLock());
  15. wrapper.eq("`note`", pageAO.getNote());
  16. umsAdminMapper.selectPage(page, wrapper);
  17. return page;
  18. }
  19. @Override
  20. public boolean save(UmsAdminSaveAO params) {
  21. UmsAdminModel model = new UmsAdminModel();
  22. BeanUtils.copyProperties(params,model);
  23. /**
  24. * 你的逻辑写在这里
  25. */
  26. int num = umsAdminMapper.insert(model);
  27. return SqlHelper.retBool(num);
  28. }
  29. @Override
  30. public boolean updateById(UmsAdminSaveAO params, Integer id) {
  31. UmsAdminModel model = new UmsAdminModel();
  32. BeanUtils.copyProperties(params,model);
  33. /**
  34. * 你的逻辑写在这里
  35. */
  36. model.setId(id);
  37. int num = umsAdminMapper.updateById(model);
  38. return SqlHelper.retBool(num);
  39. }
  40. @Override
  41. public boolean deleteById(Integer id) {
  42. /**
  43. * 你的逻辑写在这里
  44. */
  45. int num = umsAdminMapper.deleteById(id);
  46. return SqlHelper.retBool(num);
  47. }
  48. }

Mapper

  • 继承 Mybatis-Plus BaseMapper 获得基础CRUD 能力。
  1. public interface UmsAdminMapper extends BaseMapper<UmsAdminModel> {
  2. // 继承mybatis-plus 获得基础crud
  3. }

Mybatis-Plus Config

主要是配置 mybatis 扫描的mapper 所在的位置。以及开启事务的支持。

  1. @Configuration
  2. @EnableTransactionManagement
  3. @MapperScan({"xyz.chaobei.mall.dao","xyz.chaobei.mall.mapper"})
  4. public class MyBatisPlusConfig {
  5. }

开启偷懒模式

能不能有一种东西,给我生成这种重复的东西,而我只关注逻辑呢?

当然有了~

上面示例的代码都是用工具生成的~ 总不能一个一个敲出来吧~

学会偷懒其实也是一种好处。人类的发展不就是朝着偷懒的方向发展嘛

添加配置文件

这已经是最后的几个步骤了。添加配置文件,主要是配置 mybatis-plus mapper 所在的位置。

以及配置我们的逻辑删除、自动填充这两个很好用的功能。

配置逻辑删除

https://baomidou.com/guide/logic-delete.html

逻辑删除有什么好处呢?我觉得主要还是数据的完整性。上线以后、就算这条数据要被删除,也只能是通过状态隐藏起来,

并非真实删除。

还有一个注意的点就是:既然配置了这个status ,那么所有的表都应该有这个字段。

  1. #mybatis-plus 基础配置
  2. mybatis-plus:
  3. mapper-locations:
  4. - classpath:/dao/**/*.xml
  5. - classpath*:/mapper/**/*.xml
  6. global-config:
  7. db-config:
  8. logic-delete-field: status
  9. logic-not-delete-value: 1
  10. logic-delete-value: 0

配置自动填充功能

https://baomidou.com/guide/auto-fill-metainfo.html

一般情况下:我们每一条数据都会包含一个 时间字段(创建、修改) 这样的字段每次要在:插入、修改的时候进行添加。

其实很难受的。所以还是偷个懒~ 让代码帮我们完成。我这里只有一个 createTime 需要填充,你可以参考官网再详细一些。

所以:你的每个表都应该包含这个填充字段

  1. @Slf4j
  2. @Component
  3. public class MyMetaObjectHandler implements MetaObjectHandler {
  4. @Override
  5. public void insertFill(MetaObject metaObject) {
  6. log.info("start insert fill ....");
  7. this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
  8. }
  9. @Override
  10. public void updateFill(MetaObject metaObject) {}
  11. }

别忘了标识字段。

  1. /**
  2. * 创建时间
  3. */
  4. @TableField(value = "`create_time`",fill = FieldFill.INSERT)
  5. private Date createTime;

测试接口代码

细心的朋友已经发现了。我们系统已经集成了 swagger

swagger 对于接口文档的生成和测试,简直完美。代码写好了,文档自然而然的被生成。并且可以在页面上测试 接口通信

简直完美啊!

整合Swagger

考虑到 swagger 通用的配置类可能被多个模块所使用,所以我们首先建立一个 abstract class 让子类重写它的抽象方法。这样就实现了一个通用的 swagger config

  1. public abstract class BaseSwaggerConfig {
  2. @Bean
  3. public Docket createDocket() {
  4. // 获取自定义配置
  5. SwaggerProperties properties = this.customSwagger();
  6. Docket docket = new Docket(DocumentationType.SWAGGER_2)
  7. // api 生成基本信息
  8. .apiInfo(this.buildApiInfo(properties))
  9. // 开启一个端点
  10. .select()
  11. // 生成API 的包路径
  12. .apis(RequestHandlerSelectors.basePackage(properties.getApiBasePackage()))
  13. // 路径选择
  14. .paths(PathSelectors.any())
  15. .build();
  16. return docket;
  17. }
  18. /**
  19. * 构建API 信息方法,通过自定义的SwaggerProperties 转化为 ApiInfo
  20. * 通过ApiInfoBuilder 构建一个api信息。
  21. *
  22. * @param properties 自定义信息
  23. * @return
  24. */
  25. private ApiInfo buildApiInfo(SwaggerProperties properties) {
  26. return new ApiInfoBuilder()
  27. // 标题
  28. .title(properties.getTitle())
  29. // 描述
  30. .description(properties.getDescription())
  31. // 联系人信息
  32. .contact(new Contact(properties.getContactName(), properties.getContactUrl(), properties.getContactEmail()))
  33. // 版本信息
  34. .version(properties.getVersion())
  35. .build();
  36. }
  37. /**
  38. * 自定义实现配置信息
  39. *
  40. * @return
  41. */
  42. public abstract SwaggerProperties customSwagger();
  43. }

Admin Swagger Config

让我们的子类继承通用的父类,并且重写customSwagger 自定义一个配置类。填写一些 api 的基本信息。即可。

@EnableSwagger2 开启Swagger 支持

SwaggerProperties 是自己定义的一个配置信息类,用户包装如下的信息。详细见代码

  1. @Configuration
  2. @EnableSwagger2
  3. public class AdminSwaggerConfig extends BaseSwaggerConfig {
  4. @Override
  5. public SwaggerProperties customSwagger() {
  6. return SwaggerProperties.builder()
  7. .title("mall-pro")
  8. .description("mall-pro 接口描述信息")
  9. .apiBasePackage("xyz.chaobei.mall.controller")
  10. .contactName("mrc")
  11. .enableSecurity(false)
  12. .version("1.0")
  13. .build();
  14. }
  15. }

访问Swagger

启动我们的main() 方法。让这个项目跑起来!

访问:http://localhost:8080/swagger-ui.html

基本的增删改查,已经展现出来了。可以直接在这里测试我们接口的连通性,真的特别方便。

测试这个一个添加的接口。

操作成功的返回信息。状态码、以及提示语。

小结

学到这里。你已经整合了一个基本的接口、并且测试通了接口的连通性。而且文档也不用自己手写了,全部自动生成。

总结一下:我们学习和使用到了:

  • maven 子项目的搭建
  • mybatis-plus 的整合
  • mybatis-plus 自动填充功能的使用
  • 逻辑删除字段的使用方式。
  • 以及整合swagger 自动生成测试接口和 接口说明文档。

码云开源

https://gitee.com/mrc1999/mall-pro

持续更新中,欢迎关注

【手摸手,带你搭建前后端分离商城系统】01 搭建基本代码框架、生成一个基本API的更多相关文章

  1. 【手摸手,带你搭建前后端分离商城系统】02 VUE-CLI 脚手架生成基本项目,axios配置请求、解决跨域问题

    [手摸手,带你搭建前后端分离商城系统]02 VUE-CLI 脚手架生成基本项目,axios配置请求.解决跨域问题. 回顾一下上一节我们学习到的内容.已经将一个 usm_admin 后台用户 表的基本增 ...

  2. 【手摸手,带你搭建前后端分离商城系统】03 整合Spring Security token 实现方案,完成主业务登录

    [手摸手,带你搭建前后端分离商城系统]03 整合Spring Security token 实现方案,完成主业务登录 上节里面,我们已经将基本的前端 VUE + Element UI 整合到了一起.并 ...

  3. List多个字段标识过滤 IIS发布.net core mvc web站点 ASP.NET Core 实战:构建带有版本控制的 API 接口 ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目 Using AutoFac

    List多个字段标识过滤 class Program{  public static void Main(string[] args) { List<T> list = new List& ...

  4. 利用grunt-contrib-connect和grunt-connect-proxy搭建前后端分离的开发环境

    前后端分离这个词一点都不新鲜,完全的前后端分离在岗位协作方面,前端不写任何后台,后台不写任何页面,双方通过接口传递数据完成软件的各个功能实现.此种情况下,前后端的项目都独立开发和独立部署,在开发期间有 ...

  5. ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目

    一.前言 这几年前端的发展速度就像坐上了火箭,各种的框架一个接一个的出现,需要学习的东西越来越多,分工也越来越细,作为一个 .NET Web 程序猿,多了解了解行业的发展,让自己扩展出新的技能树,对自 ...

  6. 【转】python+django+vue搭建前后端分离项目

    https://www.cnblogs.com/zhixi/p/9996832.html 以前一直是做基于PHP或JAVA的前后端分离开发,最近跟着python风搭建了一个基于django的前后端分享 ...

  7. python drf+xadmin+react+dva+react-native+sentry+nginx 搭建前后端分离的博客完整平台

    前言: 经过差不多半年的开发,搭建从前端到服务器,实现了前后端分离的一个集PC端.移动端的多端应用,实属不易,今天得空,好好写篇文章,记录这些天的成果.同时也做个分享. 演示网站地址: http:// ...

  8. python+django+vue搭建前后端分离项目

    以前一直是做基于PHP或JAVA的前后端分离开发,最近跟着python风搭建了一个基于django的前后端分享项目 准备工作:IDE,[JetBrains PyCharm2018][webpack 3 ...

  9. SpringBoot+Jpa+SpringSecurity+Redis+Vue的前后端分离开源系统

    项目简介: eladmin基于 Spring Boot 2.1.0 . Jpa. Spring Security.redis.Vue的前后端分离的后台管理系统,项目采用分模块开发方式, 权限控制采用 ...

随机推荐

  1. js map对象处理if

    onButtonClick只有一个参数时候,map和object对象都可以 // onButtonClick1(3) onButtonClick只有一个参数时候,map和object对象都可以 con ...

  2. Redux异步解决方案之Redux-Thunk原理及源码解析

    前段时间,我们写了一篇Redux源码分析的文章,也分析了跟React连接的库React-Redux的源码实现.但是在Redux的生态中还有一个很重要的部分没有涉及到,那就是Redux的异步解决方案.本 ...

  3. 读取文本文件中的中文打印到Eclipse控制台为何显示问号

    原因:未将文本文件存为utf-8编码格式而是ascii编码格式.

  4. Java实现随机生成由字母、数字组合的N位随机数

    通过Math.random函数生成所需的字符所有序列,通过判断当前字符是否属于大小写.数字,符合者加入数组内,直到数组存储N位为止,最后把当前数组转为字符串返回调用处. /** * 随机生成由数字.字 ...

  5. python修改excel内容

    前提:安装pip install xlutils和xlrd 思路:xlrd用来读数据,xlutils用来修改数据:先打开excel——读到原来的sheet页——生成可以修改的excel和sheet页— ...

  6. iOS面试关于http知识点basic-01-http

    URL URL 的全称是 Uniform Resource Locator(统一资源定位符) 通过 1 个 URL,能找到互联网上唯一的 1 个资源 URL就是资源的地址.位置,互联网上的每个资源都有 ...

  7. 【深入理解Linux内核架构】第3章:内存管理

    3.1 概述 内存管理涵盖了许多领域: 内存中物理内存页的管理: 分配大块内存的伙伴系统: 分配小块内存的slab.slub.slob分配器: 分配非连续内存块的vmalloc机制: 进程的地址空间. ...

  8. SpringCloud实战 | 第一篇:Windows搭建Nacos服务

    前言 为什么放弃eureka选择nacos?本地开发环境需要搭建nacos-server,想着是很简单的事但是被一些文章(少了关键必要的步骤)给带偏了,所以亲测成功后写了这篇文章. 搭建nacos-s ...

  9. 鸿蒙真的是套壳吗?HarmonyOS应用开发初体验,Java原生和JavaScript的mvvm开发

    初探寻鸿蒙os的应用开发 本期视频已发布到bilibili 注意是应用开发,没错码农(应用开发)一般关注这个就行了 IDE 点击应用开发以后,点击链接下载IDE,DevEco Studio是基于IDE ...

  10. Windows Server系统部署MySQL数据库

    由于工作需要在阿里云服务器中使用MySQL,所以安装一下MySQL数据库,中间也踩了一些坑,现在将整个过程给大家记录下来,便于后续查找. 阿里云服务器是WinServer2012系统,之前在Windo ...