首页 文章 精选 留言 我的

精选列表

搜索[用户留存],共10000篇文章
优秀的个人博客,低调大师

MyBatis 配置文件 用户密码加密存储

properties配置文件 一般是使用properties保存配置文件内容,然后在mybatis配置文件中进行读取在resource文件下新建db.properties文件内容如下 # 数据库配置文件 driver = com.mysql.cj.jdbc.Driver url = jdbc:mysql:// /mybatis username = password = 然后,接着把文件放入源码包中配置mybatis-config.xml文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 读取数据库配置文件 --> <properties resource="db.properties"/> <!-- 定义别名 --> <typeAliases> <typeAlias type="com.ming.Role" alias="role"/> </typeAliases> <!-- 自定义数据处理 --> <typeHandlers> <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.ming.Sex"/> </typeHandlers> <!-- 定义数据库信息 --> <environments default="development"> <environment id="development"> <!-- jdbc事物管理 --> <transactionManager type="JDBC"/> <!-- 数据库链接信息 --> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="RoleMapper.xml"/> </mappers> </configuration> 目录结构如下 数据库密码加密 生产环境的数据库密码都为加密密码,需要在使用的时候,把加密密码解密成为明文先创建数据库密码类 package com.ming.Util; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.*; import java.util.Base64; public class Decode { /** * 生成秘钥 * @param * @return */ public static String generateDecode() throws UnsupportedEncodingException { KeyGenerator keyGen = null;//密钥生成器 try { keyGen = KeyGenerator.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyGen.init(56);//初始化密钥生成器 SecretKey secretKey = keyGen.generateKey();//生成密钥 byte[] key = secretKey.getEncoded();//密钥字节数组 // 进行base64编码 String encodedKey = Base64.getEncoder().encodeToString(key); return encodedKey; } /** * 进行加密 * @param string * @param key * @return */ public static String encryptionDecode(String string, String key){ //System.out.println(System.getenv("KEYWORDES")); SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "DES");//恢复密钥 Cipher cipher = null;//Cipher完成加密或解密工作类 try { cipher = Cipher.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } try { cipher.init(Cipher.ENCRYPT_MODE, secretKey);//对Cipher初始化,加密模式 } catch (InvalidKeyException e) { e.printStackTrace(); } byte[] cipherByte = null; try { cipherByte = cipher.doFinal(Base64.getDecoder().decode(string));//加密data } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return Base64.getEncoder().encodeToString(cipherByte); } public static String decryptDecode(String string, String key){ SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "DES");//恢复密钥 Cipher cipher = null;//Cipher完成加密或解密工作类 try { cipher = Cipher.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } try { cipher.init(Cipher.DECRYPT_MODE, secretKey);//对Cipher初始化,解密模式 } catch (InvalidKeyException e) { e.printStackTrace(); } byte[] cipherByte = new byte[0];//解密data try { cipherByte = cipher.doFinal(Base64.getDecoder().decode(string)); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return Base64.getEncoder().encodeToString(cipherByte); } } 该类有三个方法,为加密data,解密data,生成key然后编辑操作系统环境变量达到输入 ~ echo $KEYWORDES 可以输出环境变量接着再次修改SqlSessionFactoryUtil类 package com.ming.Util; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Properties; /** * @author ming * 构建SqlSessionFactory * 由于数据库连接是宝贵的,需要对数据库连接统一管理,所以使用单例进行管理 * 这里的单利使用的双重锁 * SqlSessionFactory为线程不安全类型需要加锁,确保同一时刻,只有一个线程可以使用该对象 */ public class SqlSessionFactoryUtil { /** * SqlSessionFactory对象 */ private static SqlSessionFactory sqlSessionFactory = null; /** * 类线程锁 */ private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class; /** * 日志管理类 */ private static final Logger logger = LogManager.getLogger(); /** * 单例 */ private SqlSessionFactoryUtil(){ } /** * @return SqlSessionFactory * 初始化SqlSessionFactory对象 */ public static SqlSessionFactory initSqlSessionFactory(){ // 获得输入流 InputStream cfgStream = null; // 阅读流 Reader cfgReader = null; InputStream proStream = null; Reader proReader = null; // 持久化属性集 Properties properties = null; try{ // 配置文件流 cfgStream = Resources.getResourceAsStream("mybatis-config.xml"); // 获得阅读流 cfgReader = new InputStreamReader(cfgStream); // 读入属性文件 proStream = Resources.getResourceAsStream("db.properties"); proReader = new InputStreamReader(proStream); // 持久化属性集 properties = new Properties(); // 流转载进入属性集合 properties.load(proReader); }catch (Exception e){ logger.error(e); } if(sqlSessionFactory == null){ synchronized (CLASS_LOCK){ sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader, properties); } } return sqlSessionFactory; } /** * 打开SqlSession * @return SqlSession */ public static SqlSession openSqlSesion(){ // 判空处理 if(sqlSessionFactory == null){ initSqlSessionFactory(); } return sqlSessionFactory.openSession(); } } 接着,再次对密码进行加密,在读取的时候,对阅读流的结果集进行持久化设置先对db.properties数据库密码进行加密更改以后配置文件如下 # 数据库配置文件 driver = com.mysql.cj.jdbc.Driver url = jdbc:mysql://47.94.95.84:32786/mybatis username = mybatis password = 8GgwaJCtTXLGItiYF9c4mg== 接着再次更改Util类 package com.ming.Util; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Properties; /** * @author ming * 构建SqlSessionFactory * 由于数据库连接是宝贵的,需要对数据库连接统一管理,所以使用单例进行管理 * 这里的单利使用的双重锁 * SqlSessionFactory为线程不安全类型需要加锁,确保同一时刻,只有一个线程可以使用该对象 */ public class SqlSessionFactoryUtil { /** * SqlSessionFactory对象 */ private static SqlSessionFactory sqlSessionFactory = null; /** * 类线程锁 */ private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class; /** * 日志管理类 */ private static final Logger logger = LogManager.getLogger(); /** * 单例 */ private SqlSessionFactoryUtil(){ } /** * @return SqlSessionFactory * 初始化SqlSessionFactory对象 */ public static SqlSessionFactory initSqlSessionFactory(){ // 获得输入流 InputStream cfgStream = null; // 阅读流 Reader cfgReader = null; InputStream proStream = null; Reader proReader = null; // 持久化属性集 Properties properties = null; try{ // 配置文件流 cfgStream = Resources.getResourceAsStream("mybatis-config.xml"); // 获得阅读流 cfgReader = new InputStreamReader(cfgStream); // 读入属性文件 proStream = Resources.getResourceAsStream("db.properties"); proReader = new InputStreamReader(proStream); // 持久化属性集 properties = new Properties(); // 流装载进入属性集合 properties.load(proReader); // 获取当前系统ENV String key = System.getenv("KEYWORDES"); // 进行解密 properties.setProperty("password", Decode.decryptDecode(properties.getProperty("password"), key)); }catch (Exception e){ logger.error(e); } if(sqlSessionFactory == null){ synchronized (CLASS_LOCK){ sqlSessionFactory = new SqlSessionFactoryBuilder().build(cfgReader, properties); } } return sqlSessionFactory; } /** * 打开SqlSession * @return SqlSession */ public static SqlSession openSqlSesion(){ // 判空处理 if(sqlSessionFactory == null){ initSqlSessionFactory(); } return sqlSessionFactory.openSession(); } } 书写单元测试 package com.ming.Util; import org.junit.Test; import static org.junit.Assert.*; public class SqlSessionFactoryUtilTest { @Test public void initSqlSessionFactory() { } @Test public void openSqlSesion() { SqlSessionFactoryUtil.openSqlSesion(); } } 目前的目录结构 此时执行单元测试,可以发现单元测试已经通过控制台打印出log信息 2019-04-11 17:17:37.357 [DEBUG] org.apache.ibatis.logging.LogFactory.setImplementation(LogFactory.java:105) - Logging initialized using 'class org.apache.ibatis.logging.log4j2.Log4j2Impl' adapter. 2019-04-11 17:17:37.403 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.forceCloseAll(PooledDataSource.java:334) - PooledDataSource forcefully closed/removed all connections. 2019-04-11 17:17:37.403 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.forceCloseAll(PooledDataSource.java:334) - PooledDataSource forcefully closed/removed all connections. 2019-04-11 17:17:37.404 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.forceCloseAll(PooledDataSource.java:334) - PooledDataSource forcefully closed/removed all connections. 2019-04-11 17:17:37.404 [DEBUG] org.apache.ibatis.datasource.pooled.PooledDataSource.forceCloseAll(PooledDataSource.java:334) - PooledDataSource forcefully closed/removed all connections. Process finished with exit code 0 发现错误,修改加密类 package com.ming.Util; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.*; import java.util.Base64; public class Decode { /** * 生成秘钥 * @param * @return */ public static String generateDecode() throws UnsupportedEncodingException { KeyGenerator keyGen = null;//密钥生成器 try { keyGen = KeyGenerator.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyGen.init(56);//初始化密钥生成器 SecretKey secretKey = keyGen.generateKey();//生成密钥 byte[] key = secretKey.getEncoded();//密钥字节数组 // 进行base64编码 String encodedKey = Base64.getEncoder().encodeToString(key); return encodedKey; } /** * 进行加密 * @param string * @param key * @return */ public static String encryptionDecode(String string, String key){ SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "DES");//恢复密钥 Cipher cipher = null;//Cipher完成加密或解密工作类 try { cipher = Cipher.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } try { cipher.init(Cipher.ENCRYPT_MODE, secretKey);//对Cipher初始化,加密模式 } catch (InvalidKeyException e) { e.printStackTrace(); } byte[] cipherByte = null; try { cipherByte = cipher.doFinal(string.getBytes());//加密data } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return Base64.getEncoder().encodeToString(cipherByte); } /** * 进行解密 * @param string * @param key * @return */ public static String decryptDecode(String string, String key){ SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), "DES");//恢复密钥 Cipher cipher = null;//Cipher完成加密或解密工作类 try { cipher = Cipher.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } try { cipher.init(Cipher.DECRYPT_MODE, secretKey);//对Cipher初始化,解密模式 } catch (InvalidKeyException e) { e.printStackTrace(); } byte[] cipherByte = new byte[0];//解密data try { cipherByte = cipher.doFinal(Base64.getDecoder().decode(string)); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } return new String(cipherByte); } } 再次运行,可以发现已经成功执行sql语句

优秀的个人博客,低调大师

SpringBoot-Security-用户权限分配-项目搭建

官网地址:https://docs.spring.io/spring-boot/docs/2.1.x/reference/htmlsingle/ SpringBoot原则是约定优于配置,简化spring应用开发,去繁从简,产品级别的应用。 SpringBoot有哪些优点1、快速创建独立运行的spring项目与主流框架集成 2、使用嵌入式的servlet容器,应用无需打包成war包 3、starters自动依赖与版本控制 4、大量的自动配置,简化开发,也可修改默认值 5、准生产环境的运行应用监控 6、与云计算的天然集成 在使用spring boot之前,搭建一个spring web项目需要的步骤:1、配置web.xml,加载spring和spring mvc2、配置数据库连接、配置spring事务3、配置加载配置文件的读取,开启注解4、配置日志文件... Spring发展阶段 第一阶段:xml配置在Spring1.x时代,使用Spring开发满眼都是xml配置的Bean,随着项目的扩大,我们需要把xml配置文件放到不同的配置文件里,那时需要频繁的在开发的类和配置文件之间进行切换 第二阶段:注解配置在Spring2.x时代,随着JDK1.5带来的注解支持,Spring提供了声明Bean的注解(例如@Component、@Service),大大减少了配置量。主要使用的方式是应用的基本配置(如数据库配置)用xml,业务配置用注解 第三阶段:java配置Spring 3.0引入了基于Java的配置能力,这是一种类型安全的可重构配置方式,可以代替XML。我们目前刚好处于这个时代,Spring4.x和SpringBoot都推荐使用Java配置。 SpringBoot 启动器说明 名称 描述 spring-boot-starter 核心启动器,包括自动配置支持,日志记录和YAML spring-boot-starter-activemq 使用Apache ActiveMQ进行JMS消息传递的入门者 spring-boot-starter-amqp 使用Spring AMQP和Rabbit MQ的入门者 spring-boot-starter-aop 使用Spring AOP和AspectJ进行面向方面编程的入门者 spring-boot-starter-artemis 使用Apache Artemis进行JMS消息传递的入门者 spring-boot-starter-batch 使用Spring Batch的入门者 spring-boot-starter-cache 使用Spring Framework的缓存支持的初学者 spring-boot-starter-cloud-connectors 使用Spring Cloud Connectors的初学者简化了Cloud Foundry和Heroku等云平台中的服务连接 spring-boot-starter-data-cassandra 使用Cassandra分布式数据库和Spring Data Cassandra的入门者 spring-boot-starter-data-cassandra-reactive 使用Cassandra分布式数据库和Spring Data Cassandra Reactive的入门者 spring-boot-starter-data-couchbase 使用Couchbase面向文档的数据库和Spring Data Couchbase的入门者 spring-boot-starter-data-couchbase-reactive 使用Couchbase面向文档的数据库和Spring Data Couchbase Reactive的入门者 spring-boot-starter-data-elasticsearch 使用Elasticsearch搜索和分析引擎以及Spring Data Elasticsearch的初学者 spring-boot-starter-data-jdbc 使用Spring Data JDBC的入门者 spring-boot-starter-data-jpa 将Spring Data JPA与Hibernate一起使用的初学者 spring-boot-starter-data-ldap 使用Spring Data LDAP的入门者 spring-boot-starter-data-mongodb 使用MongoDB面向文档的数据库和Spring Data MongoDB的初学者 spring-boot-starter-data-mongodb-reactive 使用MongoDB面向文档的数据库和Spring Data MongoDB Reactive的入门者 spring-boot-starter-data-neo4j 使用Neo4j图形数据库和Spring Data Neo4j的入门者 spring-boot-starter-data-redis 在Spring Data Redis和Lettuce客户端上使用Redis键值数据存储的初学者 spring-boot-starter-data-redis-reactive 使用带有Spring Data Redis被动的Redis键值数据存储和Lettuce客户端的入门者 spring-boot-starter-data-rest 使用Spring Data REST通过REST公开Spring Data存储库的入门者 spring-boot-starter-data-solr 在Spring Data Solr中使用Apache Solr搜索平台的初学者 spring-boot-starter-freemarker 使用FreeMarker视图构建MVC Web应用程序的入门者 spring-boot-starter-groovy-templates 使用Groovy模板视图构建MVC Web应用程序的入门者 spring-boot-starter-hateoas 使用Spring MVC和Spring HATEOAS构建基于超媒体的RESTful Web应用程序的入门者 spring-boot-starter-integration 使用Spring Integration的入门者 spring-boot-starter-jdbc 将JDBC与HikariCP连接池一起使用的入门者 spring-boot-starter-jersey 使用JAX-RS和Jersey构建RESTful Web应用程序的初学者。替代spring-boot-starter-web spring-boot-starter-jooq 使用jOOQ访问SQL数据库的初学者。替代spring-boot-starter-data-jpa或spring-boot-starter-jdbc spring-boot-starter-json 阅读和写作json的初学者 spring-boot-starter-jta-atomikos 使用Atomikos进行JTA交易的入门者 spring-boot-starter-jta-bitronix 使用Bitronix进行JTA事务的入门者 spring-boot-starter-mail 使用Java Mail和Spring Framework的电子邮件发送支持的入门者 spring-boot-starter-mustache 使用Mustache视图构建Web应用程序的入门者 spring-boot-starter-oauth2-client 使用Spring Security的OAuth2 / OpenID Connect客户端功能的入门者 spring-boot-starter-oauth2-resource-server 使用Spring Security的OAuth2资源服务器功能的入门者 spring-boot-starter-quartz 使用Quartz调度程序的入门者 spring-boot-starter-security 使用Spring Security的入门者 spring-boot-starter-test 使用JUnit,Hamcrest和Mockito等库来测试Spring Boot应用程序的初学者 spring-boot-starter-thymeleaf 使用Thymeleaf视图构建MVC Web应用程序的入门者 spring-boot-starter-validation 使用Java Bean Validation和Hibernate Validator的初学者 spring-boot-starter-web 使用Spring MVC构建Web(包括RESTful)应用程序的入门者。使用Tomcat作为默认嵌入式容器 spring-boot-starter-web-services 使用Spring Web Services的入门者 spring-boot-starter-webflux 使用Spring Framework的Reactive Web支持构建WebFlux应用程序的初学者 spring-boot-starter-websocket 使用Spring Framework的WebSocket支持构建WebSocket应用程序的初学者 spring-boot-starter-jetty 使用Jetty作为嵌入式servlet容器的入门。替代spring-boot-starter-tomcat spring-boot-starter-log4j2 使用Log4j2进行日志记录的入门。替代spring-boot-starter-logging spring-boot-starter-logging 使用Logback进行日志记录的入门。默认日志启动器 spring-boot-starter-reactor-netty 使用Reactor Netty作为嵌入式响应式HTTP服务器的入门者。 spring-boot-starter-tomcat 使用Tomcat作为嵌入式servlet容器的入门者。使用的默认servlet容器启动器spring-boot-starter-web spring-boot-starter-undertow 使用Undertow作为嵌入式servlet容器的入门者。替代spring-boot-starter-tomcat spring-boot-starter-actuator 使用Spring Boot的Actuator的初学者,它提供生产就绪功能,帮助您监控和管理您的应用程序 创建SpringBoot项目 1、打开idea开发工具,在菜单栏选择File-->New-->Project...-->Spring Initializer2、填写Group和Artifact信息3、勾选web4、修改工程名字和路径,完成

优秀的个人博客,低调大师

Django 搭建CMDB系统完整[1](用户登录)

***使用的mysql数据库,所以系统中要先安装mysql数据库 1、安装环境: pip install django python -m pip install --upgrade pip setuptools python -m pip install django pip install --upgrade pyls https://pypi.python.org/simple pip install MySQL-python pip install mysqlclient mkdir /dj cd /dj django-admin startproject cmdb cd cmdb python manage.py migrate cd cmdb vi settings.py 做如下更改 ALLOWED_HOSTS = ['*'] TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'cmdb', 'USER': 'root', 'PASSWORD': 'xxxxxxx', 'HOST': '127.0.0.1', 'PORT': '3306', } } vi urls.py 做如下更改 from django.conf.urls import url from django.contrib import admin from cmdb import views from django.contrib.auth.views import * urlpatterns = [ url(r'^', login), ] vi views.py 做如下更改 from django.shortcuts import render_to_response def main_page(request): return render_to_response('main_page.html', {'user':request.user }) cd /dj/cmdb mkdir -p templates/registration cd templates vi main_page.html 做如下更改 <html> <head> <title>Django Bookmarks</title> </head> <body> <h1>Welcome to Django Bookmarks</h1> {% if user.username %} <p>Welcome {{ user.username }}! Here you can store and share bookmarks!</p> {% else %} <p>Welcome anonymous user! You need to <a href="/login/">login</a> before you can store and share bookmarks.</p> {% endif %} </body> </html> cd registration vi login.html 做如下更改 <html> <head> <title>Django Bookmarks - User Login</title> </head> <body> <h1>User Login</h1> {% if form.has_errors %} <p>Your username and password didn't match. Please try again.</p> {% endif %} <form method="post" action="."> <p><label for="id_username">Username:</label> {{ form.username }}</p> <p><label for="id_password">Password:</label> {{ form.password }}</p> <input type="hidden" name="next" value="/" /> {% csrf_token %} <input type="submit" value="login" /> </form> </body> </html>

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册