在此 Spring Roo 系列的 Spring Roo 简介,第 1 部分:从源代码构建 中,我们使用 Spring Roo 构建了一个小的企业会议应用程序。此处,我们将使用 Spring Roo 将简单的 CRUD web 应用程序扩展成一个成熟的企业应用程序。开始之前,要确认您已经安装了 Spring Roo 并下载了 SpringSource Tool Suite (见第 1 部分获取更多信息)。
现在开始
要扩展会议应用程序,需要重建第 1 部分中的应用程序。您可以按照之前的指导或者是使用 Roo 的 script
命令。script
会执行源文件中的所有命令。如果您学习了第 1 部分,您会注意到 Roo 创建了一个名为 log.roo 的文件,它包含了 Roo shell 中执行的所有命令。我们将执行 log.roo 文件并重建应用程序。
- 此文件包含在代码样例中。可以将其重命名为 conference.roo。
- 创建一个名为 conference 的目录并把 conference.roo 拷贝进去。
- 打开操作系统命令行 shell。
- 进入刚创建的 conference 目录。
- 执行
script --file conference.roo
命令。
如果所需要的 JAR 在 Maven 存储库,script
将会在几秒钟之内重建应用程序。否则,将会花费更长的时间,因为它要下载所有 JAR。script
命令很有用,因为可以将它用作一个模板来创建 Spring 托管的项目。
在进入下一步之前,将 Maven 项目导入 STS 中 。STS 预装捆绑在 Maven Eclipse 插件 中。您可以通过选择 File > Import > Maven > Existing Maven Projects 导入此项目。我们将在此后编写自定义代码导入 STS 项目。
目前所创建的 web 应用程序已经可以运行,我们可以通过创建、读取、更新和删除 Speaker 和 Talk 实体来手工测试。但如果这些过程能自动化不是更好么?
自动化 web 测试
这里是 Spring Roo 的另一个属性:Selenium 测试支持。Selenium 是一组功能强大的工具,它支持基于 web 应用程序测试自动化的快速开发。要将 Selenium 测试支持添加到您的应用程序中,执行以下命令:
selenium test --controller ~.web.SpeakerController selenium test --controller ~.web.TalkController
selenium test
命令将会创建 Speaker 和 Talk 控制器的 Selenium 支持。此命令有个属性 controller 用来指定控制器的名称,以创建 Selenium 测试。此命令还有两个可选属性 name
和 serverUrl
用来指定 Selenium 测试的名称和 web 应用程序可用的服务器。当您执行 selenium test
命令时,Spring Roo 还会添加 Selenium Maven 插件。
至此,我们创建了控制器的 Selenium 测试用例,但在运行之前,我们要先修复 Spring Roo 所创建的 Selenium 测试套件中的一个小缺陷。我们在 Speaker 实体中加入一个约束, 年龄应在 25 到 60 之间,但测试套件对此约束不予考虑。它使用了年龄 1 岁,测试失败。我们需要修改一个名为 test-speaker.xhtml 的文件,并按清单 1 所示更新这部分。
清单 1. 修改 test-speaker.xhtml
<tr> <td>type</td> <td>_age_id</td> <td>1</td> </tr>
to
<tr> <td>type</td> <td>_age_id</td> <td>26</td> </tr>
此缺陷将会在 Spring Roo 的后续版本中修复。
要运行 Selenium 测试案例,需要启动 Tomcat 服务器。可以通过使用 Maven 命令 mvn tomcat:run
来启动。默认情况下,所有使用 Roo 创建的 web 应用程序都有用于 Tomcat 和 Jetty web 服务器的 Maven 插件。要运行 selenium test
,执行 Maven 命令 mvn selenium:selenese
。
这将启动 Firefox 浏览器运行 Selenium 测试案例。在测试执行时,您会看到如图 1 所示的图片。
图 1. Selenium 测试
现在,所有人可以访问应用程序并在 Speaker 和 Talk 上执行创建、更新和删除操作。在实时应用程序中,还有安全问题,即谁能做哪些操作。
保证 web 应用程序的安全
Roo 使用 Spring Security 向应用程序添加安全性能。Spring Security 是功能强大的并高度可定制的认证和访问控制框架。这是保证基于 Spring 的应用程序安全的实际标准。
添加 Spring Security
要添加 Spring Security,输入以下命令:security setup
。
此 命令将会添加所有所需的 Spring Security JAR 并设置应用程序的基本安全。此命令还会创建其他文件,其中重要的是 applicationContext-security.xml,它包含所有与安全相关的 bean 定义。applicationContext-security.xml 内容看上去像清单 2 。我已经用点号代替了密码,使得可读性更好。
清单 2. applicationContext-security.xml 的内容
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans \ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security \ http://www.springframework.org/schema/security/spring-security-3.0.xsd"> <!-- HTTP security configurations --> <http auto-config="true" use-expressions="true"> <form-login login-processing-url="/resources/j_spring_security_check" \ login-page="/login" authentication-failure-url="/login?login_error=t"/> <logout logout-url="/resources/j_spring_security_logout"/> <!-- Configure these elements to secure URIs in your application --> <intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')"/> <intercept-url pattern="/member/**" access="isAuthenticated()" /> <intercept-url pattern="/resources/**" access="permitAll" /> <intercept-url pattern="/**" access="permitAll" /> </http> <!-- Configure Authentication mechanism --> <authentication-manager alias="authenticationManager"> <!-- SHA-256 values can be produced using \ 'echo -n your_desired_password | sha256sum' \ (using normal *nix environments) --> <authentication-provider> <password-encoder hash="sha-256"/> <user-service> <user name="admin" password="..." authorities="ROLE_ADMIN"/> <user name="user" password="..." authorities="ROLE_USER"/> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
由 Roo 配置的安全是通用的,我们的应用程序不需要关注。请记住 Roo 能够帮助您快速安装或配置,但定制最终产品是开发人员的责任。本例中,Roo 只提供了 Spring Security 模板,按照需求定制是我们的责任。
自定义 Spring Security
在我们的应用程序中,所有人都能创建 Speaker,但只有 Speaker 能创建 Talk。我们需要如下修改 applicationContext-security.xml。清单 3 只显示了需要修改的 XML 的一部分。
清单 3. 修改 applicationContext-security.xml
<http auto-config="true" use-expressions="true"> <form-login login-processing-url="/resources/j_spring_security_check" \ login-page="/login" authentication-failure-url="/login?login_error=t"/> <logout logout-url="/resources/j_spring_security_logout"/> <!-- Configure these elements to secure URIs in your application --> <intercept-url pattern="/talks/**" access="hasRole('ROLE_USER')"/> <intercept-url pattern="/speakers/**" access="permitAll" /> <intercept-url pattern="/resources/**" access="permitAll" /> <intercept-url pattern="/**" access="permitAll" /> </http>
我更新了 intercept-url
,这样只有角色为 user 的用户才能创建 Talk,并且所有用户都可以将自己注册为 Speaker。
如上 Roo 生成的 Spring Security 在 <user-service>
标记下使用了 内存认证 提供程序。由于我们的应用程序管理 Speaker 实体,我们应当建立一个使用 Speaker 数据的自定义认证提供程序。对于认证,我们将使用 Speaker email 作为用户名,并为 Speaker 实体添加一个密码字段,它也将用作认证密码。
我将再次使用 Roo shell 来将密码字段添加到 Speaker 实体:
field string --class ~.domain.Speaker --fieldName password --notNull --sizeMin 6 –sizeMax 10
我还加入了限制条件,密码不能为空,长度在 6 至 10 个字符之间。
由于我们使用 email 和密码作为认证参数,我们找一个 Speaker 的 email 和密码。Spring Roo 提供了一个功能为您的应用程序创建查找程序,是用 finder add
命令:
finder add --finderName findSpeakersByEmailAndPasswordEquals --class ~.domain.Speaker
您可以使用 finder list
命令找到某个实体的所有查找程序。finder add
在 Speaker_Roo_Finder.aj 文件写入查找程序代码,并写入一些视图相关的文件。这让您能够从 GUI 查找所有演讲者。
写入自定义 AuthenticationProvider
我们通过扩展一个名为 AbstractUserDetailsAuthenticationProvider
的类来写入自定义 Authentication 提供程序,它使用用户名/密码进行认证。扩展 AbstractUserDetailsAuthenticationProvider
的类需要提供两个具体方法的实现:additionalAuthenticationChecks
和 retrieveUser
。提供程序调用 retrieveUser
方法使用输入的 email 和密码来认证 Speaker。数据库查找 Speaker 是使用我们之前创建的查找程序。如果找到了 Speaker,会将 GrantedAuthority ROLE_USER
分配给 Speaker。如果登录成功,此方法最终会返回一个弹出的 UserDetails
对象,否则会抛出一个 BadCredentialsException
及相关信息(见清单 4)。
清单 4. 自定义认证
package com.dw.roo.conference.security; import java.util.ArrayList; import java.util.List; import javax.persistence.EntityNotFoundException; import javax.persistence.NonUniqueResultException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.\ dao.AbstractUserDetailsAuthenticationProvider; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.StringUtils; import com.dw.roo.conference.domain.Speaker; public class ConferenceAuthenticationProvider extends \ AbstractUserDetailsAuthenticationProvider { @Override protected void additionalAuthenticationChecks(UserDetails userDetails, \ UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { // TODO Auto-generated method stub } @Override protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken \ authentication) throws AuthenticationException { String password = (String) authentication.getCredentials(); if (!StringUtils.hasText(password)) { throw new BadCredentialsException("Please enter password"); } List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); try { Speaker speaker = Speaker.findSpeakersByEmailAndPasswordEquals(username, \ password).getSingleResult(); authorities.add(new GrantedAuthorityImpl("ROLE_USER")); } catch (EmptyResultDataAccessException e) { throw new BadCredentialsException("Invalid username or password"); } catch (EntityNotFoundException e) { throw new BadCredentialsException("Invalid user"); } catch (NonUniqueResultException e) { throw new BadCredentialsException("Non-unique user, contact administrator"); } return new User(username, password, true, // enabled true, // account not expired true, // credentials not expired true, // account not locked authorities); } }
在 applicationContext-security.xml 中,我们要定义 conferenceAuthenticationProvider
bean 并用我们的 conferenceAuthenticationProvider
代替 Roo 创建的内存认证提供程序,如清单 5 所示。
清单 5. conferenceAuthenticationProvider
<beans:bean name="conferenceAuthenticationProvider" class="com.dw.roo.conference.security.ConferenceAuthenticationProvider"> </beans:bean> <!-- Configure Authentication mechanism --> <authentication-manager alias="authenticationManager"> <authentication-provider ref="conferenceAuthenticationProvider"/> </authentication-manager>
现在如果您启动了服务器并试图创建 Talk,您会看到一个登录屏幕,需要在此处输入您创建的 Speaker 的 email 和密码。构建自定义认证提供程序的目的不是构建一个理想的认证提供程序,而是告诉您 Roo 做了哪些,您自己需要做哪些。
Email 通知
在 我们的应用程序中,Speaker 在创建 Talk 时应该能收到 email,让我们在应用程序中加入 email 支持。我们将使用 Gmail 作为 SMTP 服务器,以便把精力集中在使用 Roo 发送 email。向应用程序中加入 email 支持要使用以下命令:
email sender setup --hostServer smtp.gmail.com --username \ <Your email address> --password <Your email password> --port 587 --protocol SMTP
email 发送程序命令会在您的项目中安装一个 Spring JavaMailSender
。您可以在 email.properties 文件中修改 email 相关的属性。
创建 Talk 后,我们要发送一封 email。需要在 TalkController
中加入 email 字段。要添加 email 字段,输入:
field email template --class ~.web.TalkController
这会将 MailSender
模板和 sendMessage
方法加入 TalkController
。当 Talk 存在于数据库之后,我们需要触发 sendMessage
方法。由于 TalkController
的所有代码都在 TalkController_Roo_Controller.aj 文件中,完成该任务的最简单的方法是创建一个从 .aj 文件到 TalkController
类的 encodeUrlPathSegment
方法,并在 talk.persist()
行之后添加一个对 sendMessage
方法的调用,如清单 6 所示。
清单 6. 创建一个从 .aj 文件到 TalkController
的 encodeUrlPathSegment
方法
public class TalkController { @Autowired private transient MailSender mailTemplate; public void sendMessage(String mailFrom, String subject, String mailTo, String message) { org.springframework.mail.SimpleMailMessage \ simpleMailMessage = new org.springframework.mail.SimpleMailMessage(); simpleMailMessage.setFrom(mailFrom); simpleMailMessage.setSubject(subject); simpleMailMessage.setTo(mailTo); simpleMailMessage.setText(message); mailTemplate.send(simpleMailMessage); } @RequestMapping(method = RequestMethod.POST) public String create(@Valid Talk talk, BindingResult result, Model model, HttpServletRequest request) { if (result.hasErrors()) { model.addAttribute("talk", talk); return "talks/create"; } talk.persist(); sendMessage("spring.roo.playground@gmail.com", "Your talk is created", talk.getSpeaker().getEmail(), \ "Congrats your talk is created"); return "redirect:/talks/" + encodeUrlPathSegment(talk.getId().toString(), request); } private String encodeUrlPathSegment(String pathSegment, HttpServletRequest request) { String enc = request.getCharacterEncoding(); if (enc == null) { enc = WebUtils.DEFAULT_CHARACTER_ENCODING; } try { pathSegment = UriUtils.encodePathSegment(pathSegment, enc); } catch (UnsupportedEncodingException uee) { } return pathSegment; } }
至此,Speaker 将会在创建 Talk 后在专有帐户中收到 email。
国际化支持
我们构建的是基于 Internet 的 web 应用程序,因此,支持不同语言让来自不同地方的用户能够使用我们的应用程序就非常重要。Spring Roo 通过使用 web mvc install language
命令来添加国际化支持,它将会在您的应用程序中添加新的语言。例如,西班牙语和意大利语的命令是:
web mvc install language --code es web mvc install language --code it
Roo 目前支持六种语言,您可以根据选择编写其他的语言插件。但应用程序运行时,会显示两个国旗(意大利和西班牙),还有英国国旗。如果单击其中任意一个国旗,您会看到 web 应用程序变成对应的语言。
社会化 web 应用程序
这是社会化媒体的时代,现在的应用程序中通常会添加社会化特性。添加 Talk 视频会很有意义。Roo 提供了嵌入视频上传到 YouTube、Vimeo、Viddler 和 Google Video 等等的支持。要嵌入视频,使用如下命令:
web mvc embed video --provider VIMEO --videoId 16069687
如果您启动服务器并在浏览器中打开应用程序,您将能看到以上嵌入的视频。同样,您可以添加 YouTube 或 Viddler 视频。
Roo 还提供了一个选项,可以在您的应用程序中嵌入 Twitter 消息、文档、股票行情,地图,照片和视频流。各种命令如清单 7。
清单 7. 嵌入命令
web mvc embed document web mvc embed finances web mvc embed map web mvc embed photos web mvc embed stream video web mvc embed twitter web mvc embed video
数据库反向工程
数据库反向工程(DBRE)能让您从内部检查一个现有的数据库并将其公开为应用程序。为了让 DBRE 能用起来,我将用现有的反馈模式创建一个反馈应用程序。我将用 MySQL 数据库。
在启动 Roo 之前,我们将在 MySQL 安装程序中创建一个模式。运行清单 8 中的 SQL 脚本,在 MySQL 数据库中创建一个反馈模式。
清单 8. 创建反馈模式的 SQL 脚本
create database feedback_schema; use feedback_schema; CREATE TABLE feedback ( id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, TalkTitle VARCHAR(45) NOT NULL, SpeakerName VARCHAR(45) NOT NULL, Feedback VARCHAR(4000) NOT NULL, PRIMARY KEY (id) ) ENGINE = InnoDB;
这是一个简单的模式,一个表,没有关系,但 Roo 能成功地对多个表和多个关系的复杂模式进行反向工程。
在运行了以上的 SQL 脚本并生成模式后,创建反馈应用程序:
- 创建名为 feedback 的目录。
- 在操作系统命令行,到达 feedback 目录。
- 通过输入
roo
命令打开 Roo shell。 - 输入
project --topLevelPackage com.dw.roo.feedback
来创建新的 Maven 项目。 - 在此应用程序中,我们将使用 MySQL 作为数据库。要设置应用程序的持久性,用:
persistence setup --provider HIBERNATE --database MYSQL --databaseName feedback_schema --userName root --password password
由于我使用根用户创建模式,我将使用根作为用户名。输入您创建模式的用户名和密码。此命令还会添加持久性所需的所有 JAR。
- 您可以使用
database introspect --schema feedback_schema
来内部检查数据库模式。database introspect
命令显示了与数据库模式相关的元数据。此命令将会在 Roo shell 控制台显示模式的元数据。您还可以使用--file attribute
将元数据 xml 导入文件。 - 完成数据库模式内部检查以后,您可以用
database reverse engineer --schema feedback_schema --package ~.domain
对模式进行反向工程。database reverse engineer
命令有两个参数,schema 和 package,用来指定需要进行反向工程的模式的名称和 Roo 生成资源所在的包。这会在 com.dw.roo.feedback.domain 包中创建所有实体。 - 下一步是生成应用程序的控制器。可以通过运行
controller all --package ~.web
来完成。 - 在运行应用程序之前,需要对 persistence.xml 中的一个属性做点小变动。hibernate.ejb.naming_strategy i属性使用
ImprovedNamingStrategy
,它无法用于 MySQL 数据库,如果运行mvn clean install tomcat:run
将会产生例外。要使它能用,需要将 hiberate.ejb.naming_strategy 改成DefaultNamingStrategy
,如下所示:<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultNamingStrategy"/>
- 现在您可以使用 Now you can run the feedback application using the Maven 命令
mvn clean install tomcat:run
来运行反馈程序。
您可以下载会议和反馈程序的源代码(见下载)。
结束语
至 此,我们已将简单的 CRUD web 应用程序扩展为成熟的企业应用程序。我们演示了添加特性,如 Selenium 测试、Spring Security、国际化支持等,其实很简单。我还演示了如何使用 Spring Roo 数据库反向工程特性根据现有数据库创建应用程序。还有其他很多特性如 JMS、Solr 和 JSON 支持,等等。 Roo 都能方便地添加到您应用程序中。
在第 3 部分中,我将讲述如何将此会议应用系统移植到 Google App Engine。
原文地址:http://www.ibm.com/developerworks/cn/opensource/os-springroo2/
相关推荐
基于万能逼近原理的自适应模糊控制算法在多自由度AUV运动控制中的应用与抗干扰补偿Simulink仿真研究,自适应模糊控制算法的万能逼近原理与多自由度AUV运动控制的抗干扰补偿技术——基于Simulink的仿真研究,万能逼近原理自适应模糊控制算法的多自由度AUV运动控制抗干扰补偿simulink仿真 ,核心关键词:万能逼近原理; 自适应模糊控制算法; 多自由度AUV运动控制; 抗干扰补偿; Simulink仿真。,基于万能逼近的模糊控制算法多自由度AUV抗干扰补偿Simulink仿真
deepseek最新资讯、配置方法、使用技巧,持续更新中
deepseek最新资讯、配置方法、使用技巧,持续更新中
结合扩展卡尔曼滤波与滑模观测器的策略:优化电角度估计,反电势波形逼近完美正弦波,结合扩展卡尔曼滤波与滑模观测器的反电势波形优化:正弦波形展现近乎完美精度,电角度估算与实际应用差异微小,扩展卡尔曼滤波与滑模观测器的结合,反电势波形近乎完美的正弦波形,观测器估算转子电角度与实际电角度相差0.3弧度左右,转速跟随效果较好。 ,核心关键词:扩展卡尔曼滤波; 滑模观测器; 反电势波形; 转子电角度估算; 转速跟随效果。,卡尔曼滑模观测器:优化正弦波转子角度与转速估算
毕业设计_基于springboot+vue的**学生公寓管理系统**【源码+sql+可运行】【**50217**】.zip 全部代码均可运行,亲测可用,尽我所能,为你服务; 1.代码压缩包内容 代码:springboo后端代码+vue前端页面代码; 脚本:数据库SQL脚本 效果图:运行结果请看资源详情效果图 2.环境准备: - JDK1.8+ - maven3.6+ - nodejs14+ - mysql5.6+ - redis 3.技术栈 - 后台:springboot+mybatisPlus+Shiro - 前台:vue+iview+Vuex+Axios - 开发工具: idea、navicate 4.功能列表 - 系统设置:用户管理、角色管理、资源管理、系统日志 - **业务管理:业务管理:公寓信息、房间信息、入住记录、学生信息** 3.运行步骤: 步骤一:修改数据库连接信息(ip、port修改) 步骤二:找到启动类xxxApplication启动 4.若不会,可私信博主!!!
1、文件内容:xorg-x11-server-source-1.20.4-29.el7_9.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/xorg-x11-server-source-1.20.4-29.el7_9.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
1、文件内容:yum-plugin-ps-1.1.31-54.el7_8.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/yum-plugin-ps-1.1.31-54.el7_8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
基于模型预测控制(MPC)的无人船与无人车编队一致性协同控制研究(附原文献),基于模型预测控制(MPC)的无人船与无人车编队一致性协同控制研究(附原文献),无人船编队 无人车编队 MPC 模型预测控制 多智能体协同控制 一致性 MATLAB 无人车 USV 带原文献 ,无人船编队; 无人车编队; MPC 模型预测控制; 多智能体协同控制; 一致性; MATLAB; USV; 原文献,无人系统协同控制:MPC模型预测控制下的多智能体编队与一致性研究(原文献支撑)
4套中级通信工程师综合真题及答案(2019,2020,2021,2023),适用于需要考中级通信工程师的人群
deepseek最新资讯,配置方法,使用技巧,持续更新中
基于matlab的锁相环PLL相位噪声拟合仿真代码集合:多个版本建模与仿真,高质量的锁相环PLL仿真代码集合:Matlab与Simulink建模研究,[1]锁相环 PLL 几个版本的matlab相位噪声拟合仿真代码,质量杠杠的,都是好东西 [2]锁相环matlab建模稳定性仿真,好几个版本 [3]锁相环2.4G小数分频 simulink建模仿真 ,PLL; Matlab相位噪声拟合仿真; Matlab建模稳定性仿真; 锁相环2.4G小数分频Simulink建模仿真,MATLAB仿真系列:锁相环PLL及分频器建模仿真
exceptionLogs.zip
基于光伏微网的经济性与并网负荷波动率双目标优化调度策略:蓄电池与V2G协同管理策略仿真研究,MATLAB下光储充微网结合电动汽车V2G的多目标协同调度策略研究:经济性与并网负荷波动性的对比分析,MATLAB代码:考虑V2G的光储充一体化微网多目标优化调度策略 关键词:光储充微网 电电汽车V2G 多目标优化 蓄电池优化 调度 参考文档:《光伏微网下考虑V2G补偿蓄电池容量的双目标优化调度策略》,已经投稿EI会议,中文说明文档可联系我咨询 仿真平台:MATLAB 平台 优势:代码注释详实,适合参考学习,相关成果已经采用,程序非常精品,请仔细辨识 主要内容:过建立光伏微网中以经济性和并网负荷波动率为双目标的蓄电池和V2G的协同调度模型。 采用粒子群算法,对电网、微网调度中心和电动汽车用户三方在无、无序、转移和调度V2G电动汽车负荷四种运行模式下的经济和安全影响进行对比。 最后,根据算例分析,求解四种模式下两级负荷曲线及经济收益表。 对比分析得出,引入V2G可以替代部分容量的蓄电池,使光伏微网在负荷峰谷平抑、三方经济和安全等方面进一步优化。 求解采用的是PSO算法(粒子群算法),求解效果极
javascript 动态网页设计期末大作业(自己手写的,高分期末作业),含有代码注释,新手也可看懂,个人手打98分项目,导师非常认可的高分项目,毕业设计、期末大作业和课程设计高分必看,下载下来,简单部署,就可以使用。该项目可以直接作为毕设、期末大作业使用,代码都在里面,系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值,项目都经过严格调试,确保可以运行! javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期
混合智能体系统编队控制:分布式优化与15异构混合阶的挑战,异构混合阶智能体系统编队控制的分布式优化策略研究,15异构混合阶多智能体系统编队控制的分布式优化(无参考文献) ,核心关键词:15异构混合阶; 多智能体系统; 编队控制; 分布式优化; 无参考文献。,15混合阶多智能体系统编队分布式优化控制
javascript 动态网页设计期末大作业(自己手写的,很适合期末作业),含有代码注释,新手也可看懂,个人手打98分项目,导师非常认可的高分项目,毕业设计、期末大作业和课程设计高分必看,下载下来,简单部署,就可以使用。该项目可以直接作为毕设、期末大作业使用,代码都在里面,系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值,项目都经过严格调试,确保可以运行! javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascrip
X光安检OPIXray数据集已经转换为VOC格式,可直接转换为为YOLO
DataX--Web:图形化界面简化大数据任务管理_datax-web
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!