欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于SpringBoot的JEE应用构建

程序员文章站 2022-04-12 19:13:23
...

        Spring生态圈的演进从未停歇。自从2013年SpringBoot出现以来,基于Spring的应用构建方式已经逐渐发生变化。

        Spring无疑是JEE发展历程中最成功的开发平台之一,但这并不能阻止大家的吐槽。在早期版本中,开发人员需要配置大量的XML---这在引入注解方式后有所改善,另外还要处理复杂的(版本)依赖关系,一点差池都可能导致系统无法正常运行。SpringBoot解决了上述问题,同时带来了全新的开发体验,为RAD领域提供了一种优秀的解决方案。

        本文将尝试整合一些主流的框架,基于SpringBoot搭建出适合某类场景的应用架构,提供特定的技术选型参考。

 

1、入门级应用

        可认为包含前端、中端和后端。前端部分使用官方推荐的thymeleaf模板进行渲染,中端部分就是基于SpringBoot的微服务应用。至于后端,可以是其它服务或者是数据库系统,此处以mysql为例。以下将适当详细地描述一个轻服务通常包含哪些东西。

        以maven作为构建工具,创建一个项目。pom.xml配置如下:

        

<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>

	<groupId>cn.j1ee</groupId>
	<artifactId>testing</artifactId>
	<version>1.0</version>
	<packaging>jar</packaging>
	<name>testing</name>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.4.3.RELEASE</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>com.zaxxer</groupId>
			<artifactId>HikariCP</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

 

 

持久层组件选用jpa而不是Mybatis,数据库连接池组件采用HikariCP。应用需要一些必要的配置,如/src/main/resources/application.properties所示的一些信息:

 

        

#server
server.port=8081
server.session-timeout=20
server.context-path=/testing
server.tomcat.uri-encoding=UTF-8


#datasource
spring.datasource.url=jdbc:mysql://192.168.124.7:3306/test?useUnicode=true&characterEncoding=utf8
spring.datasource.username=mysqlx
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-idle=100
spring.datasource.max-wait=10000
spring.datasource.min-idle=10
spring.datasource.initial-size=10
spring.datasource.type=com.zaxxer.hikari.HikariDataSource

#jpa
spring.jpa.database = MYSQL
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto=none  
spring.jpa.generate-ddl=true  
spring.jpa.properties.hibernate.show_sql=true 

 

 

 

创建启动类,该类的目录是有要求的,需要放在根包下。该类所在的main方法是应用的入口,将系统引导工作交给了SpringBoot。

        

@SpringBootApplication
public class App {

	public static void main(String[] args) {
		SpringApplication.run(App.class, args);
	}
}

 

 

以一次请求为例,首先有一个实体bean:

@Entity
@Table(name = "users")
public class User {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private long id;
	@NotNull
	private String name;
	@NotNull
	private int age;

//…
}

 

 

有一个Data Access Object:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
	public User findByName(String name);
}

 

 

有一个前端展示需要的模板/src/main/resources/templates/user.html:

<h3>user info:</h3>
<div>
	name:	<span th:text="${user.name}">not find the user</span><br/>
	age:	<span th:text="${user.age}">no age</span><br/>
</div>

 

 

再有一个UserService和UserServiceImpl,作为逻辑层,此处略过;

最后还需要一个Controller:

@Controller
public class UserController {

	@Autowired
	UserService userService;

	@RequestMapping("/user/{name}")
	public String getByName(@PathVariable String name, Model model) {
		User user = userService.findByName(name);
		model.addAttribute("user", user);
		return "user";
	}
}

 

 

这样一个MVC模块的雏形就有了。通过mvn spring-boot:run启动应用,在浏览器中输入http://localhost:8081/testing/user/du访问,出现如下结果:

 

user info:
name: du
age: 18

 

 

        Boot提供了一些特性,比如嵌入式应用服务容器(默认tomcat)。Maven可将应用打包成一个fat jar,在服务器上直接用java运行即可启动程序。

        Boot基于约定优于配置的原则,做了很多自动化配置的工作。如前所述,这些(默认)配置是可以根据需要修改的,也可以通过启动命令参数传入,后一种方式在云端部署时比较有用。

 

        入门级SpringBoot应用的技术架构如下:

 
基于SpringBoot的JEE应用构建
            
    
    博客分类: ArchitectureMongoDBSoftware EngineeringSystem Analysis Springboot集群负载ha并发 
 

 

 

2、HA/负载均衡

        一些重要的系统需要支持ha,有一定并发规模的情况下还需要做负载均衡,这看起来和SpringBoot没有太大的关系。实际上并非如此,Boot支持开箱即用的特性,使得部署前所未有的方便了。由于Boot对配置支持的优先级划分能力,允许在应用之外传入参数的方式运行,进一步提高了其实用性。

        对于规模较大的系统,如何提高吞吐量,解决IO瓶颈一直是关注的焦点。传统的方法是分库(垂直)分表(水平),这在很多时候需要做不少额外的工作,并且会带来各种问题。为解决该问题,实现数据库集群负载和数据安全,Oracle提供了RAC方案,后来出现了支持多种数据库的工具 MyCat。

        MongoDB在很多时候是一个更好的选择,它支持三种集群方式,可根据实际情况使用。Boot可以很方便的集成包括MongoDB在内的大部分数据库系统,只需要引入必要的starter组件(还需要配置一些数据连接相关的参数,略)。:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

 

 

        本部分不涉及DNS和CDN,它们也是负载均衡的常用技术。

        以LVS软交换为例,SpringBoot集群部署示图如下:

 
基于SpringBoot的JEE应用构建
            
    
    博客分类: ArchitectureMongoDBSoftware EngineeringSystem Analysis Springboot集群负载ha并发 
 

 

 

3、内容性应用

        另外一些情况则需要一些变化。对于内容性比较强的系统,比如微博、论坛之类的,需要对大量的内容进行缓存处理,以减少不必要的IO操作,提高响应速度。这些内容通常实时性要求不高,只需保持最终一致性即可。目前流行的方案是redis,实际上mongodb也是可以满足要求的。

        引入依赖:

<dependency>  
<groupId>org.springframework.boot</groupId>  
<artifactId>spring-boot-starter-redis</artifactId>  
</dependency>  

 

 

        可能的方式:

 
基于SpringBoot的JEE应用构建
            
    
    博客分类: ArchitectureMongoDBSoftware EngineeringSystem Analysis Springboot集群负载ha并发 
 

 

        对于海量数据,需要进行数据分析的话,考虑引入hadoop/spark替换当前的持久化存储。

 

4、高并发系统

        某些极端情况需要特殊处理。本人曾尝试过一些量化交易的研究,就以股票行情为例简单地介绍一下。假如需要做一个Http服务,为用户提供股票行情信息,并且这个东西访问量非常大。那该如何搞呢?

        除了做负载之外,关键的一点就是减少损耗:减少IO、减少计算、减少转换,最好一个请求上来服务端马上就能把需要的行情数据直接返回。所以,问题的关键就是这个数据了。可能的过程是这样的:原始数据经过清洗、处理后推送到某一数据源,专用工具从数据源获取需要的数据推到服务端(如果可以,不经过数据源直接推送到服务端显然会更快),服务端缓存这些数据并响应客户端请求。很明显,数据处理和推送过程会导致行情有一点儿延迟,需要把这个延迟尽可能做小。这样,一次数据处理就可以应付N多次请求了,这个N基本上就要看服务器性能和网络情况了。

 
基于SpringBoot的JEE应用构建
            
    
    博客分类: ArchitectureMongoDBSoftware EngineeringSystem Analysis Springboot集群负载ha并发 
 

 

        如图所示,采用EhCache作为微服务Service的服务端缓存组件,搭建集群环境。其中,虚线部分标识出一个EhCache集群,它连接了两个服务:Service和Helper。Helper服务负责获取数据(被动或主动)并写入缓存,EhCache会将这些数据广播到其它节点完成同步。Service应用只需要进行读操作即可,最大限度地降低了IO频次和重复计算。

 

 

        不难发现,SpringBoot很容易地与当前的一些主流框架进行整合,适合很多应用场景的开发。Spring框架经过若干年的发展,集其大成者看来是Boot了。当然,它不仅仅是某一技术或某一工具,我们应更多地关注其背后体现的思想,掌握解决问题的方法。

 

  • 基于SpringBoot的JEE应用构建
            
    
    博客分类: ArchitectureMongoDBSoftware EngineeringSystem Analysis Springboot集群负载ha并发 
  • 大小: 16.8 KB
  • 基于SpringBoot的JEE应用构建
            
    
    博客分类: ArchitectureMongoDBSoftware EngineeringSystem Analysis Springboot集群负载ha并发 
  • 大小: 27.2 KB
  • 基于SpringBoot的JEE应用构建
            
    
    博客分类: ArchitectureMongoDBSoftware EngineeringSystem Analysis Springboot集群负载ha并发 
  • 大小: 38.6 KB
  • 基于SpringBoot的JEE应用构建
            
    
    博客分类: ArchitectureMongoDBSoftware EngineeringSystem Analysis Springboot集群负载ha并发 
  • 大小: 36.7 KB