基于SpringBoot的JEE应用构建

        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应用的技术架构如下:

 

 

 

 

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集群部署示图如下:

 

 

 

 

3、内容性应用

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

        引入依赖:

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

 

 

        可能的方式:

 

 

 

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

 

4、高并发系统

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

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

 

 

 

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

 

 

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值