为什么要用springboot?
springboot是由pivotal团队提供的全新框架,其设计目的是用来简化新spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,spring boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
为什么要用nginx?
概述
nginx(engine x)是一个开源的,支持高并发的www服务和代理服务软件。nginx是俄罗斯人igor sysoev开发的,最初被应用到俄罗斯的大型网站()上。后来作者将源代码以类bsd许可证的形式开源出来供全球使用。在功能应用方面,nginx不仅是一个优秀的web服务软件,还具有反向代理负载均衡和缓存的功能。在反向代理负载均衡方面类似于lvs负载均衡及haproxy等你专业代理软件。nginx部署起来更加方便简单,在缓存服务功能方面,有类似于squid等专业的缓存服务软件。nginx可以运行在unix、linux、ms windows server、mac os x server、solaris等操作系统中。
nginx的重要特性
nginx所具备的www服务特性
nginx软件主要企业应用
web服务应用产品性能对比
为什么nginx比apache的性能高?
如何正确采用web服务器?
关于部署,就不在重复了,如果需要请移步《java高级架构之fastdfs分布式文件集群》:
使用idea场景启动器创建工程
创建maven工程,修改pom.xml文件添加如下依赖:
<dependencies> <!-- springboot的自动配置相关依赖 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-autoconfigure</artifactid> <version>1.5.20.release</version> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-configuration-processor</artifactid> <version>1.5.20.release</version> </dependency> <!-- 日志相关的依赖 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-logging</artifactid> <version>1.5.20.release</version> </dependency> <!-- 对象池相关的依赖 --> <dependency> <groupid>org.apache.commons</groupid> <artifactid>commons-pool2</artifactid> <version>2.6.0</version> </dependency> </dependencies>
创建必要的包
一般情况下,springboot都会提供相应的@enablexxx注解标注在应用的主启动类上开启某个功能:
// enablefastdfsclient.java @target(elementtype.type) @retention(retentionpolicy.runtime) @import(fastdfsautoconfiguration.class) @documented public @interface enablefastdfsclient { }
下面是相关的自动配置类:
// fastdfsautoconfiguration.java @configuration @enableconfigurationproperties(fastdfsproperties.class) public class fastdfsautoconfiguration { @autowired private fastdfsproperties fastdfsproperties; @bean @conditionalonmissingbean(fastdfsclientservice.class) public fastdfsclientservice fastdfsclientservice() throws exception { return new fastdfsclientservice(fastdfsproperties); } }
创建相关的工厂类:
// storageclientfactory.java // 用于创建连接对象的工厂类 public class storageclientfactory implements pooledobjectfactory<storageclient> { @override public pooledobject<storageclient> makeobject() throws exception { trackerclient client = new trackerclient(); trackerserver server = client.getconnection(); return new defaultpooledobject<>(new storageclient(server, null)); } @override public void destroyobject(pooledobject<storageclient> p) throws exception { p.getobject().gettrackerserver().close(); } @override public boolean validateobject(pooledobject<storageclient> p) { return false; } @override public void activateobject(pooledobject<storageclient> p) throws exception { } @override public void passivateobject(pooledobject<storageclient> p) throws exception { } }
properties类用来映射application.properties或者application.yml配置文件:
// fastdfsproperties.java @configurationproperties(prefix = "fastdfs") public class fastdfsproperties { // 连接超时时间 // 网络超时时间 // 字符集编码 // 是否使用token // token加密密钥 // 跟踪器ip地址,多个使用分号隔开 // 连接池的连接对象最大个数 // 连接池的最大空闲对象个数 // 连接池的最小空闲对象个数 // nginx服务器ip,多个使用分号分割 // 获取连接对象时可忍受的等待时长(毫秒) private string connecttimeout = "5"; private string networktimeout = "30"; private string charset = "utf-8"; private string httpantistealtoken = "false"; private string httpsecretkey = ""; private string httptrackerhttpport = ""; private string trackerservers = ""; private string connectionpoolmaxtotal = "18"; private string connectionpoolmaxidle = "18"; private string connectionpoolminidle = "2"; private string nginxservers = ""; // 需要创建相关的setter和getter方法 }
在service类中封装方法, 下面仅展示3个常用的方法:
// fastdfsclientserivce.java public class fastdfsclientservice { // springboot加载的配置文件 // 连接池配置项 // 转换后的配置条目 // 连接池 // nginx服务器地址 private fastdfsproperties fdfsprop; private genericobjectpoolconfig config; private properties prop; private genericobjectpool<storageclient> pool; private string[] nginxservers; private logger logger; public fastdfsclientservice(fastdfsproperties fdfsprop) throws exception { this.fdfsprop = fdfsprop; this.logger = loggerfactory.getlogger(getclass()); init(); create(); info(); } /** * 初始化全局客户端 */ private void init() throws exception { this.prop = new properties(); this.logger.info("fastdfs: reading config file..."); this.logger.info("fastdfs: fastdfs.connect_timeout_in_seconds=" + this.fdfsprop.getconnecttimeout()); this.logger.info("fastdfs: fastdfs.network_timeout_in_seconds=" + this.fdfsprop.getnetworktimeout()); this.logger.info("fastdfs: fastdfs.charset=" + this.fdfsprop.getcharset()); this.logger.info("fastdfs: fastdfs.http_anti_steal_token=" + this.fdfsprop.gethttpantistealtoken()); this.logger.info("fastdfs: fastdfs.http_secret_key=" + this.fdfsprop.gethttpsecretkey()); this.logger.info("fastdfs: fastdfs.http_tracker_http_port=" + this.fdfsprop.gethttptrackerhttpport()); this.logger.info("fastdfs: fastdfs.tracker_servers=" + this.fdfsprop.gettrackerservers()); this.logger.info("fastdfs: fastdfs.connection_pool_max_total=" + this.fdfsprop.getconnectionpoolmaxtotal()); this.logger.info("fastdfs: fastdfs.connection_pool_max_idle=" + this.fdfsprop.getconnectionpoolmaxidle()); this.logger.info("fastdfs: fastdfs.connection_pool_min_idle=" + this.fdfsprop.getconnectionpoolminidle()); this.logger.info("fastdfs: fastdfs.nginx_servers=" + this.fdfsprop.getnginxservers()); this.prop.put("fastdfs.connect_timeout_in_seconds", this.fdfsprop.getconnecttimeout()); this.prop.put("fastdfs.network_timeout_in_seconds", this.fdfsprop.getnetworktimeout()); this.prop.put("fastdfs.charset", this.fdfsprop.getcharset()); this.prop.put("fastdfs.http_anti_steal_token", this.fdfsprop.gethttpantistealtoken()); this.prop.put("fastdfs.http_secret_key", this.fdfsprop.gethttpsecretkey()); this.prop.put("fastdfs.http_tracker_http_port", this.fdfsprop.gethttptrackerhttpport()); this.prop.put("fastdfs.tracker_servers", this.fdfsprop.gettrackerservers()); clientglobal.initbyproperties(this.prop); } /** * 显示初始化信息 */ private void info() { this.logger.info("fastdfs parameter: connectionpoolmaxtotal ==> " + this.pool.getmaxtotal()); this.logger.info("fastdfs parameter: connectionpoolmaxidle ==> " + this.pool.getmaxidle()); this.logger.info("fastdfs parameter: connectionpoolminidle ==> " + this.pool.getminidle()); this.logger.info("fastdfs parameter: nginxserver ==> " + arrays.tostring(this.nginxservers)); this.logger.info(clientglobal.configinfo()); } /** * 创建连接池 */ private void create() { this.config = new genericobjectpoolconfig(); this.logger.info("fastdfs client: creating connection pool..."); this.config.setmaxtotal(integer.parseint(this.fdfsprop.getconnectionpoolmaxtotal())); this.config.setmaxidle(integer.parseint(this.fdfsprop.getconnectionpoolmaxidle())); this.config.setminidle(integer.parseint(this.fdfsprop.getconnectionpoolminidle())); storageclientfactory factory = new storageclientfactory(); this.pool = new genericobjectpool<storageclient>(factory, this.config); this.nginxservers = this.fdfsprop.getnginxservers().split(","); } /** * nginx服务器负载均衡算法 * * @param servers 服务器地址 * @param address 客户端ip地址 * @return 可用的服务器地址 */ private string getnginxserver(string[] servers, string address) { int size = servers.length; int i = address.hashcode(); int index = abs(i % size); return servers[index]; } /** * 带有防盗链的下载 * * @param filegroup 文件组名 * @param remotefilename 远程文件名称 * @param clientipaddress 客户端ip地址 * @return 完整的url地址 */ public string autodownloadwithtoken(string filegroup, string remotefilename, string clientipaddress) throws exception { int ts = (int) (system.currenttimemillis() / 1000); string token = protocommon.gettoken(remotefilename, ts, clientglobal.getg_secret_key()); string nginx = this.getnginxserver(this.nginxservers, clientipaddress); return "http://" + nginx + "/" + filegroup + "/" + remotefilename + "?token=" + token + "&ts=" + ts; } /** * 上传文件,适合上传图片 * * @param buffer 字节数组 * @param ext 扩展名 * @return 文件组名和id */ public string[] autoupload(byte[] buffer, string ext) throws exception { string[] upload = this.upload(buffer, ext, null); return upload; } /** * 不带防盗链的下载,如果开启防盗链会导致该方法抛出异常 * * @param filegroup 文件组名 * @param remotefilename 远程文件id * @param clientipaddress 客户端ip地址,根据客户端ip来分配nginx服务器 * @return 完整的url地址 */ public string autodownloadwithouttoken(string filegroup, string remotefilename, string clientipaddress) throws exception { if (clientglobal.getg_anti_steal_token()) { this.logger.error("fastdfs client: you've turned on token authentication."); throw new exception("you've turned on token authentication."); } string nginx = this.getnginxserver(this.nginxservers, clientipaddress); return "http://" + nginx + filegroup + "/" + remotefilename; } // 后面还有好多方法,就不一一展示了 }
为了在idea中使用便捷的配置提示功能,我们需要创建元数据文件(resources/spring-configuration-metadata.json):
{ "groups": [ { "name": "fastdfs", "type": "com.bluemiaomiao.properties.fastdfsproperties", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties" } ], "properties": [ { "name": "connecttimeout", "type": "java.lang.string", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties", "defaultvalue": "5" }, { "name": "networktimeout", "type": "java.lang.string", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties", "defaultvalue": "30" }, { "name": "charset", "type": "java.lang.string", "defaultvalue": "utf-8" }, { "name": "httpantistealtoken", "type": "java.lang.string", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties", "defaultvalue": "false" }, { "name": "httpsecretkey", "type": "java.lang.string", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties" }, { "name": "httptrackerhttpport", "type": "java.lang.integer", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties" }, { "name": "trackerservers", "type": "java.lang.string", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties" }, { "name": "connectionpoolmaxtotal", "type": "java.lang.integer", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties", "defaultvalue": "18" }, { "name": "connectionpoolmaxidle", "type": "java.lang.integer", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties", "defaultvalue": "18" }, { "name": "connectionpoolminidle", "type": "java.lang.integer", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties", "defaultvalue": "2" }, { "name": "nginxservers", "type": "java.lang.string", "sourcetype": "com.bluemiaomiao.properties.fastdfsproperties" } ], "hints": [ { "name": "http_anti_steal_token", "values": [ { "value": "false" }, { "value": "true" } ] } ] }
应用到项目中
创建springboot项目,勾选web选项,版本选择1.5.20
进入场景启动器的项目目录执行mvn clean install 将其安装到本地
在pom.xml文件中添加依赖:
<dependency> <groupid>com.bluemiaomiao</groupid> <artifactid>fastdfs-spring-boot-starter</artifactid> <version>1.0-snapshot</version> </dependency>
记得开启idea的自动导入功能
创建配置文件application.properties
fastdfs.nginx-servers=192.168.80.2:8000,192.168.80.3:8000,192.168.80.4:8000 fastdfs.tracker-servers=192.168.80.2:22122,192.168.80.3:22122,192.168.80.4:22122 fastdfs.http-secret-key=2scpwmpctxhblvoyb0jyuyqzytoofmfcbiye65n56ppyvwrntxzlidbpdvddljm8qhhkxsgwtcr+9vdg3yptkw fastdfs.http-anti-steal-token=true fastdfs.http-tracker-http-port=8080 fastdfs.network-timeout=30 fastdfs.connect-timeout=5 fastdfs.connection-pool-max-idle=18 fastdfs.connection-pool-min-idle=2 fastdfs.connection-pool-max-total=18 fastdfs.charset=utf-8
或者使用application.yml
fastdfs: charset: utf-8 connect-timeout: 5 http-secret-key: 2scpwmpctxhblvoyb0jyuyqzytoofmfcbiye65n56ppyvwrntxzlidbpdvddljm8qhhkxsgwtcr+9vdg3yptkw network-timeout: 30 http-anti-steal-token: true http-tracker-http-port: 8080 connection-pool-max-idle: 20 connection-pool-max-total: 20 connection-pool-min-idle: 2 nginx-servers: 192.168.80.2:8000,192.168.80.3:8000,192.168.80.4:8000 tracker-servers: 192.168.80.2:22122,192.168.80.3:22122,192.168.80.4:22122
创建控制器类测试方法
// controllers.downloadcontroller.java @controller @requestmapping(value = "/download") public class downloadcontroller { @autowired private fastdfsclientservice service; @responsebody @requestmapping(value = "/image") public string image() throws exception { // 之前上传过的数据,实际应用场景应该使用sql数据库来存储 return service.autodownloadwithtoken("group1", "m00/00/00/wkhqa1ysjsgapjxbaavfol7fju4.tar.gz", "192.168.80.1"); } }
项目主页:
国内项目主页:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。
如对本文有疑问, 点击进行留言回复!!
Mybatis PersistenceException异常:Error building SqlSession The error may exist in SQL Mapper Configur
MyBatis——动态SQL语句——if标签和where标签复合使用
网友评论