写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。扫码加微信好友进【程序员面试学习交流群】,免费领取。也欢迎各位一起在群里探讨技术。

前言

本篇随笔用于记录我在学习 Java 和构建 Spring Boot 项目过程中的一些思考,包含架构、组件和部署方式等。下文仅为概要,待闲时逐一整理为详细文档。

1. 组件

开源社区如火如荼,若在当下我们还要去重复 “造轮子” 那真是罪过罪过(当然也并不意味着所有的一切都可拿来即用,了解他,使用他,若有能力,去完善它)。因此,当我们拿到需求的时候首先应当进行拆解,哪些模块在社区中已有比较成熟的解决方案,然后大致罗列一个粗略的所需组件列表(后续根据架构的设计和兼容情况再进行调整)。

1.1 ORM

用于解耦实体对象的装载过程,他让我们的编程过程更关注业务逻辑本身,其重要性毋庸多言。在 Spring Boot 中比较主流的 ORM 框架有 Spring-Data-JPA 和 MyBatis。

JPA 规范的好处是我们几乎完全专注于业务逻辑本身,JpaRepository 中的接口能够满足大部分简单的操作逻辑了,若要扩展,我们也可以再抽离出一个父类,添加自定义的通用 CRUD 操作,如此一来仓储层的代码变得异常优雅和简洁。以下是一个简单的实现案例:

application.yml:

spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://mysql:3306/youclk?characterEncoding=utf8&useSSL=falseusername: rootpassword: youclkjpa:hibernate:ddl-auto: createshow-sql: true

BookRespository.java:


public interface BookRespository extends JpaRepository<Book,Integer> {}

Book.java:


@Datapublic class Book  {private Long id;private String name;private Date createTime;}

BookRespositoryTest.java:


@RunWith(SpringRunner.class)@SpringBootTestpublic class BookRespositoryTest {@Autowiredprivate BookRespository repository;@Testpublic void saveTest() {Assert.assertEquals(repository.findAll().size(),0);}}

映射得到的 sql 如下:

Hibernate: select book0_.id as id1_0_, book0_.name as name2_0_, book0_.number as number3_0_ from book book0_

如果是几年前的话我肯定会首选 JPA, 但是期间近两年的 EFCore 开发经历让我的选择变得谨慎。C# 是 Lambda 和 Linq 的先驱者,因此 .NET + EF 实践 Code First 着实优雅。然而在迁移 EFCore 的过程中遇到的问题真是不少,比如说 EFCore 1.x 的时候处理 GroupBy 是全表扫描然后拿到内存中过滤。对于旧项目的迁移我们一般没有精力去验证 ORM 映射生成的每条 SQL 语句,而且本地环境因数据基数少,测试阶段很难直观地体现出来,但部署后就悲剧了,服务和数据库一起都要死要死的。

由此引发的思考是当进行里程碑版本的升级和迁移的时候,新版本 ORM 框架所生成的 SQL 还能否完全正确体现之前代码中的逻辑。

在 .NET Core 中除了 EFCore 还有一个非常优秀的 ORM 框架是 Dapper,这个和 MyBatis 非常像,相当于半自动档吧,开发者能更好地掌控 SQL,但牺牲了一定的简洁。介于曾经的入坑经历,至少在查询方面我选择 MyBatis,实例如下:

BookRespository.java:


public interface BookRepository {List<Book> findAll();@Select("SELECT name FROM book WHERE id = #{id}")@Results({@Result(property = "name", column = "name")})String findBookName(Long id);}

BookRepository.xml:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace="com.youclk.demo.repositories.BookRepository" ><resultMap id="BaseResultMap" type="com.youclk.demo.domain.Book" ><id column="id" property="id" jdbcType="BIGINT" /><result column="name" property="name" jdbcType="VARCHAR" /><result column="createTime" property="createTime" jdbcType="DATE" /></resultMap><sql id="Base_Column_List" >id, name, createTime</sql><select id="findAll" resultMap="BaseResultMap"  >SELECT<include refid="Base_Column_List" />FROM book</select></mapper>

Application.java 中加一行 MapperScan 注解:


@SpringBootApplication()@MapperScan("com.youclk.demo.repositories")public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}}

以上 BookRepository.java 中分别使用了注解和 xml,虽然在 Spring 中注解是王道,但我还是喜欢 xml 这种方式。一方面接口上写这么一堆 SQL 和返回类型看起来很难受,头重脚轻,而且没有突出重点,另一方面在于 IDEA 中对 xml 的智能提示相当友好,效率上也不见得是写注解快多少。不过采用注解方式少了些配置文件,项目结构更优。

1.2 日志

Java 中主流的日志框架有 JUL(java.util.logging)、Log4j、Log4j2 和 Logback 这四款,JUL 因过于简陋优先淘汰,剩下的三款都是同一个作者开发,Log4j 太旧速度慢,Log4j2 太新问题多,因此 Logback 就是最优解,对应的接口门面我选择 SLF4j。需要导入的包有: slf4j-api、ogback-classic 和 logback-core,以下是我的案例:

logback-spring.xml:

<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{35} - %msg%n</pattern></encoder></appender><appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>WARN</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/com.youclk.demo/warm/%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>90</maxHistory></rollingPolicy><encoder><pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{35} - %msg%n</pattern></encoder></appender><appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMismatch>DENY</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/com.youclk.demo/error/%d{yyyy-MM-dd}.log</fileNamePattern><maxHistory>90</maxHistory></rollingPolicy><encoder><pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{35} - %msg%n</pattern></encoder></appender><root level="warn"><appender-ref ref="STDOUT"/><appender-ref ref="FILE_WARN"/><appender-ref ref="FILE_ERROR"/></root></configuration>

LoggerTest.java:


@RunWith(SpringRunner.class)@SpringBootTest@Slf4jpublic class LoggerTest {@Testpublic void testOutput() {log.error("error");log.warn("warn");log.info("info");}}

以上将日志的输出整理归类,若要分布式部署,则只要每个 Container 都挂载 log 目录便可做日志的集中管理。Logback 更详细信息可查阅 “官方文档”

1.3 缓存

Memcached 和 Redis 都老生常谈了,Redis 支持更多的数据结构和操作,并且二者性能差距不大,因此选他无疑,实现上也极其简单,如下:


@RunWith(SpringRunner.class)@SpringBootTestpublic class RedisTest {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void testSetCache() {ValueOperations<String, Book> operations = redisTemplate.opsForValue();operations.set("my-book",new Book(),5, TimeUnit.SECONDS);System.out.println(operations.get("my-book"));}}

另外还有一种注解的用法功能上要强大不少:

@Service@CacheConfig(cacheNames="book")public class BookService {@Autowiredprivate BookRepository bookRepository;@Cacheable()public List<Book> findAll() {return bookRepository.findAll();}}

2. 架构

程序员界一直存在着一条所谓的 “语言鄙视链”,曾经为了 “打嘴炮” 而粗略地对比过 Java 和 C#,由于未深入探究,因此我一直以来的观念都是 C# 的语法糖比 Java 优雅太多。直到我切身感受了使用 Java 构建项目,或许就原生的二者来说确实是 C# 更优雅,但加上社区的力量可就不好说了。比如习惯了 C# 自动属性的我最不喜欢的就是 Java 那么一堆冗长的 get 和 set, 直到我认识了 lombok,简直汗颜啊,源码注解原来还能这么灵活地使用,由此展开只要你足够有耐心,想要什么语法糖自定义注解去实现就好。还有其他的零零总总, Java 中注解和 AOP 范式的成熟应用拓展了更多的 “编程姿势” 呵(C# 中通过反射也能做到,奈何封闭的生态导致为其造轮子的不多,现今微软已拥抱开源,给个祝福吧,互相竞争才更有意思嘛)。

回归本节主题,在 .NET 中 DDD 架构的应用可谓是相当普及,你要是不晓得领域、充血模型、事件驱动等概念都不好意思说熟悉 .NET。

这里简要概括一下,顺便谈谈我的想法,传统 DDD 架构主要分四层,分别为:User Interface(用户界面层)、Application(应用层)、Domain(领域层) 和 Infrastructure(基础设施层)。界面层就不说了,应用层主要起协调作用,比如一个请求从用户界面层过来,应用层应当分析其需要哪几个领域模块参与,并协调他们工作,但其本身不应包含任何的业务规则,基础设施层在实际应用中最重要的功能就是提供数据持久化机制。领域层则为整个项目的核心,其应囊括几乎全部的业务规则,我们应当在该层根据项目需求设计领域模型,抽离出领域服务,每个领域模块应当专注于处理其自身的核心业务逻辑,非核心的业务可封装为领域事件交由异步队列处理。其次,领域层作为核心,他不应该对其他层有所依赖,因此一般他会包含基础设施层的实现接口。

之前对于领域模块中的通用逻辑或非核心业务,我通常的处理方案是封装为领域事件分发,现在想想如此做法不合理之处,领域事件有些被滥用了。介于 AOP 在 Spring Boot 的广泛应用,领域模型中除了领域实体、值对象、领域服务、领域事件和工作单元之外再加一个领域切面也是极好的。另外,对于领域实体最后的持久化操作如果使用 MyBatis 此类的 ORM 框架那整个编程过程就变得相当繁琐,在领域中比较容易做到的是对实体状态的跟踪,因此持久化选择 JPA 规范的 ORM 框架才更为合理,但在查询上我更喜欢 MyBatis,因此若要做读写分离的话, JPA 和 MyBatis 分别对应主备数据库操作正好。

3. 部署

自从习惯了 Docker 之后,我已经不适应服务的单独部署了,具体操作详见我的这篇博文:“Compose & Swarm”。

结语

近期正在寻觅 “全栈” 或 “Java 开发” 的工作岗位,若有意向,欢迎留言,微信: youclk。


我的公众号《有刻》,我们共同成长!

转载:https://www.cnblogs.com/youclk/p/8566805.html

推荐内容:
十大经典排序算法最强总结(含JAVA代码实现)
为什么说 Java 程序员到了必须掌握 Spring Boot 的时候?
Java 面试知识点解析(二)——高并发编程篇
java实现 redis的发布订阅(简单易懂)
Java--面试通关要点
Java高级工程师面试题总结及参考答案
Java面试总结
java 面试收集
知名互联网公司校招 Java 开发岗面试知识点解析
知名互联网公司校招 Java 开发岗面试知识点解析

Java 小记 — Spring Boot 的实践与思考,互联网 面试官 如何面试相关推荐

  1. Spring Boot 最佳实践

    转载自  Spring Boot 最佳实践 Spring Boot是用于开发微服务的最流行的Java框架.在本文中,我将与您分享自2016年以来我在专业开发中使用Spring Boot所采用的最佳实践 ...

  2. Spring Boot 2 实践记录之 MyBatis 集成的启动时警告信息问题

    按笔者 Spring Boot 2 实践记录之 MySQL + MyBatis 配置 中的方式,如果想正确运行,需要在 Mapper 类上添加 @Mapper 注解. 但是加入此注解之后,启动时会出现 ...

  3. 精选10个用于Java开发Spring Boot的Eclipse插件

    前言 作为从事Java多年的程序员,在此分享用于 Java 和 Spring Boot 开发的 10 大 Eclipse插件: 1. EGit - Eclipse 的 Git 集成 这可能是当今 Ja ...

  4. java中用spring boot连接oracle数据库

    java中用spring boot连接oracle数据库 代码下载链接 百度云:https://pan.baidu.com/s/1dU_z2pUS2NSfowI4_mJ4Ow 提取码:mmlm CSD ...

  5. Elasticsearch+Spring Boot集成实践

    ELK-技术栈 Elasticsearch 简介 ​ Elasticsearch 是一个分布式.RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例. 作为 Elastic Stac ...

  6. [JAVA EE]Spring Boot 控制层:参数传递方法

    项目需要参照本人java ee系列前文建立,请读者自行前往本人主页查看. 当然,您自己创建一个项目也是可以的. bean包下的Student.java package com.example.demo ...

  7. 使用Gradle禁止Java和Spring Boot Web应用程序中的FindBugs警告

    如何在+ Spring Boot和+ Java应用程序中使用注释抑制FindBugs警告 如果您的构建由于FindBugs问题而中断,并且是假阳性,或者由于其他考虑而无法解决问题,则可以添加注释来忽略 ...

  8. Spring Boot 最佳实践(五)Spring Data JPA 操作 MySQL 8

    ## 一.Spring Data JPA 介绍 JPA(Java Persistence API)Java持久化API,是 Java 持久化的标准规范,Hibernate是持久化规范的技术实现,而Sp ...

  9. Spring Boot 最佳实践(四)模板引擎Thymeleaf集成

    ## 一.Thymeleaf介绍 Thymeleaf是一种Java XML / XHTML / HTML5模板引擎,可以在Web和非Web环境中使用.它更适合在基于MVC的Web应用程序的视图层提供X ...

最新文章

  1. 技术01期:大规模图计算【基础篇】
  2. LeetCode Non-overlapping Intervals(dp,greedy)
  3. Linux 文本界面转到图形界面
  4. python PyQt5 QtCore.QPointF类、QPointF类与QPoint类区别
  5. Winform中实现List<string>赋值给dataGridView与实现多选、全选和获取选择的内容
  6. 用启明云端支持ESP32的GUI做了一个测温HMI交互界面
  7. 团部培训笔记-设计模式-《2013-11-27 代理模式》
  8. 【学习笔记】计算机导论之计算机软件
  9. python安装完毕后,提示找不到ssl模块的解决步骤
  10. 计算机网络期末复习资料
  11. Spark Shuffle 中 JVM 内存使用及配置内幕详情
  12. swagger默认访问地址
  13. java B2B2C Springboot电子商城系统-eureka详解
  14. 项目过程管理(十七)结项
  15. C语言实现的简易FTP客户端
  16. 捷联惯导系统ETest半实物仿真系统试验方法
  17. postman下载地址
  18. 利用二维向量的叉乘判断凹凸多边形
  19. 数字 显示为LED 字体
  20. wpsppt放映时间_wps演示怎么调整放映速度?

热门文章

  1. BAPI_SALESDOCU_CREATEFROMDATA1--VA01
  2. 余世维《职业经理人常犯的错误》[文字版]
  3. html5下input的placeholder标签兼容ie9
  4. DMA流程简介--CPU/内存/网卡之间的交互
  5. ControllerChannelManager分析
  6. (44)FPGA时序逻辑与组合逻辑(组合逻辑)
  7. (17)FPGA速度和面积互换原则
  8. (12)System Verilog 数组查找常数
  9. FPGA系统设计考虑因素
  10. oracle安装检测空间china,oracle安装 - Ginn的个人空间 - OSCHINA - 中文开源技术交流社区...