`
jinnianshilongnian
  • 浏览: 21497314 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2417289
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3007791
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5638791
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259754
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1596936
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250081
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5857765
Group-logo
跟我学Nginx+Lua开...
浏览量:701672
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:784740
社区版块
存档分类
最新评论

是时候闭环Java应用了

阅读更多

你曾经因为部署/上线而痛苦吗?你曾经因为要去运维那改配置而烦恼吗?在我接触过的一些部署/上线方式中,曾碰到过以下一些问题:

1、程序代码和依赖都是人工上传到服务器,不是通过工具进行部署和发布;

2、目录结构没有规范,jar启动时通过-classpath任意指定;

3、fat jar,把程序代码、配置文件和依赖jar都打包到一个jar中,改配置文件太费劲;

4、不管是非web应用还是web应用都部署到web容器环境,如Tomcat;

5、web应用还需要先在服务器上安装好环境(如装Tomcat)才能部署,想升级版本或者换个容器太难了;

6、线上参数修改还需要找运维,痛苦。

 

还有如没有自动部署平台,回滚到上一个版本那可真是天方夜谈;增量包而非全量包,无法自由在在的回滚;前端代码直接覆盖而非版本化,难快速回滚,出问题要清理CDN,痛苦;ngx_lua项目时不按照项目的方式部署,在服务器上随意修改代码,导致某些服务器忘记修改或者版本不一致,排查问题太痛苦。

 

还有很多部署中不好的方式,但是本文只关注闭环Java应用带来的好处。首先介绍下应该如何部署应用,然后介绍下什么是闭环Java应用,它的好处和如何搭建。

 

应该如何部署应用



 

项目

项目中应该包括了所有要执行的代码、启停脚本,比如非web应用


 

web应用


 

打包应用后,会按照相应的目录结构构建。如果项目使用maven,可以使用maven-assembly-plugin进行按照相应的目录结构构件。

 

即项目、打包的应用要按照统一的风格来实施。

 

自动部署系统

自动部署系统负责打包应用(比如执行mvn相应的命令即可)、抽包(从指定目录抽取要部署的代码,如target/nonweb-example-package目录)、部署代码(发布代码,将代码同步到宿主机器)、启停应用(配置指定的启停脚本并调用)。

 

自动部署除了这些功能外,应该还有如发布历史管理(回滚)、分组管理(如不同机房不同的配置文件)、配置管理(如要修改启动/停止脚本、修改配置文件[不同机房不同的配置]、参数管理[如jvm参数等])等。

 

宿主机器

即代码部署到的机器,它应该只安装最小化环境,如只需要装JDK即可,像Tomcat是不需要安装的,由应用决定使用哪个容器。

 

通过增加自动部署系统可以更好的进行项目的统一发布、管理和回滚。

 

闭环Java应用

闭环Java应用指Java代码、容器、配置文件、启停脚本等都在同一处维护,修改配置文件、修改环境参数、更改容器类型等都不需要到宿主机器上进行更改。宿主机器只提供基本运行环境,如仅部署JDK环境即可,不需要部署如Tomcat容器,需要什么容器,都是在Java应用中指定。

 

这样的好处是配置文件修改、JVM参数修改、容器的选择都可以在Java应用中配置,形成闭环。

 

闭环Java应用的目的主要是让Java应用能自启动,这样程序的控制权就在我们手里,而不是运维手里。而我们更懂我们的程序。

 

随着微服务概念的流行,spring boot也受到大家的热捧。spring boot能帮助我们快速构建基于spring的应用;其能方便创建自启动应用、可以嵌入各种容器(如Tomcat、Jetty)、提供了一些starter pom用于简化配置文件、自动化配置(只需要引入相关的pom,就自动获得了某些功能)等。

 

在介绍spring boot之前,我们看下在以前是怎么构建闭环Java应用。

 

从零构建非web应用

项目结构


 
本示例演示了构建一个非web应用
RPC服务生产者(如Dubbo服务),还可以构建如Worker类型的应用,他们本身不需要web容器,作为普通的java应用启动即可。

 

maven依赖(pom.xml)

需要自己添加如spring-core、spring-context等相关依赖,此处就不展示了。

 

打包配置(pom.xml)

nonweb-example\pom.xml

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptor>src/assembly/assembly.xml</descriptor>
<finalName>${project.build.finalName}</finalName>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>directory</goal>
</goals>
</execution>
</executions>
</plugin>

 

使用maven-assembly-plugin进行打包;打包配置如下:

<id>package</id>
<
formats>
    <
format>dir</format>
</
formats>
<
includeBaseDirectory>false</includeBaseDirectory>
<
fileSets>
   
<!-- 可执行文件 -->
   
<fileSet>
        <
directory>src/bin</directory>
        <
outputDirectory>bin</outputDirectory>
        <
includes>
            <
include>*.bat</include>
        </
includes>
        <
lineEnding>dos</lineEnding>
    </
fileSet>
    <
fileSet>
        <
directory>src/bin</directory>
        <
outputDirectory>bin</outputDirectory>
        <
includes>
            <
include>*.sh</include>
        </
includes>
        <
lineEnding>unix</lineEnding>
        <
fileMode>0755</fileMode>
    </
fileSet>
   
<!-- classes -->
   
<fileSet>
        <
directory>${project.build.directory}/classes</directory>
        <
outputDirectory>classes</outputDirectory>
    </
fileSet>
</
fileSets>
<!-- 依赖jar包 -->
<dependencySets>
    <
dependencySet>
        <
outputDirectory>lib</outputDirectory>
        <
excludes>
            <
exclude>com.jd:nonweb-example</exclude>
        </
excludes>
    </
dependencySet>
</
dependencySets>

主要有三组配置:

formats:打包格式,此处使用的是dir,还可以是zip、rar等;

fileSet:拷贝文件,本示例主要有bin文件、classes文件需要拷贝;

dependencySets:依赖jar,拷贝到lib目录;

 

执行mvn package后形成了将得到如下结构:

 

将该目录通过自动部署抽包并部署到宿主机器即可。然后自动部署系统执行bin下的启停脚本执行即可。

  

启动类 

public class Bootstrap {
  
public static void main(String[] args) throws Exception {
      ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath:spring-config.xml");
      ctx.registerShutdownHook();
      Thread.currentThread().join();
  }
}

本示例没有使用Java Config方式构建,直接加载spring配置文件启动Java应用。

 

启动脚本

#!/bin/sh
echo -------------------------------------------
echo start server
echo -------------------------------------------
#
设置项目代码路径
export CODE_HOME="/export/App/nonweb-example-startup-package"
#日志路径
export LOG_PATH="/export/Logs/nonweb.example.jd.local"
mkdir -p $LOG_PATH
# 设置依赖路径
export CLASSPATH="$CODE_HOME/classes:$CODE_HOME/lib/*"
# java可执行文件位置
export _EXECJAVA="$JAVA_HOME/bin/java"
# JVM启动参数
export JAVA_OPTS="-server -Xms128m -Xmx256m -Xss256k -XX:MaxDirectMemorySize=128m"
# 启动类
export MAIN_CLASS=com.jd.nonweb.example.startup.Bootstrap

$_EXECJAVA $JAVA_OPTS -classpath $CLASSPATH $MAIN_CLASS &
tail -f $LOG_PATH/stdout.log

配置项目代码路径、日志路径、依赖路径、java执行文件路径、JVM启动参数、启动类。

 

停止脚本

#日志路径
export LOG_PATH="/export/Logs/nonweb.example.jd.local"
mkdir -p $LOG_PATH
# 启动类
export MAIN_CLASS=com.jd.nonweb.example.startup.Bootstrap

echo -------------------------------------------
echo stop server

#所有相关进程
PIDs=`jps -l | grep $MAIN_CLASS | awk '{print $1}'`
#停止进程
if [ -n "$PIDs" ]; then
  for PID in $PIDs; do
      kill $PID
      echo "kill $PID"
  done
fi

#等待50秒
for i in 1 10; do
  PIDs=`jps -l | grep $MAIN_CLASS | awk '{print $1}'`
  if [ ! -n "$PIDs" ]; then
    echo "stop server success"
    echo -------------------------------------------
    break
  fi
  echo "sleep 5s"
  sleep 5
done

#如果等待50秒还没有停止完,直接杀掉
PIDs=`jps -l | grep $MAIN_CLASS | awk '{print $1}'`
if [ -n "$PIDs" ]; then
  for PID in $PIDs; do
      kill -9 $PID
      echo "kill -9 $PID"
  done
fi
tail -fn200 $LOG_PATH/stdout.log

到此一个闭环非web应用就构建完了,启停脚本、启动类、项目代码都是统一在一处维护,并使用maven-assembly-plugin将这些打包在一起,通过自动部署发布并执行,达到了闭环的目的。

 

 

从零构建web应用

项目结构 


 

 

maven依赖(pom.xml)

需要自己添加如spring-core、spring-context、spring-web、spring-webmvc、velocity等相关依赖,此处就不展示了。

 

打包配置(pom.xml)

web-example\pom.xml

<plugin>
    <
groupId>org.apache.maven.plugins</groupId>
    <
artifactId>maven-assembly-plugin</artifactId>
    <
version>2.6</version>
    <
configuration>
        <
descriptor>src/assembly/assembly.xml</descriptor>
        <
finalName>${project.build.finalName}</finalName>
    </
configuration>
    <
executions>
        <
execution>
            <
phase>package</phase>
            <
goals>
                <
goal>directory</goal>
            </
goals>
        </
execution>
    </
executions>
</
plugin>

使用maven-assembly-plugin进行打包;打包配置如下:

<id>package</id>
<
formats>
    <
format>dir</format>
</
formats>
<
includeBaseDirectory>false</includeBaseDirectory>
<
fileSets>
    <
fileSet>
        <
directory>src/bin</directory>
        <
outputDirectory>bin</outputDirectory>
        <
includes>
            <
include>*.sh</include>
        </
includes>
        <
lineEnding>unix</lineEnding>
        <
fileMode>0755</fileMode>
    </
fileSet>
   
<!-- WEB-INF -->
   
<fileSet>
        <
directory>src/main/webapp</directory>
        <
outputDirectory></outputDirectory>
    </
fileSet>
   
<!-- classes -->
   
<fileSet>
        <
directory>${project.build.directory}/classes</directory>
        <
outputDirectory>WEB-INF/classes</outputDirectory>
    </
fileSet>

</
fileSets>
<!-- 依赖jar包 -->
<dependencySets>
    <
dependencySet>
        <
outputDirectory>WEB-INF/lib</outputDirectory>
        <
excludes>
            <
exclude>com.jd:web-example</exclude>
        </
excludes>
    </
dependencySet>
</
dependencySets>

主要有三组配置:

formats:打包格式,此处使用的是dir,还可以是zip、rar等;

fileSet:拷贝文件,本示例主要有bin文件、classes文件、webapp文件需要拷贝;

dependencySets:依赖jar,拷贝到WEB-INF\lib目录;

 

执行mvn package后形成了将得到如下结构:


  

打包的目录结构和普通web结构完全一样;将该目录通过自动部署抽包并发布到宿主机器即可。然后自动部署系统执行bin下的启停脚本执行即可。

 

启动类

public class TomcatBootstrap {
 
private static final Logger LOG = LoggerFactory.getLogger(TomcatBootstrap.class);
 
public static void main(String[] args) throws Exception{
    
//提升性能(https://wiki.apache.org/tomcat/HowTo/FasterStartUp)
    
System.setProperty("tomcat.util.scan.StandardJarScanFilter.jarsToSkip", "*.jar");
    
//System.setProperty("securerandom.source","file:/dev/./urandom");
    
int port =Integer.parseInt(System.getProperty("server.port", "8080"));
    String contextPath = System.getProperty(
"server.contextPath", "");
    String docBase = System.getProperty(
"server.docBase", getDefaultDocBase());
    
LOG.info("server port : {}, context path : {},doc base : {}",port, contextPath, docBase);
    Tomcat tomcat = createTomcat(port,contextPath, docBase);
    tomcat.start();
    Runtime.getRuntime().addShutdownHook(
new Thread() {
       
@Override
       
public void run(){
           
try {
               
tomcat.stop();
            }
catch (LifecycleException e) {
               
LOG.error("stoptomcat error.", e);
            }
        }
    });
    tomcat.getServer().await();
 }

 private static String getDefaultDocBase() {
   File classpathDir =
new File(Thread.currentThread().getContextClassLoader().getResource(".").getFile());
   File projectDir =classpathDir.getParentFile().getParentFile();
  
return new File(projectDir,"src/main/webapp").getPath();
 }

 private static Tomcat createTomcat(int port,String contextPath, String docBase) throws Exception{
    String tmpdir = System.getProperty(
"java.io.tmpdir");
    Tomcat tomcat =
new Tomcat();
    tomcat.setBaseDir(tmpdir);
    tomcat.getHost().setAppBase(tmpdir);
    tomcat.getHost().setAutoDeploy(
false);
    tomcat.getHost().setDeployOnStartup(
false);
    tomcat.getEngine().setBackgroundProcessorDelay(-
1);
    tomcat.setConnector(newNioConnector());
    tomcat.getConnector().setPort(port);
    tomcat.getService().addConnector(tomcat.getConnector());
    Context context =tomcat.addWebapp(contextPath, docBase);
    StandardServer server =(StandardServer) tomcat.getServer();
   
//APR library loader. Documentation at /docs/apr.html
   
server.addLifecycleListener(new AprLifecycleListener());
   
//Prevent memory leaks due to use of particularjava/javax APIs
   
server.addLifecycleListener(new JreMemoryLeakPreventionListener());
   
return tomcat;
  }

 
//在这里调整参数优化
 
private static Connector newNioConnector() {
    Connector connector =
new Connector("org.apache.coyote.http11.Http11NioProtocol");
    Http11NioProtocol protocol =(Http11NioProtocol) connector.getProtocolHandler();
   
return connector;
 }

}

通过嵌入Tomcat容器启动,这种方式的确定是需要先写Tomcat的启动代码,优点也很明显:以后Tomcat的控制权在我们手中,可以随时进行切换或者优化,不需要改线上的配置文件。

 

启动脚本

#!/bin/sh
echo -------------------------------------------
echo start server
echo -------------------------------------------
#
设置项目代码路径
export CODE_HOME="/export/App/web-example-web-package"
#日志路径
export LOG_PATH="/export/Logs/web.example.jd.local"
mkdir -p $LOG_PATH
# 设置依赖路径
export CLASSPATH="$CODE_HOME/WEB-INF/classes:$CODE_HOME/WEB-INF/lib/*"
# java可执行文件位置
export _EXECJAVA="$JAVA_HOME/bin/java"
# JVM启动参数
export JAVA_OPTS="-server -Xms128m -Xmx256m -Xss256k-XX:MaxDirectMemorySize=128m"
# 服务端端口、上下文、项目根配置
export SERVER_INFO="-Dserver.port=8090 -Dserver.contextPath=-Dserver.docBase=$CODE_HOME"
# 启动类
export MAIN_CLASS=com.jd.web.example.startup.TomcatBootstrap

$_EXECJAVA $JAVA_OPTS -classpath $CLASSPATH $SERVER_INFO $MAIN_CLASS &
tail -f $LOG_PATH/stdout.log

 

配置项目代码路径、日志路径、依赖路径、java执行文件路径、JVM启动参数、启动类;相当于非web应用,多了web服务器端口、上下文、项目根路径配置。

 

停止脚本

和非web的类似就不再重复了。

 

到此一个闭环web应用就构建完了,启停脚本、启动类、项目代码都是统一在一处维护,并使用maven-assembly-plugin将这些打包在一起,通过自动部署发布并执行。达到了闭环的目的。

 

Spring Boot构建非web/web应用

项目结构

 

maven依赖(pom.xml)

spring-boot-example/pom.xml继承spring-boot-starter-parent

<parent>
    <
groupId>org.springframework.boot</groupId>
    <
artifactId>spring-boot-starter-parent</artifactId>
    <
version>1.4.1.BUILD-SNAPSHOT</version>
</
parent>

spring-boot-starter-parent中是一些通用配置,如JDK编码、依赖管理(它又继承了spring-boot-dependencies,这里边定义了所有依赖);

 

依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-velocity</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

spring-boot-starter是最小化的spring boot环境(spring-core、spring-context等);spring-boot-starter-web是spring mvc环境,并使用Tomcat作为web容器;spring-boot-starter-velocity将自动将模板引擎配置为velocity。此处可以看到starter的好处了,需要什么功能只需要引入一个starter,相关的依赖自动添加,而且会自动配置使用该特性。

 

 

打包配置(pom.xml)

spring-boot-example-web\pom.xml添加如下maven插件:

<plugin>
    <
groupId>org.springframework.boot</groupId>
    <
artifactId>spring-boot-maven-plugin</artifactId>
</
plugin>

执行mvn package时将得到如下fat jar:



  

启动类

package com.jd.springboot.example.web.startup;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication(scanBasePackages = "com.jd.springboot.example")
@ImportResource("classpath:spring-config.xml")
public class Bootstrap {
  
public static void main(String[] args) {
      SpringApplication.run(Bootstrap.
class, args);
  }
}

@SpringBootApplication指定了要扫描的包、可以使用@ImportResource引入xml配置文件。然后可以直接作为普通java应用启动即可,此时自动使用tomcat作为web容器启动。

 

运行 jar -jar spring-boot-example-1.0-SNAPSHOT.jar即可启动(META-INF\MANIFEST.MF指定了Main-Class)。

 

个人不太喜欢fat jar的方式。可以使用maven-assembly-plugin配合来打包Java应用。项目结构如下所示:


 

项目结构和之前的区别是多了assembly和bin。

 

打包配置(pom.xml)

spring-boot-example-web\pom.xml将如下maven插件

<plugin>
    <
groupId>org.springframework.boot</groupId>
    <
artifactId>spring-boot-maven-plugin</artifactId>
</
plugin>

 更改为assembly插件

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptor>src/assembly/assembly.xml</descriptor>
<finalName>${project.build.finalName}</finalName>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>directory</goal>
</goals>
</execution>
</executions>
</plugin>

assembly.xml和“从零构建非web应用”的类似,就不贴配置了。

 

执行mvn package时将得到如下打包:

 

启停脚本也是类似的,在此也不贴配置了。到此基于spring boot的非fat jar方式的自启动Java应用就构建好了。

   

 

总结

从零构建非web应用/web应用需要我们查找相关依赖并配置,还需要进行一些配置(Spring配置、容器配置),如果构建一个新的项目还是相对较慢的,但是在公司内大家应该都有自己的“starter pom”,因此实际构建也不会很慢。而如果没有一些项目的积累,使用spring boot可以非常容易而且快速的就能搭建出想要的项目。使用spring boot后:容易添加依赖、启动类不用自己创建、享受到自动配置的好处等;而自带的spring-boot-maven-plugin会生成fat jar,不过可以配合maven-assembly-plugin来实现之前的方式的。

 

另外因笔者所在公司使用Docker容器,一个宿主机器只部署一个JVM示例,示例中的启停脚本不用考虑单机多JVM实例问题。

 

创建闭环Java应用,可以更容易的进行如JVM参数调优、修改容器配置文件、非web应用不需要部署到Tomcat容器中;这是笔者想进行闭环Java应用的主要目的。

  • 大小: 7.2 KB
  • 大小: 26.4 KB
  • 大小: 171.4 KB
  • 大小: 24.5 KB
  • 大小: 54.4 KB
  • 大小: 20.1 KB
  • 大小: 171.3 KB
  • 大小: 18.1 KB
  • 大小: 19.8 KB
  • 大小: 5.2 KB
4
1
分享到:
评论
4 楼 mooncafes 2017-06-15  
你好,tao哥,请教问题
1、内嵌tomcat后,原有tomcat的日志输出目录怎么设置,也就是原来logs路径下的catalina.out怎么指定?另外,BaseDir和AppBase有什么用呢?

tomcat.setBaseDir(tmpdir);
tomcat.getHost().setAppBase(tmpdir);

2、可不可以让内嵌tomcat加载原有的XML文件进行初始化呢?只抽取设置端口的逻辑到bootstrap启动类中

期待tao哥指导
3 楼 jinnianshilongnian 2016-08-19  
LinApex 写道
总体来说,文章只讲了打包方式,通过打包结合自动部署的 start,stop程序,来进行控制程序。 关于如何做增量更新,版本回滚,测试这块都还没有,希望作者有空可以分享一下,谢谢你。

哈,主要这块是京东自研的系统,思路是这样的,具体去做并不是很难
2 楼 LinApex 2016-08-19  
总体来说,文章只讲了打包方式,通过打包结合自动部署的 start,stop程序,来进行控制程序。 关于如何做增量更新,版本回滚,测试这块都还没有,希望作者有空可以分享一下,谢谢你。
1 楼 masuweng 2016-08-18  
内容有点林乱,分开讲解下把,最近正血虚springboot呢.

相关推荐

    Java版查找并打印有向图中的所有环路径

    而`MSTApp.java`可能是主应用程序,用于测试和展示有向图的环路检测功能。 在有向图中查找环路的方法通常有深度优先搜索(DFS)和拓扑排序。深度优先搜索是一种递归策略,通过遍历图的分支直到达到终点或发现环路。...

    java与uml协同应用开发

    这样,整个软件开发过程就形成了一个闭环,UML和Java之间形成了良性的互动关系。 总结来说,Java与UML协同应用开发旨在通过模型驱动的方法,提升软件开发的效率、质量和可维护性。通过清晰的UML模型,可以更好地...

    事件驱动模型实例详解(Java篇)

    在Java中,事件驱动模型的应用主要体现在Swing框架上,它是Java中用于构建桌面应用程序的标准工具包。Swing提供了丰富的预置组件,如按钮(`JButton`)、单选按钮(`JRadioButton`)等,用于创建动态、响应式的用户...

    实战应用Java算法分析与设计(链表、二叉树、哈夫曼树、图、动态规划)视频

    ### 实战应用Java算法分析与设计 #### 一、引言 在计算机科学领域,算法是解决问题的关键。《实战应用Java算法分析与设计》视频教程深入浅出地讲解了链表、二叉树、哈夫曼树、图以及动态规划等核心数据结构与算法,...

    Java超市购物进销存系统

    【Java超市购物进销存系统】是一个基于Java技术开发的软件应用,主要用于管理超市的进货、销售和库存等业务流程。这个系统集成了多种核心功能,以提高超市运营效率,确保库存准确,优化商品流通。下面我们将深入探讨...

    java深度优先搜索 可以设置图的一系列数据

    深度优先搜索(Depth-First Search,简称DFS)是图论中的一个重要算法,广泛应用于计算机科学领域,尤其是在解决图和树结构的问题中。DFS的基本思想是从起点开始,沿着某一条路径一直深入到不能再深入为止,然后回溯...

    “MOOC+项目驱动”教学模式在《Java EE应用开发》教学中的实践研究.zip

    《“MOOC+项目驱动”教学模式在《Java EE应用开发》教学中的实践研究》这篇文档,揭示了在信息技术教育领域中,如何结合大规模在线开放课程(MOOC)与项目驱动学习方法,来提升Java EE应用开发的教学效果。...

    基于java小区物业管理系统

    9. **移动应用支持**:考虑到便捷性,系统可能还包括移动端的应用,如微信小程序或Android/iOS App,让业主可以随时随地进行操作。 在【JAVA物业管理系统】的压缩包中,可能包含了源码、数据库脚本、配置文件以及...

    Java的循环单链表及其测试程序

    循环单链表是一种常见的数据结构,它在计算机科学和编程中有着广泛的应用。与普通单链表不同,循环单链表的最后一个元素指向第一个元素,形成一个闭环,使得链表的遍历可以无止境地进行。在Java中实现循环单链表,...

    转速闭环控制直流调速系统仿真.docx.zip

    转速闭环控制直流调速系统是电力驱动领域中一个重要的研究课题,它涉及到电机控制理论、自动控制原理以及电力电子技术等多个方面的知识。在实际应用中,这种控制系统能够确保电机运行稳定,转速准确,适应性强,适用...

    转速闭环控制直流调速系统仿真.zip

    通过这个仿真项目,学习者不仅可以掌握转速闭环控制的基本概念,还能深入理解控制理论在实际系统中的应用。此外,掌握如何使用计算机工具进行系统建模和仿真,对于提升工程实践能力也是非常有益的。在实际工作中,...

    融入OBE理念的JAVA课程教学模式研究.pdf

    这样,通过闭环设计的教学模式,可以不断完善Java课程教学,使之与市场需求有效对接,提高学生的职业竞争力。 总体来说,融入OBE理念的Java课程教学模式研究,不仅关注学生技能的培养,而且强调学生综合能力的提升...

    java循环队列的分析和实例介绍.pdf

    ### Java循环队列的深入解析与实践应用 #### 循环队列概念解析 循环队列,作为一种高效的数据结构,广泛应用于计算机科学中,尤其是在Java编程语言中,它以其独特的性能优势,在各种算法和系统设计中占据了...

    BLDC_JAVA.zip_run

    4. 闭环控制:为了精确控制电机,通常采用PID(比例-积分-微分)控制器,通过实时反馈调整电机的转速和位置。 五、Java编程实践 在本项目中,开发者可能创建了Java类来处理电机驱动逻辑,如电机状态管理、PWM控制、...

    深度搜索 Depth-First Search的Java实现

    深度搜索(DFS,Depth-First Search)是一种在图或树...以上就是关于深度搜索(DFS)的基本概念、实现方式、应用以及Java实现的关键知识点。在实际编程中,需要根据具体问题调整代码,例如处理闭环、优化路径记录等。

    java毕业设计&课设-画布:时钟.zip

    本资源包“java毕业设计&课设-画布:时钟.zip”提供了一个具体的实例——使用Java实现一个时钟应用,旨在帮助学生深入理解Java图形用户界面(GUI)的开发,特别是Java AWT和Swing库的应用。 在Java中,`Canvas`类是...

    基于虚拟化云计算的医学装备闭环管理系统设计.pdf

    在本系统的设计和开发过程中,使用了RationalRose2007这一设计工具进行系统结构设计,利用JAVA编程软件进行开发,并使用MySQL数据库管理系统来存储相关数据。开发环境采用的是CenteOS6.4操作系统。通过这些工具和...

Global site tag (gtag.js) - Google Analytics