Rop重大升级周知

[size=large][color=red]
首先,非常感谢众多网友对Rop所提出的修改建议,你们的建议是我完善Rop框架的源动力!由于这次更改很大,所以我还是在这边发,后面请大家到Rop群组[url]http://rop.group.iteye.com/[/url]中讨论,谢谢合作!

这段时间,对Rop进行了较大的调整和优化,这边出一个较完整的更改日志,说明如下:

[/color]
[b][size=x-large]2012-06-12[/size]
[/b]

[b]1.新增了Rop的Spring Schema命令空间[/b]

可以通过rop命名空间配置Rop,如指定应用错误国际化资源地址、设置自定义的RopValidator,配置FormattingConversionService并添加自定义的转换器、注册拦截器,注册监听器,设置系统级参数的名称等,如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:rop="http://www.rop.com/schema/rop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.rop.com/schema/rop http://www.rop.com/schema/rop/rop-1.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

<!--① 扫描Web类包-->
<context:component-scan base-package="com.rop.sample">
<!-- 假设所有的服务方法都放在rop包下-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!-- 配置一个Rop框架 -->
<rop:annotation-driven
rop-validator="ropValidator"
formatting-conversion-service="conversionService"
ext-error-base-name="i18n/rop/sampleRopError"
sign-enable="true"/>

<!--定义自定义的RopValiator,如appKey及密钥的管理器、会话管理器、服务安全访问管理器等-->
<bean id="ropValidator" class="com.rop.validation.DefaultRopValidator">
<property name="appSecretManager">
<bean class="com.rop.sample.SampleAppSecretManager"/>
</property>
<property name="securityManager">
<bean class="com.rop.sample.SampleSecurityManager"/>
</property>
<property name="sessionChecker">
<bean class="com.rop.sample.SampleSessionChecker"/>
</property>
</bean>

<!--设置自定义的类型转换服务,注册自定义的类型转换器-->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<!--将xxxx-yyyyyyy格式的电话转换为内部的Telephone对象-->
<bean class="com.rop.sample.request.TelephoneConverter"/>
</set>
</property>
</bean>

<!--注册拦截器,可配置多个-->
<rop:interceptors>
<bean class="com.rop.sample.ReservedUserNameInterceptor"/>
</rop:interceptors>

<!--注册监听器,可配置多具-->
<rop:listeners>
<bean class="com.rop.sample.SamplePostInitializeEventListener"/>
<bean class="com.rop.sample.SampleAfterDoServiceEventListener"/>
</rop:listeners>

<!--自定义method,appKey等这些系统级参数的参数名-->
<rop:sysparams format-param-name="messageFormat"/>

</beans>


这个RopServlet就变化很简单,自定义配置性的工作转换到Spring的rop schema中,RopServlet的配置简化为:

<servlet>
<servlet-name>rop</servlet-name>
<servlet-class>
com.rop.RopServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>rop</servlet-name>
<url-pattern>/router</url-pattern>
</servlet-mapping>

原来配置Rop的文件配置也移除了,统一在Spring的rop空间中来做。

[b]2.支持异步调用[/b]

ApiMethob易名为ServiceMethod,该注解添加了多个属性,其中有一个timeout属性,当服务端的服务超过后,会返回相应的错误信息,如下所示:

@ServiceMethod(value = "user.timeout", version = "1.0", timeout = 1)
public RopResponse timeoutService(CreateUserRequest request) throws Throwable {
Thread.sleep(2000);
CreateUserResponse response = new CreateUserResponse();
//add creaet new user here...
response.setCreateTime("20120101010102");
response.setUserId("2");
return response;
}

这儿,我们设定timeoutService()服务方法的过期时间为1,如果过滤,将返回如下的错误报文:
response:<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error solution="Service Currently Unavailable" message="Service Currently Unavailable" code="1">
<subErrors>
<subError message="connect to a remote service timeout Remote connection error" code="isp.remote-service-timeout"/>
</subErrors>
</error>


[b]3.支持服务的多版本[/b]

@ServiceMethod添加了一个version属性,Rop将自动将method和version都匹配的请求路由到相应的服务方法中,如果找不到对应的版本,会报相应的错误,如下所示:

@ServiceMethodBean(value = "group1", title = "组1")
public class UserRestService {

private static final String USER_NAME_RESERVED = "USER_NAME_RESERVED";
private List reservesUserNames = Arrays.asList(new String[]{"tom", "jhon"});

@ServiceMethod(value = "user.add", version = "1.0")//② Let this method service the sample.user.add method
public RopResponse addUser(CreateUserRequest request) {
if (reservesUserNames.contains(request.getUserName())) { //如果注册的用户是预留的帐号,则返回错误的报文

return new ServiceErrorResponse(
request.getRequestContext().getMethod(), USER_NAME_RESERVED,
request.getRequestContext().getLocale(), request.getUserName());
} else {
CreateUserResponse response = new CreateUserResponse();
//add creaet new user here...
response.setCreateTime("20120101010101");
response.setUserId("1");
return response;
}
}

//版本为2.0的user.add
@ServiceMethod(value = "user.add", version = "2.0")
public RopResponse addUser2(CreateUserRequest request) {
if (reservesUserNames.contains(request.getUserName())) { //如果注册的用户是预留的帐号,则返回错误的报文
return new ServiceErrorResponse(
request.getRequestContext().getMethod(), USER_NAME_RESERVED,
request.getRequestContext().getLocale(), request.getUserName());
} else {
CreateUserResponse response = new CreateUserResponse();
//add creaet new user here...
response.setCreateTime("20120101010102");
response.setUserId("2");
return response;
}
}
}

以上服务为user.add定义了两个版本的方法。

[b]4.支持HTTP请求方法限制(目前仅支持GET和POST)[/b]

@ServiceMethod添加了一个httpAction的属性,默认情况下不限定,如果设置后,只有HTTP请求是相应的方法时,才会路由到相应的服务方法中,返回直接驳回请求。如下所示:

@ServiceMethod(value = "user.get", version = "1.0", httpAction = HttpAction.GET)
public RopResponse getUser(CreateUserRequest request) throws Throwable {
String userId = request.getRequestContext().getParamValue("userId");
CreateUserResponse response = new CreateUserResponse();
//add creaet new user here...
response.setCreateTime("20120101010102");
response.setUserId(userId);
response.setFeedback("user.get");
return response;
}


假设使用POST HTTP 方法访问:
    @Test
public void testGetUserWithPOST() {
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("method", "user.get");//<--指定方法名称
form.add("appKey", "00001");
form.add("v", "1.0");
form.add("sessionId", "mockSessionId1");
form.add("locale", "en");
form.add("userName", "tomson");
form.add("salary", "2,500.00");

//对请求参数列表进行签名
String sign = RopUtils.sign(new ArrayList<String>(
form.keySet()), form.toSingleValueMap(), "abcdeabcdeabcdeabcdeabcde");
form.add("sign", sign);

String response = restTemplate.postForObject(
"http://localhost:8088/router", form, String.class);
System.out.println("response:\n" + response);
assertTrue(response.indexOf("code=\"5\"") > -1);
}


将返回如下的错误信息:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error solution="Use the correct HTTP method(GET or POST)" message="Http Action Not Allowed" code="5"/>


[b]5.添加事件体系[/b]

支持Rop框架启动后,关闭前的事件,每个服务处理前处理后的事件;
以下是一个监听Rop框架初始化后事件的监听器:

public class SamplePostInitializeEventListener implements RopEventListener<AfterStartedRopEvent> {

@Override
public void onRopEvent(AfterStartedRopEvent ropRopEvent) {
System.out.println("execute SamplePostInitializeEventListener!");
}

@Override
public int getOrder() {
return 0; //To change body of implemented methods use File | Settings | File Templates.
}
}


要使事件启用,必须在Spring中配置好:

<rop:listeners>
<bean class="com.rop.sample.SamplePostInitializeEventListener"/>
</rop:listeners>


[b]6.添加拦截器支持[/b]

可以对每个服务调用进行拦截,如果在拦截器中往RequestContext中设置RopResponse了,将阻止业务执行,直接返回,否则继续执行服务:

下面的拦截器,对user.add的方法进行拦截,并发现userName为jhonson(相当于说这是预留的用户名,不能添加这个用户)时,驳回请求,返回相应的错误报文:


package com.rop.sample;

import com.rop.AbstractInterceptor;
import com.rop.RequestContext;
import com.rop.sample.response.InterceptorResponse;
import org.springframework.stereotype.Component;

/**
* <pre>
* 该拦截器仅对method为“user.add”进行拦截,你可以在{@link #isMatch(com.rop.RequestContext)}方法中定义拦截器的匹配规则。
* 你可以通过{@link com.rop.RequestContext#getServiceMethodDefinition()}获取服务方法的注解信息,通过这些信息进行拦截匹配规则
* 定义。
* </pre>
*
* @version 1.0
*/

@Component
public class ReservedUserNameInterceptor extends AbstractInterceptor {

/**
* 在数据绑定后,服务方法调用前执行该拦截方法
* @param methodContext
*/
@Override
public void beforeService(RequestContext methodContext) {
System.out.println("beforeService ...");

if ("jhonson".equals(methodContext.getParamValue("userName"))) {
InterceptorResponse response = new InterceptorResponse();
response.setTestField("the userName can't be jhonson!");
//设置了RopResponse后,后续的服务将不执行,直接返回这个RopResponse响应
methodContext.setRopResponse(response);
}
}

/**
* 在服务执行完成后,响应返回前执行该拦截方法
* @param methodContext
*/
@Override
public void beforeResponse(RequestContext methodContext) {
System.out.println("beforeResponse ...");
}

/**
* 对method为user.add的方法进行拦截,你可以通过methodContext中的信息制定拦截方案
* @param methodContext
* @return
*/
@Override
public boolean isMatch(RequestContext methodContext) {
return "user.add".equals(methodContext.getMethod());
}
}



这样,将执行下面的测试时将返回由拦截器生产的响应报文:
    /**
* 测试被拦截器阻截服务的情况 (user.add + 1.0)
*/
@Test
public void testAddUserWithInterceptorViolidateReservedUserName() {
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("method", "user.add");//<--指定方法名称
form.add("appKey", "00001");
form.add("v", "2.0");
form.add("sessionId", "mockSessionId1");
form.add("locale", "en");
form.add("userName", "jhonson");//这个用户名会被ReservedUserNameInterceptor拦截器驳回
form.add("salary", "2,500.00");

//对请求参数列表进行签名
String sign = RopUtils.sign(new ArrayList<String>(
form.keySet()), form.toSingleValueMap(), "abcdeabcdeabcdeabcdeabcde");
form.add("sign", sign);

String response = restTemplate.postForObject(
"http://localhost:8088/router", form, String.class);
System.out.println("response:\n" + response);
assertTrue(response.indexOf("the userName can't be jhonson!") > -1);
}


返回如下报文:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<createUserResponse testField="the userName can't be jhonson!"/>



[b]7.可以将XML及JSON的请求数据绑定到请求对象中[/b]

如果需要使用XML请求数据,则format必须设置成xml,如果需要使用json,则format必须设置成json.

以下是一个带XML的请求:
    @Test
public void testServiceXmlRequestAttr() {
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("method", "user.add");//<--指定方法名称
form.add("appKey", "00001");
form.add("v", "1.0");
form.add("sessionId", "mockSessionId1");
form.add("userName", "tomson");
form.add("salary", "2,500.00");

//address会正确绑定
form.add("address",
"<address zoneCode=\"0001\" doorCode=\"002\">\n" +
" <streets>\n" +
" <street no=\"001\" name=\"street1\"/>\n" +
" <street no=\"002\" name=\"street2\"/>\n" +
" </streets>\n" +
"</address>");

//对请求参数列表进行签名
String sign = RopUtils.sign(new ArrayList<String>(
form.keySet()), form.toSingleValueMap(), "abcdeabcdeabcdeabcdeabcde");
form.add("sign", sign);

String response = restTemplate.postForObject(
"http://localhost:8088/router", form, String.class);
System.out.println("response:\n" + response);
assertTrue(response.indexOf("<createUserResponse createTime=\"20120101010101\" userId=\"1\">") > -1);
}


来看一下服务端的

public class CreateUserRequest extends AbstractRopRequest {

@Pattern(regexp = "\\w{4,30}")
private String userName;

@IgnoreSign
@Pattern(regexp = "\\w{6,30}")
private String password;

@DecimalMin("1000.00")
@DecimalMax("100000.00")
@NumberFormat(pattern = "#,###.##")
private long salary;

@Valid
private Address address;//这个属性对象用于接受address请求参数的XML内容
...
}

来看一下Address的代码:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "address")
public class Address {

@XmlAttribute
@Pattern(regexp = "\\w{4,30}")
private String zoneCode;

@XmlAttribute
private String doorCode;


@XmlElementWrapper(name = "streets")
@XmlElement(name = "street")
private List<Street> streets;
...
}

即也是采用和RopResponse一样的JAXB注解就可以了。

[b]8.RopRequest和RopResponse都接口化[/b]

1)原来的RopRequest是一个类,系统级参数放在这个类中,现在移到RequestContext接口中,可以通过RopRequest#getRequestContext()访问这些系统级参数;
2)RequestContext对应每一个请求,它还包括以下接口方法:

//获取本次服务对应服务方法处的ServiceMethod注解的信息;
ServiceMethodDefinition getServiceMethodDefinition();

//对应本次请求服务客户端传过来的所有参数列表
Map<String, String> getAllParams();

//可以获取客户端传过来的某个参数值
String getParamValue(String paramName);

//获取原始的请求对象(目前都为HttpServletRequest对象)
Object getRawRequestObject();

有了这个抽象,如果你的业务请求参数不需要合法性校验且数量很少,那么你就不要再为请求数据定义一个专门的请求类了,直接使用RopRequest作为服务方法的入参就可以了,如下所示:

//直接使用RopRequest对象作为入参
@ServiceMethod(value = "user.query", version = "1.0", httpAction = HttpAction.GET)
public RopResponse queryUsers(RopRequest request) throws Throwable {

//直接从参数列表中获取参数值
String userId = request.getRequestContext().getParamValue("userId");
CreateUserResponse response = new CreateUserResponse();
response.setCreateTime("20120101010102");
response.setUserId(userId);
response.setFeedback("user.query");
return response;
}


[b]8.ServiceMethodBean[/b]

可以在服务类上打上这个注解就可以将其变成一个Bean了,此外它拥有和@Servicemethod类似的属性,如果一个服务类有拥有多个服务方法,这些服务方法都拥有一些相同的属性(如组名,TAG名等),那么可以在ServiceMethodBean中定义,方法处的@Servicemethod 将覆盖类处ServiceMethodBean的定义。
@ServiceMethodBean(value = "group1", title = "组1")
public class UserRestService {

@ServiceMethod(value = "user.add", version = "1.0")
public RopResponse addUser(CreateUserRequest request) {
...
}

//版本为2.0的user.add
@ServiceMethod(value = "user.add", version = "2.0")
public RopResponse addUser2(CreateUserRequest request) {
...
}
}


ServiceMethod比ServiceMethodBean多了方法名的属性,其它的属性ServiceMethodBean都有:
[list]
[*]value:组名,对应ServiceMethod的group
[*]title:组标识,对应ServiceMethod的groupTile
[*]TAG:tags
[*]timeout:过期时间,单位为秒
[*]httpAction:HTTP请求方法(GET,POST)
[*]needInSession:服务方法是否要工作于会话环境下(有些方法不需要会话,如获取软件的最新版本等),默认服务方法工作于会话环境下,如果没有会话将报错
[*]ignoreSign:方法是否要忽略签名,有些方法无需签名校验,默认要签名
[*]version:服务方法的版本号,如果你将不同版本的服务方法定义在不同类中,这个很有用
[/list]
组、tags有什么用途呢?
它们可以访问你定义拦截器的拦截过滤规则,如果你的一个拦截器仅希望拦截每些服务方法,那么在制定拦截器的isMatch方法时,使用这些信息将非常方便。如下所示:

public boolean isMatch(RequestContext methodContext) {
if("group1".equals(methodContext.getServiceMethodDefinition().getMethodGroup())){
//do sth
}
}


[b]9.请求数据签名的校验的启用和关闭[/b]

有些服务方法不需要签名校验,则可以方便地通过

@ServiceMethod(value = "service.method1",
ignoreSign = IgnoreSignType.NO)
public RopResponse service1() {
return new RopResponse() {
};
}

你也可以使整个Rop框架不启动签名校验(一般用于测试时使用):

<rop:annotation-driven sign-enable="false"/>

这样它就会忽略服务方法处的设置,整体不启用签名校验了。

此外,如果你希望对某个服务方法的某些请求数据不签名(如图片数据这种),那么可以在请求对象类定义处使用@IgnoreSign,如下所示:

public class CreateUserRequest extends AbstractRopRequest {

@Pattern(regexp = "\\w{4,30}")
private String userName;

@IgnoreSign
@Pattern(regexp = "\\w{6,30}")
private String password;

@DecimalMin("1000.00")
@DecimalMax("100000.00")
@NumberFormat(pattern = "#,###.##")
private long salary;

@Valid
private Address address;

private String format;

private Telephone telephone;
}

这样,remark的请求参数就会忽略掉签名而仅对其它请求参数实施签名校验了(也即客户端在签名时不要将remark添加到SHA1(<secret><paramName><paramValue><secret>)的参数列表中进行签名了),客户端的调用如下所示:

@Test
public void testIngoreSignParamOfPassword() {
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("method", "user.add");//<--指定方法名称
form.add("appKey", "00001");
form.add("v", "1.0");
form.add("sessionId", "mockSessionId1");
form.add("userName", "tomsony");
form.add("salary", "2,500.00");
String sign = RopUtils.sign(new ArrayList<String>(
form.keySet()), form.toSingleValueMap(), "abcdeabcdeabcdeabcdeabcde");

form.add("sign", sign);
form.add("password", "123456"); //password无需签名,所以放在最后

String response = restTemplate.postForObject(
"http://localhost:8088/router", form, String.class);
System.out.println("response:\n" + response);
assertTrue(response.indexOf("<createUserResponse createTime=\"20120101010101\" userId=\"1\">") > -1);
}


[b]10.服务方法不工作在会话环境下[/b]

有些方法在不需要会话的时候也能访问,如下载一张图片,检查软件的最新版本等服务,这时可以通过@ServiceMethod的needInSession来设置:
    //版本为4.0的user.add:不需要会话
@ServiceMethod(value = "user.add", version = "4.0",needInSession = NeedInSessionType.NO)
public RopResponse addUser4(CreateUserRequest request) {
CreateUserResponse response = new CreateUserResponse();
//add creaet new user here...
response.setCreateTime("20120101010102");
response.setUserId("4");
return response;
}


以下测试方法在不提供sessionId系统级参数的情况下调用该服务方法:
   @Test
public void testIngoreSession() {
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
form.add("appKey", "00001");
form.add("method", "user.add");//<--指定方法名称
form.add("v", "4.0");
form.add("userName", "tomsony");
form.add("salary", "2,500.00");
String sign = RopUtils.sign(new ArrayList<String>(
form.keySet()), form.toSingleValueMap(), "abcdeabcdeabcdeabcdeabcde");

form.add("sign", sign);

String response = restTemplate.postForObject(
"http://localhost:8088/router", form, String.class);
System.out.println("response:\n" + response);
assertTrue(response.indexOf("userId=\"4\"") > -1);
}
Rop开发手册 详细的Rop开发及应用,有示例和代码讲述 立即下载

相关推荐

rop demo完整用例

本文是借助maven搭建的一个rop框架,以及一个简单的测试用例,供大家学习分享。如果发现不对的地方,希望大家留言提出,

Rop开发手册(3):最简单的服务开放平台框架

:D [quote]Rop项目文档前后写了一个多月,在写的过程中发现很多功能不完善的,又回过头了改项目,此种反复多次,现在Rop开源项目的文档已经差不多了,将陆续在iteye此发出,希望对大家有帮助。在Rop项目的开发过程中得到了众多iteye网友的有力帮助,收到了很多很好的整改的意见,在此对他们的奉献和帮助表示诚挚的感谢,这些网友包括但不限于: [url=http://melin.iteye...

stamen的程序员之路 309

快速框架ropv1.0

ropv1.0,快速组建如淘宝开放api接口类的框架,实现appKey/secrett管理

Rop开发手册(4):最简单的服务开放平台框架

[b][size=x-large]会话管理概述[/size][/b] 一个客户端应用开发出来后,可以有很多具体的使用者。Rop使用应用键/密钥可以定位到一个具体的客户端应用,但却无法定位到客户端应用当前的使用者。服务开放平台必须开放一个用户登录的服务,在登录成功后分配一个sessionId。这样,应用用户后续对服务平台的服务调用都附上这个sessionId,服务端就可根据这个session...

stamen的程序员之路 317

高效打卡系统设计:从行为心理学到实践工具

打卡系统作为现代时间管理的重要工具,其核心原理植根于行为心理学中的即时反馈机制和习惯养成理论。通过科学设计的打卡周期和可视化反馈,能有效提升个人自律性和目标达成率。在技术实现上,从纸质记录到数字化工具(如Notion、Excel自动化模板)的演进,为不同场景提供了灵活解决方案。特别在习惯追踪和进度管理领域,结合热力图生成、数据统计等技巧,打卡系统能转化为强大的自我监督工具。本文通过实践案例,详解如何构建兼顾弹性和约束力的个性化打卡方案,帮助读者突破'三天打鱼两天晒网'的常见困境。

weixin_30047059的博客 337

从零开始:用Python搭建你的第一个加密货币量化交易机器人(附完整代码)

本文详细介绍了如何使用Python从零开始搭建一个加密货币量化交易机器人,涵盖环境准备、交易所API连接、基础交易策略实现、回测系统构建以及实盘部署等关键步骤。通过完整的代码示例,帮助读者快速掌握数字货币量化交易的核心技术,适合有一定编程基础的投资者入门。

weixin_30415113的博客 465

Rop开发手册(1):最简单的服务开放平台框架

[b][size=x-large] Rop概述[/size][/b] Rop是Rapid Open Platform的简称,它不同于一般纯技术型的Web Service框架(如CXF,Jersey等),Rop致力于构建开放服务平台的框架,您可以使用Rop开发类似于淘宝开放服务平台这样的服务平台。Rop充分借鉴了当前大型网站的开放服务平台的设计思路,汲取了它们成功的实践经验,对开放服务平台的很...

stamen的程序员之路 663

AISHELL-2 中文语音数据库

AISHELL-1 is by far the largest open-source speech corpus available for Mandarin speech recognition research. It was released with a baseline system containing solid training and testing pipelines for Mandarin ASR. In AISHELL-2, 1000 hours of cle

AI_SHELL的博客 7888

rop入门(二)

一: 上一篇讲解了一下什么是rop以及如何搭建rop框架,本章节讲解,如何使用rop进行服务的调用以及参数的传递 同springMvc相似 rop也是通过在web.xml中配置拦截来声明该url链接启用rop框架。至于如何调用controller层内的方法,rop有专门的参数用来指定,这个下边会讲到。示例: web.xml <!-- rop servlet --> <servle

李永亮的专栏 9943

在VM虚拟机的MobaXterm下安装JDK17

本文介绍了在Linux系统下安装配置JDK17的完整步骤:1)从Oracle或OpenJDK官网下载Linux版JDK17压缩包;2)上传至/usr/local目录;3)解压安装包;4)通过编辑/etc/profile文件配置环境变量,添加JAVA_HOME和PATH路径;5)使用source命令使配置生效;6)通过javac -version验证安装是否成功。整个过程涵盖了从下载到环境配置的完整流程,确保Java开发环境正确设置。

qq_2937655951的博客 442

ANSYS_APDL实战入门——从零开始掌握模态分析

本文为ANSYS APDL模态分析实战入门指南,通过一个悬臂梁案例,手把手教你从零开始掌握APDL命令流。内容涵盖从模型创建、材料定义、网格划分到边界条件设置、求解及后处理结果查看的全流程,帮助工程师快速上手结构动力学分析,避免共振风险。

egg99的博客 1129

Rop开发手册(2):最简单的服务开放平台框架

:D [quote]Rop项目文档前后写了一个多月,在写的过程中发现很多功能不完善的,又回过头了改项目,此种反复多次,现在Rop开源项目的文档已经差不多了,将陆续在iteye此发出,希望对大家有帮助。在Rop项目的开发过程中得到了众多iteye网友的有力帮助,收到了很多很好的整改的意见,在此对他们的奉献和帮助表示诚挚的感谢,这些网友包括但不限于: [url=http://melin.iteye...

stamen的程序员之路 476

西南交通大学车辆工程专业大四上车辆综合实训ame仿真部分

西南交通大学车辆工程专业大四上车辆综合实训ame仿真建模部分

qq_64814052的博客 1245

N、A两家中端底牌尽出,RX 9070系列性能解禁出炉

在代表 DX 12 环境 2K 分辨率 Time Spy 1.2 测试中结果类似,RX 9070 XT 得分 29596,领先领先上代 RX 7900 GRE 31%,与对手 RTX 5070 Ti 相比则实现反超,领先 6%。不难看出,在代表 GPU 最核心的流处理器、CU 单元、RT 核心、ROPs 单元等关键参数上,RX 9070 XT 对比上代 7900 GRE 都明显缩水,只能略微领先次一级的 RX 7800 XT。

meiyimin的专栏 1051

【Bug已解决】codex file edit fails / Write operation denied — CodeX CLI 文件编辑失败解决方案

CodeX CLI 编辑文件时报写入被拒绝,本质是沙箱限制或权限不足。文中给出配置允许目录、修复权限、Git stash 管理冲突等完整方案。

一键难忘的博客 4300

C#里使用NModbus来创建一个TCP从站服务

摘要:本文介绍了一个用C#实现的Modbus TCP从站服务器,基于.NET Framework 4.6.1开发。代码使用NModbus库创建TcpListener和ModbusSlaveNetwork,支持设置IP地址、端口号和从站ID。服务器实现了数据存储初始化功能(包括线圈和保持寄存器),并提供了启动/停止操作的UI界面和日志记录功能。该解决方案适用于需要调试Modbus TCP协议的场景,特别适合无法升级到更高版本.NET Framework的环境。

大坡3D软件开发 477

Pwn2Own 2017 Linux 内核提权漏洞分析

https://zhuanlan.zhihu.com/p/26674557 0.前言 在2017年PWN2OWN大赛中,长亭安全研究实验室(Chaitin Security Research Lab)成功演示了Ubuntu 16.10 Desktop的本地提权。本次攻击主要利用了linux内核IPSEC框架(自linux2.6开始支持)中的一个内存越界漏洞,CVE编号为CVE-2017-718...

子曰小玖的博客 757

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

rop入门(一)

简介: rop不同于一般的技术性框架,主要用于构建服务放开平台,您可以使用 Rop 开发类似于淘宝服务开放平台这样的服务平台 Rop 功能 架构 CXF 和 Jersey 是纯技术纯的 Web Service 框架,而在 Rop 中,Web Service 只是核心, 它提供了开发服务平台的诸多领域问题的解决方案:如应用认证、会话管理、安全控制、 错误模型、版本管理、超时限制等。 下面

李永亮的专栏 4918

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Rop快速入门(1)

1.什么是rop:                        rop是rapid open platform (快速开放平台)的缩写,常见的rop框架就是淘宝的开放平台,随着互联网发展的升温,越来越多的公司选择搭建属于自己公司的开放平台,微信开放平台,微博开放平台...... 2.rop的整体框架:                              rop的重点在应用层,无论

分开_旅行的博客 1359

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

rop学习(三)

rop

李永亮的专栏 4445

Rop开发手册(6):最简单的服务开放平台框架

:D [quote] Rop,即Rapid Open Platform,是一个参考淘宝开放平台(TOP Taobao Open Platform)的平台设计思路,充分借鉴Spring MVC的技术架构原理开发的一个快速服务开放平台开源框架项目,可以让您迅速构建成熟的SOA服务平台。它不同于传统的SOAP Web Service和Rest Web Service这些Web Service 技术型...

stamen的程序员之路 546

Rop特性及新功能(最简单的Rest Web Service框架)

Rop是参照淘宝开发平台(TOP:Taobal Open Platform)实现的全功能Rest Web Service 全功能(Full-Stack)开源框架。它解决了以下的Web Service开发问题:   1.契约优先,URL完全Rest风格    Rop(Rest Open Platfrom)是“契约优先”的Rest URL的Web Service框架,主URL固定,通过me

wangjian223344的专栏 2025

Rop开发手册(5):最简单的服务开放平台框架

:D [quote] Rop,即Rapid Open Platform,是一个参考淘宝开放平台(TOP Taobao Open Platform)的平台设计思路,充分借鉴Spring MVC的技术架构原理开发的一个快速服务开放平台开源框架项目,可以让您迅速构建成熟的SOA服务平台。它不同于传统的SOAP Web Service和Rest Web Service这些Web Service 技术型...

stamen的程序员之路 457
上一篇: HMAC简介
下一篇: Maven实战(六)——Gradle,构建工具的未来?
quickselect
博客等级 码龄20年 1粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值