新闻详细
新闻当前位置:新闻详细

java怎么重新编译整个项目内容的内容,怎么重新编辑一个已经打包好的java程序?昨天下载了一个java的程序...

专业互联网培训机构——完成蜕变以后轻松拿高薪

电话+V: 152079-09430 ,欢迎咨询java怎么重新编译整个项目内容的内容,[python实用课程],[C++单片机原理],[C#、PHP网站搭建],[Nodejs小程序开发],[ios游戏开发],[安卓游戏开发],[教会用大脑用想法赚钱实现阶层跨越]

一、java怎么重新编译整个项目内容的内容

以下是关于如何在Java中重新编译整个项目的重点:

1.首先,确保你的计算机上已经正确安装了Java开发工具包(JDK)和集成开发环境(IDE),比如Eclipse或IntelliJIDEA。

2.打开你选择的IDE,导入项目文件。这通常可以通过在IDE的文件菜单中选择"导入"并找到项目的根目录来完成。

3.确保项目的所有源文件都被正确地组织在项目的源代码文件夹中,通常是名为"src"或"src/main/java"的文件夹。

4.如果项目中包含了其他依赖库或模块,确保它们已经被正确添加到项目的构建路径中。这可以通过在IDE的项目设置或构建配置中添加相应的依赖项来完成。

5.一旦项目被成功导入并配置好,你可以在IDE中找到构建或编译选项。这通常位于项目菜单或工具栏中。

6.选择构建或编译选项后,IDE将自动检测项目的依赖关系,并开始编译所有的源文件。这个过程可能需要一些时间,具体取决于项目的大小和复杂性。

7.在编译过程中,IDE将检查源代码中的错误和警告,并在需要时提供相应的提示和建议。你可以根据需要修复这些错误或忽略警告。

8.一旦编译完成,你将在项目的输出目录(通常是"bin"或"out"文件夹)中找到编译后的字节码文件(.class文件)。

9.现在,你已经成功地重新编译了整个Java项目,并且可以在IDE中运行、调试或部署它。

二、怎么重新编辑一个已经打包好的java程序?昨天下载了一个java的程序...

如果没有源码,一般来说不是很把握。以下方法是针对更改一个文件的。

  1. 需要反编辑工具。

  2. 在eclipse中创建一个java工程。

  3. 在工程中引入你下载的jar

  4. 用rar打开jar文件,取出你想更改的class文件。反编辑为java文件

  5. 将反编译的java文件放入工程中,并将所需要的地方修改。

  6. 到对应的工程目录中的bin目录也,找到新编译的class文件。

  7. 用rar工具将新编译的class替换jar文件中的class文件。


如果你需要更改的文件比较多,还是找一下源码工程。

上述方法。也有可能因为反编译的不完全而不成功。

Java面向容错编程之重试机制

阿里技术

2024-01-1008:30发布于浙江阿里技术官方账号

+关注

阿里妹导读


容错编程是一种重要的编程思想,它能够提高应用程序的可靠性和稳定性,同时提高代码的健壮性。本文总结了一些作者在面对服务失败时如何进行优雅重试,比如aop、cglib等同时对重试工具\\组件的源码和注意事项进行总结分析。容错编程是一种旨在确保应用程序的可靠性和稳定性的编程思想,它采取以下措施:1.异常处理:通过捕获和处理异常来避免应用程序崩溃。

2.错误处理:通过检查错误代码并采取适当的措施,如重试或回滚,来处理错误。

3.重试机制:在出现错误时,尝试重新执行代码块,直到成功或达到最大尝试次数。

4.备份机制:在主要系统出现故障时,切换到备用系统以保持应用程序的正常运行。

5.日志记录:记录错误和异常信息以便后续排查问题。容错编程是一种重要的编程思想,它能够提高应用程序的可靠性和稳定性,同时提高代码的健壮性。

一、为什么需要重试

在做业务技术时,设计具备可复用、可扩展、可编排的系统架构至关重要,它直接决定着业务需求迭代的效率。但同时业务技术人员也应具备悲观思维:在分布式环境下因单点问题导致的HSF服务瞬时抖动并不少见,比如系统瞬时抖动、单点故障、服务超时、服务异常、中间件抖动、网络超时、配置错误等等各种软硬件问题。如果直接忽略掉这些异常则会降低服务的健壮性,严重时会影响用户体验、引起用户投诉,甚至导致系统故障。因此在做方案设计和技术实现时要充分考虑各种失败场景,针对性地做防御性编程。我们在调用第三方接口时,经常会遇到失败的情况,针对这些情况,我们通常会处理失败重试和失败落库逻辑。然而,重试并不是适用于所有场景的,例如参数校验不合法、读写操作是否适合重试,数据是否幂等。远程调用超时或网络突然中断则可以进行重试。我们可以设置多次重试来提高调用成功的概率。为了方便后续排查问题和统计失败率,我们也可以将失败次数和是否成功记录落库,便于统计和定时任务兜底重试。培训研发组在大本营、培训业务、本地e站等多业务对各种失败场景做了充分演练,并对其中一些核心流程做了各种形式的失败重试处理,比如骑手考试提交、同步数据到洞察平台、获取量子平台圈人标签等。本文总结了一些我们在面对服务失败时如何进行优雅重试,比如aop、cglib等同时对重试工具\\组件的源码和注意事项进行总结分析。

二、如何重试


2.1简单重试方法

测试demo@TestpublicIntegersampleRetry(intcode){System.out.println("sampleRetry,时间:"+LocalTime.now());inttimes=0;while(times<MAX_TIMES){try{postCommentsService.retryableTest(code);}catch(Exceptione){times++;System.out.println("重试次数"+times);if(times>=MAX_TIMES){//记录落库,后续定时任务兜底重试//dosomethingrecord...thrownewRuntimeException(e);}}}System.out.println("sampleRetry,返回!");returnnull;}

2.2动态代理模式版本

在某些情况下,一个对象不适合或不能直接引用另一个对象,这时我们可以使用代理对象来起到中介作用,它可以在客户端和目标对象之间进行通信。使用代理对象的好处在于,它兼容性比较好,每个重试方法都可以调用。
使用方式

publicclassDynamicProxyTestimplementsInvocationHandler{privatefinalObjectsubject;publicDynamicProxy(Objectsubject){this.subject=subject;}
/***获取动态代理**@paramrealSubject代理对象*/publicstaticObjectgetProxy(ObjectrealSubject){//我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的InvocationHandlerhandler=newDynamicProxy(realSubject);returnProxy.newProxyInstance(handler.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),handler);}
@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{inttimes=0;while(times<MAX_TIMES){try{//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用returnmethod.invoke(subject,args);}catch(Exceptione){times++;System.out.println("重试次数"+times);if(times>=MAX_TIMES){//记录落库,后续定时任务兜底重试//dosomethingrecord...thrownewRuntimeException(e);}}}
returnnull;}}
测试demo

@TestpublicIntegerV2Retry(intcode){RetryableTestServiceImplrealService=newRetryableTestServiceImpl();RetryableTesterviceImplproxyService=(RetryableTestServiceImpl)DynamicProxyTest.getProxy(realService);proxyService.retryableTest(code);}

2.3字节码技术生成代理重试

CGLIB是一种代码生成库,它能够扩展Java类并在运行时实现接口。它具有功能强大、高性能和高质量的特点。使用CGLIB可以生成子类来代理目标对象,从而在不改变原始类的情况下,实现对其进行扩展和增强。这种技术被广泛应用于AOP框架、ORM框架、缓存框架以及其他许多Java应用程序中。CGLIB通过生成字节码来创建代理类,具有较高的性能。
使用方式

publicclassCglibProxyTestimplementsMethodInterceptor{
@OverridepublicObjectintercept(Objecto,Methodmethod,Object[]objects,MethodProxymethodProxy)throwsThrowable{inttimes=0;while(times<MAX_TIMES){try{//通过代理子类调用父类的方法returnmethodProxy.invokeSuper(o,objects);}catch(Exceptione){times++;
if(times>=MAX_TIMES){thrownewRuntimeException(e);}}}returnnull;}
/***获取代理类*@paramclazz类信息*@return代理类结果*/publicObjectgetProxy(Classclazz){Enhancerenhancer=newEnhancer();//目标对象类enhancer.setSuperclass(clazz);enhancer.setCallback(this);//通过字节码技术创建目标对象类的子类实例作为代理returnenhancer.create();}
}

测试demo

@TestpublicIntegerCglibRetry(intcode){RetryableTestServiceImplproxyService=(RetryableTestServiceImpl)newCglibProxyTest().getProxy(RetryableTestServiceImpl.class);proxyService.retryableTest(code);}

2.4HSF调用超时重试

在我们日常开发中,调用第三方HSF服务时出现瞬时抖动是很常见的。为了降低调用超时对业务造成的影响,我们可以根据业务特性和下游服务特性,使用HSF同步重试的方式。如果使用的框架没有特别设置,HSF接口超时默认不会进行自动重试。在注解@HSFConsumer中,有一个参数retries,通过它可以设置失败重试的次数。默认情况下,这个参数的值默认是0。??

@HSFConsumer(serviceVersion="1.0.0",serviceGroup="hsf",clientTimeout=2000,methodSpecials={@ConsumerMethodSpecial(methodName="methodA",clientTimeout="100",retries="2"),@ConsumerMethodSpecial(methodName="methodB",clientTimeout="200",retries="1")})privateXxxHSFServicexxxHSFServiceConsumer;HSFConsumer超时重试原理一次HSF的服务调用过程示意图:

?

HSF超时重试发生在AsyncToSyncInvocationHandler#invokeType(.):如果配置的retries参数大于0则使用retry()方法进行重试,且重试只发生在TimeoutException异常的情况下。源码分析privateRPCResultinvokeType(Invocationinvocation,InvocationHandlerinvocationHandler)throwsThrowable{finalConsumerMethodModelconsumerMethodModel=invocation.getClientInvocationContext().getMethodModel();StringmethodName=consumerMethodModel.getMethodName(invocation.getHsfRequest());
finalInvokeModeinvokeType=getInvokeType(consumerMethodModel.getMetadata(),methodName);invocation.setInvokeType(invokeType);
ListenableFuture<RPCResult>future=invocationHandler.invoke(invocation);
if(InvokeMode.SYNC==invokeType){if(invocation.getBroadcastFutures()!=nullinvocation.getBroadcastFutures().size()>1){//broadcastreturnbroadcast(invocation,future);}elseif(consumerMethodModel.getExecuteTimes()>1){//retryreturnretry(invocation,invocationHandler,future,consumerMethodModel.getExecuteTimes());}else{//normalreturngetRPCResult(invocation,future);}}else{//pseudoresponse,shouldbeignoredHSFRequestrequest=invocation.getHsfRequest();ObjectappResponse=null;if(request.getReturnClass()!=null){appResponse=ReflectUtils.defaultReturn(request.getReturnClass());}HSFResponsehsfResponse=newHSFResponse();hsfResponse.setAppResponse(appResponse);
RPCResultrpcResult=newRPCResult();rpcResult.setHsfResponse(hsfResponse);returnrpcResult;}}从上面这段代码可以看出,retry重试只有发生在同步调用当中。消费者方法的元数据的执行次数大于1(consumerMethodModel.getExecuteTimes()>1)时会走到retry方法去尝试重试:privateRPCResultretry(Invocationinvocation,InvocationHandlerinvocationHandler,ListenableFuture<RPCResult>future,intexecuteTimes)throwsThrowable{
intretryTime=0;
while(true){retryTime++;if(retryTime>1){future=invocationHandler.invoke(invocation);}
inttimeout=-1;try{timeout=(int)invocation.getInvokerContext().getTimeout();RPCResultrpcResult=future.get(timeout,TimeUnit.MILLISECONDS);
returnrpcResult;}catch(ExecutionExceptione){thrownewHSFTimeOutException(getErrorLog(e.getMessage()),e);}catch(TimeoutExceptione){//retryonlywhentimeoutif(retryTime<executeTimes){continue;}else{thrownewHSFTimeOutException(getErrorLog(e.getMessage()),timeout+"",e);}}catch(Throwablee){thrownewHSFException("",e);}}}HSFConsumer超时重试原理利用的是简单的while循环+try-catch?缺陷:1、只有方法被同步调用时候才会发生重试。

2、只有hsf接口出现TimeoutException才会调用重试方法。

3、如果为某个HSFConsumer中的method设置了retries参数,当方法返回时出现超时异常,HSFSDK会自动重试。重试实现的方式是一个while+try-catch循环。所以,如果自动重试的接口变得缓慢,而且重试次数设置得过大,会导致RT变长,极端情况下还可能导致HSF线程池被打满。因此,HSF的自动重试特性是一个基础、简单的能力,不推荐大面积使用。

2.5SpringRetry

SpringRetry是Spring系列中的一个子项目,它提供了声明式的重试支持,可以帮助我们以标准化的方式处理任何特定操作的重试。这个框架非常适合于需要进行重试的业务场景,比如网络请求、数据库访问等。使用SpringRetry,我们可以使用注解来设置重试策略,而不需要编写冗长的代码。所有的配置都是基于注解的,这使得使用SpringRetry变得非常简单和直观。POM依赖<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId></dependency>启用@Retryable引入spring-retryjar包后在springboot的启动类上打上@EnableRetry注解。@EnableRetry@SpringBootApplication(scanBasePackages={"me.ele.camp"},excludeName={"me.ele.oc.orm.OcOrmAutoConfiguraion"})@ImportResource({"classpath*:sentinel-tracer.xml"})publicclassApplication{
publicstaticvoidmain(String[]args){System.setProperty("APPID","alsc-info-local-camp");System.setProperty("project.name","alsc-info-local-camp");}service实现类添加@Retryable注解@Override@Retryable(value=BizException.class,maxAttempts=6)publicIntegerretryableTest(Integercode){System.out.println("retryableTest,时间:"+LocalTime.now());if(code==0){thrownewBizException("异常","异常");}BaseResponse<Object>objectBaseResponse=ResponseHandler.serviceFailure(ResponseErrorEnum.UPDATE_COMMENT_FAILURE);
System.out.println("retryableTest,正确!");return200;}

@RecoverpublicIntegerrecover(BizExceptione){System.out.println("回调方法执行!!!!");//记日志到数据库或者调用其余的方法return404;};可以看到代码里面,实现方法上面加上了注解@Retryable,@Retryable有以下参数可以配置:

value抛出指定异常才会重试;include和value一样,默认为空,当exclude也为空时,默认所有异常;exclude指定不处理的异常;maxAttempts最大重试次数,默认3次;backoff重试等待策略,默认使用@Backoff,@Backoff的value默认为1000(单位毫秒);multiplier指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒;

Spring-Retry还提供了@Recover注解,用于@Retryable重试失败后处理方法。如果不需要回调方法,可以直接不写回调方法,那么实现的效果是,重试次数完了后,如果还是没成功没符合业务判断,就抛出异常。可以看到传参里面写的是BizExceptione,这个是作为回调的接头暗号(重试次数用完了,还是失败,我们抛出这个BizExceptione通知触发这个回调方法)。

注意事项:
  • @Recover注解来开启重试失败后调用的方法,此注解注释的方法参数一定要是@Retryable抛出的异常,否则无法识别。
  • @Recover标注的方法的返回值必须与@Retryable标注的方法一致。
  • 该回调方法与重试方法写在同一个实现类里面。
  • 由于是基于AOP实现,所以不支持类里自调用方法。
  • 方法内不能使用trycatch,只能往外抛异常,而且异常必须是Throwable类型的。
  • 原理Spring-retyr调用时序图:?

    SpringRetry的基本原理是通过@EnableRetry注解引入AOP能力。在Spring容器启动时,会扫描所有带有@Retryable和@CircuitBreaker(熔断器)注解的方法,并为其生成PointCut和Advice。当发生方法调用时,Spring会委托拦截器RetryOperationsInterceptor进行调用,拦截器内部实现了失败退避重试和降级恢复方法。这种设计模式使得重试逻辑的实现非常简单易懂,并且能够充分利用Spring框架提供的AOP能力,从而实现高效而优雅的重试机制。缺陷尽管SpringRetry工具能够优雅地实现重试,但它仍然存在两个不太友好的设计:首先,重试实体被限定为Throwable子类,这意味着重试针对的是可捕获的功能异常,但实际上我们可能希望依赖某个数据对象实体作为重试实体,但是SpringRetry框架必须强制将其转换为Throwable子类。其次,重试根源的断言对象使用的是doWithRetry的Exception异常实例,这不符合正常内部断言的返回设计。SpringRetry建议使用注解来对方法进行重试,重试逻辑是同步执行的。重试的“失败”是指Throwable异常,如果你要通过返回值的某个状态来判断是否需要重试,则可能需要自己判断返回值并手动抛出异常。

    2.6GuavaRetrying

    GuavaRetrying是基于Google的核心类库Guava的重试机制实现的一个库,它提供了一种通用方法,可以使用Guava谓词匹配增强的特定停止、重试和异常处理功能来重试任意Java代码。这个库支持多种重试策略,比如指定重试次数、指定重试时间间隔等。此外,它还支持谓词匹配来确定是否应该重试,以及在重试时应该做些什么。GuavaRetrying的最大特点是它能够灵活地与其他Guava类库集成,这使得它非常易于使用。POM依赖<dependency><groupId>com.github.rholder</groupId><artifactId>guava-retrying</artifactId><version>2.0.0</version></dependency>测试demopublicstaticvoidmain(String[]args){Callable<Boolean>callable=newCallable<Boolean>(){@OverridepublicBooleancall()throwsException{//dosomethingusefulherelog.info("call...");thrownewRuntimeException();}};
    Retryer<Boolean>retryer=RetryerBuilder.<Boolean>newBuilder()//retryIf重试条件.retryIfException().retryIfRuntimeException().retryIfExceptionOfType(Exception.class).retryIfException(Predicates.equalTo(newException())).retryIfResult(Predicates.equalTo(false))//等待策略:每次请求间隔1s.withWaitStrategy(WaitStrategies.fixedWait(1,TimeUnit.SECONDS))//停止策略:尝试请求6次.withStopStrategy(StopStrategies.stopAfterAttempt(6))//时间限制:某次请求不得超过2s.withAttemptTimeLimiter(AttemptTimeLimiters.fixedTimeLimit(2,TimeUnit.SECONDS))//注册一个自定义监听器(可以实现失败后的兜底方法).withRetryListener(newMyRetryListener()).build();try{retryer.call(callable);}catch(Exceptionee){ee.printStackTrace();}}当发生重试之后,假如我们需要做一些额外的处理动作,比如发个告警邮件啥的,那么可以使用RetryListener。每次重试之后,guava-retrying会自动回调我们注册的监听。可以注册多个RetryListener,会按照注册顺序依次调用。publicclassMyRetryListenerimplementsRetryListener{@Overridepublic<V>voidonRetry(Attempt<V>attempt){//第几次重试System.out.print("[retry]time="+attempt.getAttemptNumber());//距离第一次重试的延迟System.out.print(",delay="+attempt.getDelaySinceFirstAttempt());
    //重试结果:是异常终止,还是正常返回System.out.print(",hasException="+attempt.hasException());System.out.print(",hasResult="+attempt.hasResult());
    //是什么原因导致异常if(attempt.hasException()){System.out.print(",causeBy="+attempt.getExceptionCause().toString());//dosomethingusefulhere}else{//正常返回时的结果System.out.print(",result="+attempt.getResult());}System.out.println();}}RetryerBuilder是一个factory创建者,可以定制设置重试源且可以支持多个重试源,可以配置重试次数或重试超时时间,以及可以配置等待时间间隔,创建重试者Retryer实例。

    RetryerBuilder的重试源支持Exception异常对象和自定义断言对象,通过retryIfException和retryIfResult设置,同时支持多个且能兼容。
  • retryIfException,抛出runtime异常、checked异常时都会重试,但是抛出error不会重试。

  • retryIfRuntimeException只会在抛runtime异常的时候才重试,checked异常和error都不重试。

  • retryIfExceptionOfType允许我们只在发生特定异常的时候才重试,比如NullPointerException和IllegalStateException都属于runtime异常,也包括自定义的error。

  • retryIfResult可以指定你的Callable方法在返回值的时候进行重试。

  • StopStrategy:停止重试策略,提供以下方式:StopAfterDelayStrategy设定一个最长允许的执行时间;比如设定最长执行10s,无论任务执行次数,只要重试的时候超出了最长时间,则任务终止,并返回重试异常NeverStopStrategy用于需要一直轮训知道返回期望结果的情况。StopAfterAttemptStrategy设定最大重试次数,如果超出最大重试次数则停止重试,并返回重试异常。WaitStrategy等待时长策略(控制时间间隔)FixedWaitStrategy固定等待时长策略。RandomWaitStrategy随机等待时长策略(可以提供一个最小和最大时长,等待时长为其区间随机值)。IncrementingWaitStrategy递增等待时长策略(提供一个初始值和步长,等待时间随重试次数增加而增加)。ExponentialWaitStrategy指数等待时长策略FibonacciWaitStrategy等待时长策略ExceptionWaitStrategy异常时长等待策略CompositeWaitStrategy复合时长等待策略

    优势GuavaRetryer工具与SpringRetry类似,都是通过定义重试者角色来包装正常逻辑重试。然而,GuavaRetryer在策略定义方面更优秀。它不仅支持设置重试次数和重试频度控制,还能够兼容多个异常或自定义实体对象的重试源定义,从而提供更多的灵活性。这使得GuavaRetryer能够适用于更多的业务场景,比如网络请求、数据库访问等。此外,GuavaRetryer还具有很好的可扩展性,可以很方便地与其他Guava类库集成使用。
    java怎么重新编译整个项目内容的内容

    三、优雅重试共性和原理

    SpringRetry和GuavaRetryer工具都是线程安全的重试工具,它们能够支持并发业务场景下的重试逻辑,并保证重试的正确性。这些工具可以设置重试间隔时间、差异化的重试策略和重试超时时间,进一步提高了重试的有效性和流程的稳定性。同时,SpringRetry和GuavaRetryer都使用了命令设计模式,通过委托重试对象来完成相应的逻辑操作,并在内部实现了重试逻辑的封装。这种设计模式使得重试逻辑的扩展和修改变得非常容易,同时也增强了代码的可重用性。

    四、总结

    在某些功能逻辑中,存在不稳定依赖的场景,这时我们需要使用重试机制来获取预期结果或尝试重新执行逻辑而不立即结束。比如在远程接口访问、数据加载访问、数据上传校验等场景中,都可能需要使用重试机制。不同的异常场景需要采用不同的重试方式,同时,我们应该尽可能将正常逻辑和重试逻辑解耦。在设置重试策略时,我们需要根据实际情况考虑一些问题。比如,我们需要考虑什么时机进行重试比较合适?是否应该同步阻塞重试还是异步延迟请重试?是否具备一键快速失败的能力?另外,我们需要考虑失败不重试会不会严重影响用户体验。在设置超时时间、重试策略、重试场景和重试次数时,我们也需要慎重考虑以上问题。本文只讲解了重试机制的一小部分,我们在实际应用时要根据实际情况采用合适的失败重试方案。?参考文档:面向失败编程之重试:https://ata.alibaba-inc.com/articles/225831?spm=ata.23639746.0.0.5b38767334nFCk?图文并茂:一文带你探索HSF的实现原理:https://ata.alibaba-inc.com/articles/181123?自动重试:HSF/Spring-retry/Resilience4j/自研小工具:https://ata.alibaba-inc.com/articles/257389?spm=ata.23639746.0.0.5b38767334nFCk#eqscrU0J?

    你时常焦虑吗?一般是在什么场景,工作或生活?我们是否掉入了“别人贩卖的焦虑”(PUA、35岁危机)的陷阱?

    .rich_media_content{color:#000000e5;font-size:17px;font-size:var(--articleFontsize);overflow:hidden;text-align:justify}.rich_media_content{color:#ffffffa6;color:var(--weui-FG-HALF)}.rich_media_content{position:relative;z-index:0}

    【FUTURE PROGRAMMING COURSE】尊享对接老板

    电话+V: 152079-09430

    机构由一批拥有10年以上开发管理经验,且来自互联网或研究机构的IT精英组成,负责研究、开发教学模式和课程内容。公司具有完善的课程研发体系,一直走在整个行业发展的前端,在行业内竖立起了良好的品质口碑。

    java怎么重新编译整个项目内容的内容
    Copyright2023未知推广科技