【SpringBoot】SpringBoot配置與單元測試(二)


  SpringBoot項目創建參考【SpringBoot】SpringBoot快速入門(一)

  本文介紹SpringBoot項目的POM文件、配置與單元測試

POM文件

  1、SpringBoot的pom文件中,看到都依賴一個springboot的父項目,如下

1 <parent>
2     <groupId>org.springframework.boot</groupId>
3     <artifactId>spring‐boot‐starter‐parent</artifactId>
4     <version>2.1.8.RELEASE</version>
5 </parent>

    而springboot的父項目又有一個父項目,此項目才是真正管理Spring Boot應用里面的所有依賴版本

1 <parent>
2     <groupId>org.springframework.boot</groupId>
3     <artifactId>spring-boot-dependencies</artifactId>
4     <version>2.1.8.RELEASE</version>
5     <relativePath>../../spring-boot-dependencies</relativePath>
6 </parent>

    以后導入依賴默認是不需要寫版本(沒有在dependencies里面管理的依賴自然需要聲明版本號)

    依賴關系如下:

    

  2、SpringBoot的啟動器

    spring-boot-starter:spring-boot場景啟動器;幫我們導入了web模塊正常運行所依賴的組件

1 <dependencies>
2     <!-- 不需要寫版本號,版本號依賴父項目(spring-boot-starter-parent)管理 -->
3     <!-- SpringBoot 將所有的功能場景抽取出來,做成一個個starter(啟動器),
4         只需要在項目中引入這些starter相關場景的所有依賴都會導入進來,要用什么功能就導入什么啟動器-->
5     <dependency>
6         <groupId>org.springframework.boot</groupId>
7         <artifactId>spring-boot-starter-web</artifactId>
8     </dependency>
9 </dependencies>

主程序類,主入口類

  1、主程序類,入口類

 1 /**
 2  * @SpringBootApplication 用來標注一個主程序,說明這是一個Spring Boot應用
 3  */
 4 @SpringBootApplication
 5 public class Application {
 6 
 7     public static void main(String[] args) {
 8 
 9         // Spring應用啟動
10         SpringApplication.run(Application.class, args);
11     }
12 }    

  2、SpringBoot注解

     a、@SpringBootApplication: Spring Boot應用標注在某個類上說明這個類是SpringBoot的主配置類,

    SpringBoot 就應該運行這個類的main方法來啟動SpringBoot應用;  

1 @Target(ElementType.TYPE)
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Inherited
5 @SpringBootConfiguration
6 @EnableAutoConfiguration
7 @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
8         @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
9 public @interface SpringBootApplication {

    b、@SpringBootApplication > @SpringBootConfiguration: Spring Boot的配置類;標注在某個類上,表示這是一個Spring Boot的配置類; 

    c、@SpringBootApplication > @SpringBootConfiguration > @Configuration: 配置類上來標注這個注解; 配置類 ----- 配置文件; 配置類也是容器中的一個組件;@Component

    d、@SpringBootApplication > @EnableAutoConfiguration: 開啟自動配置功能; Spring配置的東西,SpringBoot開啟自動配置功能;這樣自動配置才能生效;

1 @Target(ElementType.TYPE)
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Inherited
5 @AutoConfigurationPackage
6 @Import(AutoConfigurationImportSelector.class)
7 public @interface EnableAutoConfiguration {

    e、@SpringBootApplication > @EnableAutoConfiguration > @AutoConfigurationPackage: 自動配置包

    f、@SpringBootApplication > @EnableAutoConfiguration > @AutoConfigurationPackage > @Import(AutoConfigurationPackages.Registrar.class): Spring的底層注解@Import,給容器中導入一個組件;導入的組件由 AutoConfigurationPackages.Registrar.class;

      將主配置類(@SpringBootApplication標注的類)的所在包及下面所有子包里面的所有組件掃描到Spring容器;         

    g、@SpringBootApplication > @EnableAutoConfiguration > @Import(EnableAutoConfigurationImportSelector.class); 選擇要導入容器的組件,  

      EnableAutoConfigurationImportSelector: 導入哪些組件的選擇器; 將所有需要導入的組件以全類名的方式返回;這些組件就會被添加到容器中;

      會給容器中導入非常多的自動配置類(xxxAutoConfiguration);就是給容器中導入這個場景需要的所有組件, 並配置好這些組件;

      

      有了自動配置類,免去了手動編寫配置注入功能組件等的工作;SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);

      Spring Boot在啟動的時候從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration指定的值

      J2EE的整體整合解決方案和自動配置都在spring-boot-autoconfigure-2.1.8.RELEASE.jar;

SpringBoot自動配置原理

  1、SpringBoot啟動的時候加載主配置類,在主配置類@SpringBootApplication注解中,

    開啟了自動配置功能 @EnableAutoConfiguration

  2、@EnableAutoConfiguration的作用

    a、利用EnableAutoConfigurationImportSelector給容器中導入一些組件

    b、EnableAutoConfigurationImportSelector類中,可以查看getAutoConfigurationEntry()方法的內容,代碼邏輯如下

 1 // 獲取候選的配置
 2 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
 3 
 4 
 5 // getCandidateConfigurations此方法中調用了
 6 SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
 7                 getBeanClassLoader());
 8 
 9 // loadFactoryNames方法就會返回所有配置類名稱
10 // 掃描所有jar包類路徑下 META‐INF/spring.factories
11 // 把掃描到的這些文件的內容包裝成properties對象
12 // 從properties中獲取到EnableAutoConfiguration.class類(類名)對應的值,然后把他們添加在容器中

    c、將 類路徑下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中; spring.factories內容如下:

  1 # Auto Configure
  2 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  3 org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
  4 org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
  5 org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
  6 org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
  7 org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
  8 org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
  9 org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
 10 org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
 11 org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
 12 org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
 13 org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
 14 org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
 15 org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
 16 org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
 17 org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
 18 org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
 19 org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
 20 org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
 21 org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
 22 org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
 23 org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
 24 org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
 25 org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
 26 org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
 27 org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
 28 org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
 29 org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
 30 org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
 31 org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
 32 org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
 33 org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
 34 org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
 35 org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
 36 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
 37 org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
 38 org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
 39 org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
 40 org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
 41 org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
 42 org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
 43 org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
 44 org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
 45 org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
 46 org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
 47 org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
 48 org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
 49 org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
 50 org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
 51 org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
 52 org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
 53 org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
 54 org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
 55 org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
 56 org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
 57 org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
 58 org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
 59 org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
 60 org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
 61 org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
 62 org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
 63 org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
 64 org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
 65 org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
 66 org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
 67 org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
 68 org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
 69 org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
 70 org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
 71 org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
 72 org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
 73 org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
 74 org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
 75 org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
 76 org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
 77 org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
 78 org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
 79 org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
 80 org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
 81 org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
 82 org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
 83 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
 84 org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
 85 org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
 86 org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
 87 org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
 88 org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
 89 org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
 90 org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
 91 org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
 92 org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
 93 org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
 94 org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
 95 org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
 96 org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
 97 org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
 98 org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
 99 org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
100 org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
101 org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
102 org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
103 org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
104 org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
105 org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
106 org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
107 org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
108 org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
109 org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
110 org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
111 org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
112 org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
113 org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
114 org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
115 org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
116 org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
117 org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
118 org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
119 org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

  3、每一個自動配置類進行自動配置功能,每一個這樣的 xxxAutoConfiguration類都是容器中的一個組件,都加入到容器中; 用他們來做自動配置; 

  4、以HttpEncodingAutoConfiguration(Http編碼自動配置)為例解釋自動配置原理;

 1 @Configuration //表示這是一個配置類,以前編寫的配置文件一樣,也可以給容器中添加組件
 2 @EnableConfigurationProperties(HttpEncodingProperties.class) //啟動指定類的
 3 ConfigurationProperties功能;將配置文件中對應的值和HttpEncodingProperties綁定起來;並把
 4 HttpEncodingProperties加入到ioc容器中
 5 
 6 
 7 //表示這是一個配置類,以前編寫的配置文件一樣,也可以給容器中添加組件
 8 @Configuration
 9 //啟動指定屬性類的,相當於將HttpProperties注入容器
10 @EnableConfigurationProperties(HttpProperties.class)
11 
12 // Spring底層@Conditional注解,根據不同的條件,如果 滿足指定的條件,整個配置類里面的配置就會生效; 
13 // 判斷當前應用是否是web應用,如果是,當前配置類生效
14 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
15 
16 // 判斷當前項目有沒有這個類
17 // CharacterEncodingFilter; SpringMVC中進行亂碼解決的過濾器;
18 @ConditionalOnClass(CharacterEncodingFilter.class)
19 
20 // 判斷配置文件中是否存在某個配置 spring.http.encoding.enabled;如果不存在,判斷也是成立的
21 // 即使配置文件中不配置pring.http.encoding.enabled=true,也是默認生效的;
22 @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
23 public class HttpEncodingAutoConfiguration {
24 
25     // 類已經和SpringBoot的配置文件映射了
26     private final HttpProperties.Encoding properties;
27 
28     // 只有一個有參構造器的情況下,參數的值就會從容器中拿
29     public HttpEncodingAutoConfiguration(HttpProperties properties) {
30         this.properties = properties.getEncoding();
31     }
32 
33     // 給容器中添加一個組件,這個組件的某些值需要從properties中獲取
34     @Bean
35     //判斷容器沒有這個組件? 沒有則注入
36     @ConditionalOnMissingBean
37     public CharacterEncodingFilter characterEncodingFilter() {
38         CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
39         filter.setEncoding(this.properties.getCharset().name());
40         filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
41         filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
42         return filter;
43     }
44 
45     @Bean
46     public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
47         return new LocaleCharsetMappingsCustomizer(this.properties);
48     }
49 
50     private static class LocaleCharsetMappingsCustomizer
51             implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
52 
53         private final HttpProperties.Encoding properties;
54 
55         LocaleCharsetMappingsCustomizer(HttpProperties.Encoding properties) {
56             this.properties = properties;
57         }
58 
59         @Override
60         public void customize(ConfigurableServletWebServerFactory factory) {
61             if (this.properties.getMapping() != null) {
62                 factory.setLocaleCharsetMappings(this.properties.getMapping());
63             }
64         }
65 
66         @Override
67         public int getOrder() {
68             return 0;
69         }
70 
71     }
72 
73 }

    根據當前不同的條件判斷,決定這個配置類是否生效?

    一但這個配置類生效;這個配置類就會給容器中添加各種組件;這些組件的屬性是從對應的properties類中獲取 的,這些類里面的每一個屬性又是和配置文件綁定的;

  5、所有在配置文件中能配置的屬性都是在xxxxProperties類中封裝着;配置文件能配置什么就可以參照某個功 能對應的這個屬性類

1 // 從配置文件中獲取指定的值和bean的屬 性進行綁定
2 @ConfigurationProperties(prefix = "spring.http")
3 public class HttpProperties {

  6、在配置文件中設置 debug = true,可以在控制台查看springboot自動配置的服務,啟動了那些自動配置類。

  精髓

    1)、SpringBoot啟動會加載大量的自動配置類

    2)、使用時,查看需要的功能有沒有SpringBoot默認寫好的自動配置類;

    3)、再來看這個自動配置類中到底配置了哪些組件; (只要我們要用的組件有,我們就不需要再來配置了)

    4)、給容器中自動配置類添加組件的時候,會從properties類中獲取某些屬性。我們就可以在配置文件中指定這些屬性的值;

      xxxxAutoConfigurartion:自動配置類; 給容器中添加組件

      xxxxProperties:封裝配置文件中相關屬性;
 
                       

SpringBoot單元測試

  1、引入SpringBoot測試依賴

1 <dependency>
2     <groupId>org.springframework.boot</groupId>
3     <artifactId>spring-boot-starter-test</artifactId>
4     <scope>test</scope>
5 </dependency>

  2、編輯測試類。TestSpringbootApplicationTests.java

 1 package com.test.springboot;
 2 
 3 import org.junit.Test;
 4 import org.junit.runner.RunWith;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.boot.test.context.SpringBootTest;
 7 import org.springframework.context.ApplicationContext;
 8 import org.springframework.test.context.junit4.SpringRunner;
 9 
10 /**
11  * SpringBoot單元測試
12  *
13  * 可以在測試期間很方便的類似編碼一樣的自動注入
14  */
15 @RunWith(SpringRunner.class)
16 @SpringBootTest
17 public class TestSpringbootApplicationTests {
18 
19     @Autowired
20     ApplicationContext context;
21 
22     @Test
23     public void contextLoads(){
24         boolean b = context.containsBean("helloController");
25         System.out.println(b);
26     }
27 
28 
29 }

  3、運行測試類測試方法,運行結果如下:

    

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM