Commit 24efae760546a9f4bf9bd8ba8a986d6795d9cbb1

Authored by 刘基城
0 parents

init

Showing 71 changed files with 4851 additions and 0 deletions

Too many changes to show.

To preserve performance only 71 of 90 files are displayed.

.gitignore 0 → 100644
  1 +++ a/.gitignore
  1 +# Maven #
  2 +target/
  3 +
  4 +# IDEA #
  5 +.idea/
  6 +*.iml
  7 +
  8 +# Eclipse #
  9 +.settings/
  10 +.classpath
  11 +.project
0 \ No newline at end of file 12 \ No newline at end of file
LICENSE 0 → 100644
  1 +++ a/LICENSE
  1 +Apache License
  2 +Version 2.0, January 2004
  3 +http://www.apache.org/licenses/
  4 +
  5 +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  6 +
  7 +1. Definitions.
  8 +
  9 +"License" shall mean the terms and conditions for use, reproduction, and
  10 +distribution as defined by Sections 1 through 9 of this document.
  11 +
  12 +"Licensor" shall mean the copyright owner or entity authorized by the copyright
  13 +owner that is granting the License.
  14 +
  15 +"Legal Entity" shall mean the union of the acting entity and all other entities
  16 +that control, are controlled by, or are under common control with that entity.
  17 +For the purposes of this definition, "control" means (i) the power, direct or
  18 +indirect, to cause the direction or management of such entity, whether by
  19 +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
  20 +outstanding shares, or (iii) beneficial ownership of such entity.
  21 +
  22 +"You" (or "Your") shall mean an individual or Legal Entity exercising
  23 +permissions granted by this License.
  24 +
  25 +"Source" form shall mean the preferred form for making modifications, including
  26 +but not limited to software source code, documentation source, and configuration
  27 +files.
  28 +
  29 +"Object" form shall mean any form resulting from mechanical transformation or
  30 +translation of a Source form, including but not limited to compiled object code,
  31 +generated documentation, and conversions to other media types.
  32 +
  33 +"Work" shall mean the work of authorship, whether in Source or Object form, made
  34 +available under the License, as indicated by a copyright notice that is included
  35 +in or attached to the work (an example is provided in the Appendix below).
  36 +
  37 +"Derivative Works" shall mean any work, whether in Source or Object form, that
  38 +is based on (or derived from) the Work and for which the editorial revisions,
  39 +annotations, elaborations, or other modifications represent, as a whole, an
  40 +original work of authorship. For the purposes of this License, Derivative Works
  41 +shall not include works that remain separable from, or merely link (or bind by
  42 +name) to the interfaces of, the Work and Derivative Works thereof.
  43 +
  44 +"Contribution" shall mean any work of authorship, including the original version
  45 +of the Work and any modifications or additions to that Work or Derivative Works
  46 +thereof, that is intentionally submitted to Licensor for inclusion in the Work
  47 +by the copyright owner or by an individual or Legal Entity authorized to submit
  48 +on behalf of the copyright owner. For the purposes of this definition,
  49 +"submitted" means any form of electronic, verbal, or written communication sent
  50 +to the Licensor or its representatives, including but not limited to
  51 +communication on electronic mailing lists, source code control systems, and
  52 +issue tracking systems that are managed by, or on behalf of, the Licensor for
  53 +the purpose of discussing and improving the Work, but excluding communication
  54 +that is conspicuously marked or otherwise designated in writing by the copyright
  55 +owner as "Not a Contribution."
  56 +
  57 +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
  58 +of whom a Contribution has been received by Licensor and subsequently
  59 +incorporated within the Work.
  60 +
  61 +2. Grant of Copyright License.
  62 +
  63 +Subject to the terms and conditions of this License, each Contributor hereby
  64 +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
  65 +irrevocable copyright license to reproduce, prepare Derivative Works of,
  66 +publicly display, publicly perform, sublicense, and distribute the Work and such
  67 +Derivative Works in Source or Object form.
  68 +
  69 +3. Grant of Patent License.
  70 +
  71 +Subject to the terms and conditions of this License, each Contributor hereby
  72 +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
  73 +irrevocable (except as stated in this section) patent license to make, have
  74 +made, use, offer to sell, sell, import, and otherwise transfer the Work, where
  75 +such license applies only to those patent claims licensable by such Contributor
  76 +that are necessarily infringed by their Contribution(s) alone or by combination
  77 +of their Contribution(s) with the Work to which such Contribution(s) was
  78 +submitted. If You institute patent litigation against any entity (including a
  79 +cross-claim or counterclaim in a lawsuit) alleging that the Work or a
  80 +Contribution incorporated within the Work constitutes direct or contributory
  81 +patent infringement, then any patent licenses granted to You under this License
  82 +for that Work shall terminate as of the date such litigation is filed.
  83 +
  84 +4. Redistribution.
  85 +
  86 +You may reproduce and distribute copies of the Work or Derivative Works thereof
  87 +in any medium, with or without modifications, and in Source or Object form,
  88 +provided that You meet the following conditions:
  89 +
  90 +You must give any other recipients of the Work or Derivative Works a copy of
  91 +this License; and
  92 +You must cause any modified files to carry prominent notices stating that You
  93 +changed the files; and
  94 +You must retain, in the Source form of any Derivative Works that You distribute,
  95 +all copyright, patent, trademark, and attribution notices from the Source form
  96 +of the Work, excluding those notices that do not pertain to any part of the
  97 +Derivative Works; and
  98 +If the Work includes a "NOTICE" text file as part of its distribution, then any
  99 +Derivative Works that You distribute must include a readable copy of the
  100 +attribution notices contained within such NOTICE file, excluding those notices
  101 +that do not pertain to any part of the Derivative Works, in at least one of the
  102 +following places: within a NOTICE text file distributed as part of the
  103 +Derivative Works; within the Source form or documentation, if provided along
  104 +with the Derivative Works; or, within a display generated by the Derivative
  105 +Works, if and wherever such third-party notices normally appear. The contents of
  106 +the NOTICE file are for informational purposes only and do not modify the
  107 +License. You may add Your own attribution notices within Derivative Works that
  108 +You distribute, alongside or as an addendum to the NOTICE text from the Work,
  109 +provided that such additional attribution notices cannot be construed as
  110 +modifying the License.
  111 +You may add Your own copyright statement to Your modifications and may provide
  112 +additional or different license terms and conditions for use, reproduction, or
  113 +distribution of Your modifications, or for any such Derivative Works as a whole,
  114 +provided Your use, reproduction, and distribution of the Work otherwise complies
  115 +with the conditions stated in this License.
  116 +
  117 +5. Submission of Contributions.
  118 +
  119 +Unless You explicitly state otherwise, any Contribution intentionally submitted
  120 +for inclusion in the Work by You to the Licensor shall be under the terms and
  121 +conditions of this License, without any additional terms or conditions.
  122 +Notwithstanding the above, nothing herein shall supersede or modify the terms of
  123 +any separate license agreement you may have executed with Licensor regarding
  124 +such Contributions.
  125 +
  126 +6. Trademarks.
  127 +
  128 +This License does not grant permission to use the trade names, trademarks,
  129 +service marks, or product names of the Licensor, except as required for
  130 +reasonable and customary use in describing the origin of the Work and
  131 +reproducing the content of the NOTICE file.
  132 +
  133 +7. Disclaimer of Warranty.
  134 +
  135 +Unless required by applicable law or agreed to in writing, Licensor provides the
  136 +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
  137 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
  138 +including, without limitation, any warranties or conditions of TITLE,
  139 +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
  140 +solely responsible for determining the appropriateness of using or
  141 +redistributing the Work and assume any risks associated with Your exercise of
  142 +permissions under this License.
  143 +
  144 +8. Limitation of Liability.
  145 +
  146 +In no event and under no legal theory, whether in tort (including negligence),
  147 +contract, or otherwise, unless required by applicable law (such as deliberate
  148 +and grossly negligent acts) or agreed to in writing, shall any Contributor be
  149 +liable to You for damages, including any direct, indirect, special, incidental,
  150 +or consequential damages of any character arising as a result of this License or
  151 +out of the use or inability to use the Work (including but not limited to
  152 +damages for loss of goodwill, work stoppage, computer failure or malfunction, or
  153 +any and all other commercial damages or losses), even if such Contributor has
  154 +been advised of the possibility of such damages.
  155 +
  156 +9. Accepting Warranty or Additional Liability.
  157 +
  158 +While redistributing the Work or Derivative Works thereof, You may choose to
  159 +offer, and charge a fee for, acceptance of support, warranty, indemnity, or
  160 +other liability obligations and/or rights consistent with this License. However,
  161 +in accepting such obligations, You may act only on Your own behalf and on Your
  162 +sole responsibility, not on behalf of any other Contributor, and only if You
  163 +agree to indemnify, defend, and hold each Contributor harmless for any liability
  164 +incurred by, or claims asserted against, such Contributor by reason of your
  165 +accepting any such warranty or additional liability.
  166 +
  167 +END OF TERMS AND CONDITIONS
  168 +
  169 +APPENDIX: How to apply the Apache License to your work
  170 +
  171 +To apply the Apache License to your work, attach the following boilerplate
  172 +notice, with the fields enclosed by brackets "[]" replaced with your own
  173 +identifying information. (Don't include the brackets!) The text should be
  174 +enclosed in the appropriate comment syntax for the file format. We also
  175 +recommend that a file or class name and description of purpose be included on
  176 +the same "printed page" as the copyright notice for easier identification within
  177 +third-party archives.
  178 +
  179 + Copyright [yyyy] [name of copyright owner]
  180 +
  181 + Licensed under the Apache License, Version 2.0 (the "License");
  182 + you may not use this file except in compliance with the License.
  183 + You may obtain a copy of the License at
  184 +
  185 + http://www.apache.org/licenses/LICENSE-2.0
  186 +
  187 + Unless required by applicable law or agreed to in writing, software
  188 + distributed under the License is distributed on an "AS IS" BASIS,
  189 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  190 + See the License for the specific language governing permissions and
  191 + limitations under the License.
0 \ No newline at end of file 192 \ No newline at end of file
pom.xml 0 → 100644
  1 +++ a/pom.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  4 + http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 + <parent>
  7 + <groupId>org.smart4j</groupId>
  8 + <artifactId>smart-root</artifactId>
  9 + <version>1.0</version>
  10 + </parent>
  11 + <artifactId>smart-framework</artifactId>
  12 + <version>4.0.1</version>
  13 + <name>smart-framework</name>
  14 + <description>Smart Framework is a lightweight Java Web Framework</description>
  15 + <url>http://www.smart4j.org/</url>
  16 + <licenses>
  17 + <license>
  18 + <name>The Apache Software License, Version 2.0</name>
  19 + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
  20 + </license>
  21 + </licenses>
  22 + <properties>
  23 + <junit.version>4.11</junit.version>
  24 + <slf4j.version>1.7.5</slf4j.version>
  25 + <servlet.version>3.0.1</servlet.version>
  26 + <jackson.version>1.9.13</jackson.version>
  27 + <cglib.version>2.2.2</cglib.version>
  28 + <commons-lang.version>2.5</commons-lang.version>
  29 + <commons-collections.version>3.2</commons-collections.version>
  30 + <commons-beanutils.version>1.8.3</commons-beanutils.version>
  31 + <commons-dbcp.version>1.4</commons-dbcp.version>
  32 + <commons-dbutils.version>1.5.fix</commons-dbutils.version>
  33 + <commons-fileupload.version>1.3</commons-fileupload.version>
  34 + <commons-codec.version>1.8</commons-codec.version>
  35 + </properties>
  36 +
  37 + <dependencies>
  38 + <!-- JUnit -->
  39 + <dependency>
  40 + <groupId>junit</groupId>
  41 + <artifactId>junit</artifactId>
  42 + <version>${junit.version}</version>
  43 + <scope>provided</scope>
  44 + </dependency>
  45 + <!-- SLF4J -->
  46 + <dependency>
  47 + <groupId>org.slf4j</groupId>
  48 + <artifactId>slf4j-log4j12</artifactId>
  49 + <version>${slf4j.version}</version>
  50 + </dependency>
  51 + <!-- Servlet -->
  52 + <dependency>
  53 + <groupId>javax.servlet</groupId>
  54 + <artifactId>javax.servlet-api</artifactId>
  55 + <version>${servlet.version}</version>
  56 + <scope>provided</scope>
  57 + </dependency>
  58 + <!-- Jackson -->
  59 + <dependency>
  60 + <groupId>org.codehaus.jackson</groupId>
  61 + <artifactId>jackson-mapper-asl</artifactId>
  62 + <version>${jackson.version}</version>
  63 + </dependency>
  64 + <dependency>
  65 + <groupId>org.codehaus.jackson</groupId>
  66 + <artifactId>jackson-jaxrs</artifactId>
  67 + <version>${jackson.version}</version>
  68 + </dependency>
  69 + <!-- CGLib -->
  70 + <dependency>
  71 + <groupId>cglib</groupId>
  72 + <artifactId>cglib</artifactId>
  73 + <version>${cglib.version}</version>
  74 + </dependency>
  75 + <!-- Apache Commons -->
  76 + <dependency>
  77 + <groupId>commons-lang</groupId>
  78 + <artifactId>commons-lang</artifactId>
  79 + <version>${commons-lang.version}</version>
  80 + </dependency>
  81 + <dependency>
  82 + <groupId>commons-collections</groupId>
  83 + <artifactId>commons-collections</artifactId>
  84 + <version>${commons-collections.version}</version>
  85 + </dependency>
  86 + <dependency>
  87 + <groupId>commons-beanutils</groupId>
  88 + <artifactId>commons-beanutils</artifactId>
  89 + <version>${commons-beanutils.version}</version>
  90 + </dependency>
  91 + <dependency>
  92 + <groupId>commons-dbcp</groupId>
  93 + <artifactId>commons-dbcp</artifactId>
  94 + <version>${commons-dbcp.version}</version>
  95 + </dependency>
  96 + <dependency>
  97 + <groupId>commons-dbutils</groupId>
  98 + <artifactId>commons-dbutils</artifactId>
  99 + <version>${commons-dbutils.version}</version>
  100 + </dependency>
  101 + <dependency>
  102 + <groupId>commons-fileupload</groupId>
  103 + <artifactId>commons-fileupload</artifactId>
  104 + <version>${commons-fileupload.version}</version>
  105 + </dependency>
  106 + <dependency>
  107 + <groupId>commons-codec</groupId>
  108 + <artifactId>commons-codec</artifactId>
  109 + <version>${commons-codec.version}</version>
  110 + </dependency>
  111 + </dependencies>
  112 +
  113 +</project>
0 \ No newline at end of file 114 \ No newline at end of file
src/main/java/org/smart4j/framework/FrameworkConstant.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/FrameworkConstant.java
  1 +package org.smart4j.framework;
  2 +
  3 +import org.smart4j.framework.core.ConfigHelper;
  4 +
  5 +public interface FrameworkConstant {
  6 +
  7 + String UTF_8 = "UTF-8";
  8 +
  9 + String CONFIG_PROPS = "smart.properties";
  10 + String SQL_PROPS = "smart-sql.properties";
  11 +
  12 + String PLUGIN_PACKAGE = "org.smart4j.plugin";
  13 +
  14 + String JSP_PATH = ConfigHelper.getString("smart.framework.app.jsp_path", "/WEB-INF/jsp/");
  15 + String WWW_PATH = ConfigHelper.getString("smart.framework.app.www_path", "/www/");
  16 + String HOME_PAGE = ConfigHelper.getString("smart.framework.app.home_page", "/index.html");
  17 + int UPLOAD_LIMIT = ConfigHelper.getInt("smart.framework.app.upload_limit", 10);
  18 +
  19 + String PK_NAME = "id";
  20 +}
src/main/java/org/smart4j/framework/HelperLoader.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/HelperLoader.java
  1 +package org.smart4j.framework;
  2 +
  3 +import org.smart4j.framework.aop.AopHelper;
  4 +import org.smart4j.framework.dao.DatabaseHelper;
  5 +import org.smart4j.framework.ioc.BeanHelper;
  6 +import org.smart4j.framework.ioc.IocHelper;
  7 +import org.smart4j.framework.mvc.ActionHelper;
  8 +import org.smart4j.framework.orm.EntityHelper;
  9 +import org.smart4j.framework.plugin.PluginHelper;
  10 +import org.smart4j.framework.util.ClassUtil;
  11 +
  12 +/**
  13 + * 加载相应的 Helper 类
  14 + *
  15 + * @author huangyong
  16 + * @since 2.0
  17 + *
  18 + * 执行顺序:1
  19 + */
  20 +public final class HelperLoader {
  21 +
  22 + public static void init() {
  23 + // 定义需要加载的 Helper 类
  24 + Class<?>[] classList = {
  25 + //数据库
  26 + DatabaseHelper.class,
  27 + //表--类 对应关系
  28 + EntityHelper.class,
  29 + //
  30 + ActionHelper.class,
  31 + BeanHelper.class,
  32 + AopHelper.class,
  33 + IocHelper.class,
  34 + PluginHelper.class,
  35 + };
  36 + // 按照顺序加载类
  37 + for (Class<?> cls : classList) {
  38 + ClassUtil.loadClass(cls.getName());
  39 + }
  40 + }
  41 +}
src/main/java/org/smart4j/framework/InstanceFactory.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/InstanceFactory.java
  1 +package org.smart4j.framework;
  2 +
  3 +import java.util.Map;
  4 +import java.util.concurrent.ConcurrentHashMap;
  5 +import org.smart4j.framework.core.ClassScanner;
  6 +import org.smart4j.framework.core.ConfigHelper;
  7 +import org.smart4j.framework.core.impl.DefaultClassScanner;
  8 +import org.smart4j.framework.dao.DataAccessor;
  9 +import org.smart4j.framework.dao.impl.DefaultDataAccessor;
  10 +import org.smart4j.framework.ds.DataSourceFactory;
  11 +import org.smart4j.framework.ds.impl.DefaultDataSourceFactory;
  12 +import org.smart4j.framework.mvc.HandlerExceptionResolver;
  13 +import org.smart4j.framework.mvc.HandlerInvoker;
  14 +import org.smart4j.framework.mvc.HandlerMapping;
  15 +import org.smart4j.framework.mvc.ViewResolver;
  16 +import org.smart4j.framework.mvc.impl.DefaultHandlerExceptionResolver;
  17 +import org.smart4j.framework.mvc.impl.DefaultHandlerInvoker;
  18 +import org.smart4j.framework.mvc.impl.DefaultHandlerMapping;
  19 +import org.smart4j.framework.mvc.impl.DefaultViewResolver;
  20 +import org.smart4j.framework.util.ObjectUtil;
  21 +import org.smart4j.framework.util.StringUtil;
  22 +
  23 +/**
  24 + * 实例工厂
  25 + *
  26 + * @author huangyong
  27 + * @since 2.3
  28 + */
  29 +public class InstanceFactory {
  30 +
  31 + /**
  32 + * 用于缓存对应的实例
  33 + */
  34 + private static final Map<String, Object> cache = new ConcurrentHashMap<String, Object>();
  35 +
  36 + /**
  37 + * ClassScanner
  38 + */
  39 + private static final String CLASS_SCANNER = "smart.framework.custom.class_scanner";
  40 +
  41 + /**
  42 + * DataSourceFactory
  43 + */
  44 + private static final String DS_FACTORY = "smart.framework.custom.ds_factory";
  45 +
  46 + /**
  47 + * DataAccessor
  48 + */
  49 + private static final String DATA_ACCESSOR = "smart.framework.custom.data_accessor";
  50 +
  51 + /**
  52 + * HandlerMapping
  53 + */
  54 + private static final String HANDLER_MAPPING = "smart.framework.custom.handler_mapping";
  55 +
  56 + /**
  57 + * HandlerInvoker
  58 + */
  59 + private static final String HANDLER_INVOKER = "smart.framework.custom.handler_invoker";
  60 +
  61 + /**
  62 + * HandlerExceptionResolver
  63 + */
  64 + private static final String HANDLER_EXCEPTION_RESOLVER = "smart.framework.custom.handler_exception_resolver";
  65 +
  66 + /**
  67 + * ViewResolver
  68 + */
  69 + private static final String VIEW_RESOLVER = "smart.framework.custom.view_resolver";
  70 +
  71 + /**
  72 + * 获取 ClassScanner
  73 + */
  74 + public static ClassScanner getClassScanner() {
  75 + return getInstance(CLASS_SCANNER, DefaultClassScanner.class);
  76 + }
  77 +
  78 + /**
  79 + * 获取 DataSourceFactory
  80 + */
  81 + public static DataSourceFactory getDataSourceFactory() {
  82 + return getInstance(DS_FACTORY, DefaultDataSourceFactory.class);
  83 + }
  84 +
  85 + /**
  86 + * 获取 DataAccessor
  87 + */
  88 + public static DataAccessor getDataAccessor() {
  89 + return getInstance(DATA_ACCESSOR, DefaultDataAccessor.class);
  90 + }
  91 +
  92 + /**
  93 + * 获取 HandlerMapping
  94 + */
  95 + public static HandlerMapping getHandlerMapping() {
  96 + return getInstance(HANDLER_MAPPING, DefaultHandlerMapping.class);
  97 + }
  98 +
  99 + /**
  100 + * 获取 HandlerInvoker
  101 + */
  102 + public static HandlerInvoker getHandlerInvoker() {
  103 + return getInstance(HANDLER_INVOKER, DefaultHandlerInvoker.class);
  104 + }
  105 +
  106 + /**
  107 + * 获取 HandlerExceptionResolver
  108 + */
  109 + public static HandlerExceptionResolver getHandlerExceptionResolver() {
  110 + return getInstance(HANDLER_EXCEPTION_RESOLVER, DefaultHandlerExceptionResolver.class);
  111 + }
  112 +
  113 + /**
  114 + * 获取 ViewResolver
  115 + */
  116 + public static ViewResolver getViewResolver() {
  117 + return getInstance(VIEW_RESOLVER, DefaultViewResolver.class);
  118 + }
  119 +
  120 + @SuppressWarnings("unchecked")
  121 + public static <T> T getInstance(String cacheKey, Class<T> defaultImplClass) {
  122 + // 若缓存中存在对应的实例,则返回该实例
  123 + if (cache.containsKey(cacheKey)) {
  124 + return (T) cache.get(cacheKey);
  125 + }
  126 + // 从配置文件中获取相应的接口实现类配置
  127 + String implClassName = ConfigHelper.getString(cacheKey);
  128 + // 若实现类配置不存在,则使用默认实现类
  129 + if (StringUtil.isEmpty(implClassName)) {
  130 + implClassName = defaultImplClass.getName();
  131 + }
  132 + // 通过反射创建该实现类对应的实例
  133 + T instance = ObjectUtil.newInstance(implClassName);
  134 + // 若该实例不为空,则将其放入缓存
  135 + if (instance != null) {
  136 + cache.put(cacheKey, instance);
  137 + }
  138 + // 返回该实例
  139 + return instance;
  140 + }
  141 +}
src/main/java/org/smart4j/framework/aop/AopHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/aop/AopHelper.java
  1 +package org.smart4j.framework.aop;
  2 +
  3 +import java.lang.annotation.Annotation;
  4 +import java.util.ArrayList;
  5 +import java.util.Collections;
  6 +import java.util.Comparator;
  7 +import java.util.HashMap;
  8 +import java.util.LinkedHashMap;
  9 +import java.util.List;
  10 +import java.util.Map;
  11 +import org.smart4j.framework.FrameworkConstant;
  12 +import org.smart4j.framework.InstanceFactory;
  13 +import org.smart4j.framework.aop.annotation.Aspect;
  14 +import org.smart4j.framework.aop.annotation.AspectOrder;
  15 +import org.smart4j.framework.aop.proxy.Proxy;
  16 +import org.smart4j.framework.aop.proxy.ProxyManager;
  17 +import org.smart4j.framework.core.ClassHelper;
  18 +import org.smart4j.framework.core.ClassScanner;
  19 +import org.smart4j.framework.core.fault.InitializationError;
  20 +import org.smart4j.framework.ioc.BeanHelper;
  21 +import org.smart4j.framework.plugin.PluginProxy;
  22 +import org.smart4j.framework.tx.TransactionProxy;
  23 +import org.smart4j.framework.tx.annotation.Service;
  24 +import org.smart4j.framework.util.ClassUtil;
  25 +import org.smart4j.framework.util.CollectionUtil;
  26 +import org.smart4j.framework.util.StringUtil;
  27 +
  28 +/**
  29 + * 初始化 AOP 框架
  30 + *
  31 + * @author huangyong
  32 + * @since 1.0
  33 + */
  34 +public class AopHelper {
  35 +
  36 + /**
  37 + * 获取 ClassScanner
  38 + */
  39 + private static final ClassScanner classScanner = InstanceFactory.getClassScanner();
  40 +
  41 + static {
  42 + try {
  43 + // 创建 Proxy Map(用于 存放代理类 与 目标类列表 的映射关系)
  44 + Map<Class<?>, List<Class<?>>> proxyMap = createProxyMap();
  45 + // 创建 Target Map(用于 存放目标类 与 代理类列表 的映射关系)
  46 + Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);
  47 + // 遍历 Target Map
  48 + for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()) {
  49 + // 分别获取 map 中的 key 与 value
  50 + Class<?> targetClass = targetEntry.getKey();
  51 + List<Proxy> proxyList = targetEntry.getValue();
  52 + // 创建代理实例
  53 + Object proxyInstance = ProxyManager.createProxy(targetClass, proxyList);
  54 + // 用代理实例覆盖目标实例,并放入 Bean 容器中
  55 + BeanHelper.setBean(targetClass, proxyInstance);
  56 + }
  57 + } catch (Exception e) {
  58 + throw new InitializationError("初始化 AopHelper 出错!", e);
  59 + }
  60 + }
  61 +
  62 + private static Map<Class<?>, List<Class<?>>> createProxyMap() throws Exception {
  63 + Map<Class<?>, List<Class<?>>> proxyMap = new LinkedHashMap<Class<?>, List<Class<?>>>();
  64 + // 添加相关代理
  65 + addPluginProxy(proxyMap); // 插件代理
  66 + addAspectProxy(proxyMap); // 切面代理
  67 + addTransactionProxy(proxyMap); // 事务代理
  68 + return proxyMap;
  69 + }
  70 +
  71 + private static void addPluginProxy(Map<Class<?>, List<Class<?>>> proxyMap) throws Exception {
  72 + // 获取插件包名下父类为 PluginProxy 的所有类(插件代理类)
  73 + List<Class<?>> pluginProxyClassList = classScanner.getClassListBySuper(FrameworkConstant.PLUGIN_PACKAGE, PluginProxy.class);
  74 + if (CollectionUtil.isNotEmpty(pluginProxyClassList)) {
  75 + // 遍历所有插件代理类
  76 + for (Class<?> pluginProxyClass : pluginProxyClassList) {
  77 + // 创建插件代理类实例
  78 + PluginProxy pluginProxy = (PluginProxy) pluginProxyClass.newInstance();
  79 + // 将插件代理类及其所对应的目标类列表放入 Proxy Map 中
  80 + proxyMap.put(pluginProxyClass, pluginProxy.getTargetClassList());
  81 + }
  82 + }
  83 + }
  84 +
  85 + private static void addAspectProxy(Map<Class<?>, List<Class<?>>> proxyMap) throws Exception {
  86 + // 获取切面类(所有继承于 BaseAspect 的类)
  87 + List<Class<?>> aspectProxyClassList = ClassHelper.getClassListBySuper(AspectProxy.class);
  88 + // 添加插件包下所有的切面类
  89 + aspectProxyClassList.addAll(classScanner.getClassListBySuper(FrameworkConstant.PLUGIN_PACKAGE, AspectProxy.class));
  90 + // 排序切面类
  91 + sortAspectProxyClassList(aspectProxyClassList);
  92 + // 遍历切面类
  93 + for (Class<?> aspectProxyClass : aspectProxyClassList) {
  94 + // 判断 Aspect 注解是否存在
  95 + if (aspectProxyClass.isAnnotationPresent(Aspect.class)) {
  96 + // 获取 Aspect 注解
  97 + Aspect aspect = aspectProxyClass.getAnnotation(Aspect.class);
  98 + // 创建目标类列表
  99 + List<Class<?>> targetClassList = createTargetClassList(aspect);
  100 + // 初始化 Proxy Map
  101 + proxyMap.put(aspectProxyClass, targetClassList);
  102 + }
  103 + }
  104 + }
  105 +
  106 + private static void addTransactionProxy(Map<Class<?>, List<Class<?>>> proxyMap) {
  107 + // 使用 TransactionProxy 代理所有 Service 类
  108 + List<Class<?>> serviceClassList = ClassHelper.getClassListByAnnotation(Service.class);
  109 + proxyMap.put(TransactionProxy.class, serviceClassList);
  110 + }
  111 +
  112 + private static void sortAspectProxyClassList(List<Class<?>> proxyClassList) {
  113 + // 排序代理类列表
  114 + Collections.sort(proxyClassList, new Comparator<Class<?>>() {
  115 + @Override
  116 + public int compare(Class<?> aspect1, Class<?> aspect2) {
  117 + if (aspect1.isAnnotationPresent(AspectOrder.class) || aspect2.isAnnotationPresent(AspectOrder.class)) {
  118 + // 若有 Order 注解,则优先比较(序号的值越小越靠前)
  119 + if (aspect1.isAnnotationPresent(AspectOrder.class)) {
  120 + return getOrderValue(aspect1) - getOrderValue(aspect2);
  121 + } else {
  122 + return getOrderValue(aspect2) - getOrderValue(aspect1);
  123 + }
  124 + } else {
  125 + // 若无 Order 注解,则比较类名(按字母顺序升序排列)
  126 + return aspect1.hashCode() - aspect2.hashCode();
  127 + }
  128 + }
  129 +
  130 + private int getOrderValue(Class<?> aspect) {
  131 + return aspect.getAnnotation(AspectOrder.class) != null ? aspect.getAnnotation(AspectOrder.class).value() : 0;
  132 + }
  133 + });
  134 + }
  135 +
  136 + private static List<Class<?>> createTargetClassList(Aspect aspect) throws Exception {
  137 + List<Class<?>> targetClassList = new ArrayList<Class<?>>();
  138 + // 获取 Aspect 注解的相关属性
  139 + String pkg = aspect.pkg();
  140 + String cls = aspect.cls();
  141 + Class<? extends Annotation> annotation = aspect.annotation();
  142 + // 若包名不为空,则需进一步判断类名是否为空
  143 + if (StringUtil.isNotEmpty(pkg)) {
  144 + if (StringUtil.isNotEmpty(cls)) {
  145 + // 若类名不为空,则仅添加该类
  146 + targetClassList.add(ClassUtil.loadClass(pkg + "." + cls, false));
  147 + } else {
  148 + // 若注解不为空且不是 Aspect 注解,则添加指定包名下带有该注解的所有类
  149 + if (annotation != null && !annotation.equals(Aspect.class)) {
  150 + targetClassList.addAll(classScanner.getClassListByAnnotation(pkg, annotation));
  151 + } else {
  152 + // 否则添加该包名下所有类
  153 + targetClassList.addAll(classScanner.getClassList(pkg));
  154 + }
  155 + }
  156 + } else {
  157 + // 若注解不为空且不是 Aspect 注解,则添加应用包名下带有该注解的所有类
  158 + if (annotation != null && !annotation.equals(Aspect.class)) {
  159 + targetClassList.addAll(ClassHelper.getClassListByAnnotation(annotation));
  160 + }
  161 + }
  162 + return targetClassList;
  163 + }
  164 +
  165 + private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, List<Class<?>>> proxyMap) throws Exception {
  166 + Map<Class<?>, List<Proxy>> targetMap = new HashMap<Class<?>, List<Proxy>>();
  167 + // 遍历 Proxy Map
  168 + for (Map.Entry<Class<?>, List<Class<?>>> proxyEntry : proxyMap.entrySet()) {
  169 + // 分别获取 map 中的 key 与 value
  170 + Class<?> proxyClass = proxyEntry.getKey();
  171 + List<Class<?>> targetClassList = proxyEntry.getValue();
  172 + // 遍历目标类列表
  173 + for (Class<?> targetClass : targetClassList) {
  174 + // 创建代理类(切面类)实例
  175 + Proxy baseAspect = (Proxy) proxyClass.newInstance();
  176 + // 初始化 Target Map
  177 + if (targetMap.containsKey(targetClass)) {
  178 + targetMap.get(targetClass).add(baseAspect);
  179 + } else {
  180 + List<Proxy> baseAspectList = new ArrayList<Proxy>();
  181 + baseAspectList.add(baseAspect);
  182 + targetMap.put(targetClass, baseAspectList);
  183 + }
  184 + }
  185 + }
  186 + return targetMap;
  187 + }
  188 +}
src/main/java/org/smart4j/framework/aop/AspectProxy.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/aop/AspectProxy.java
  1 +package org.smart4j.framework.aop;
  2 +
  3 +import java.lang.reflect.Method;
  4 +import org.slf4j.Logger;
  5 +import org.slf4j.LoggerFactory;
  6 +import org.smart4j.framework.aop.proxy.Proxy;
  7 +import org.smart4j.framework.aop.proxy.ProxyChain;
  8 +
  9 +/**
  10 + * 切面代理
  11 + *
  12 + * @author huangyong
  13 + * @since 2.0
  14 + */
  15 +public abstract class AspectProxy implements Proxy {
  16 +
  17 + private static final Logger logger = LoggerFactory.getLogger(AspectProxy.class);
  18 +
  19 + @Override
  20 + public final Object doProxy(ProxyChain proxyChain) throws Throwable {
  21 + Object result = null;
  22 +
  23 + Class<?> cls = proxyChain.getTargetClass();
  24 + Method method = proxyChain.getTargetMethod();
  25 + Object[] params = proxyChain.getMethodParams();
  26 +
  27 + begin();
  28 + try {
  29 + if (intercept(cls, method, params)) {
  30 + before(cls, method, params);
  31 + result = proxyChain.doProxyChain();
  32 + after(cls, method, params, result);
  33 + } else {
  34 + result = proxyChain.doProxyChain();
  35 + }
  36 + } catch (Exception e) {
  37 + logger.error("AOP 异常", e);
  38 + error(cls, method, params, e);
  39 + throw e;
  40 + } finally {
  41 + end();
  42 + }
  43 +
  44 + return result;
  45 + }
  46 +
  47 + public void begin() {
  48 + }
  49 +
  50 + public boolean intercept(Class<?> cls, Method method, Object[] params) throws Throwable {
  51 + return true;
  52 + }
  53 +
  54 + public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
  55 + }
  56 +
  57 + public void after(Class<?> cls, Method method, Object[] params, Object result) throws Throwable {
  58 + }
  59 +
  60 + public void error(Class<?> cls, Method method, Object[] params, Throwable e) {
  61 + }
  62 +
  63 + public void end() {
  64 + }
  65 +}
src/main/java/org/smart4j/framework/aop/annotation/Aspect.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/aop/annotation/Aspect.java
  1 +package org.smart4j.framework.aop.annotation;
  2 +
  3 +import java.lang.annotation.Annotation;
  4 +import java.lang.annotation.ElementType;
  5 +import java.lang.annotation.Retention;
  6 +import java.lang.annotation.RetentionPolicy;
  7 +import java.lang.annotation.Target;
  8 +
  9 +/**
  10 + * 定义切面类
  11 + *
  12 + * @author huangyong
  13 + * @since 1.0
  14 + */
  15 +@Target(ElementType.TYPE)
  16 +@Retention(RetentionPolicy.RUNTIME)
  17 +public @interface Aspect {
  18 +
  19 + /**
  20 + * 包名
  21 + */
  22 + String pkg() default "";
  23 +
  24 + /**
  25 + * 类名
  26 + */
  27 + String cls() default "";
  28 +
  29 + /**
  30 + * 注解
  31 + *
  32 + * @since 2.2
  33 + */
  34 + Class<? extends Annotation> annotation() default Aspect.class;
  35 +}
src/main/java/org/smart4j/framework/aop/annotation/AspectOrder.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/aop/annotation/AspectOrder.java
  1 +package org.smart4j.framework.aop.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 定义切面顺序
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +@Target(ElementType.TYPE)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface AspectOrder {
  17 +
  18 + int value();
  19 +}
src/main/java/org/smart4j/framework/aop/proxy/Proxy.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/aop/proxy/Proxy.java
  1 +package org.smart4j.framework.aop.proxy;
  2 +
  3 +/**
  4 + * 代理接口
  5 + *
  6 + * @author huangyong
  7 + * @since 2.0
  8 + */
  9 +public interface Proxy {
  10 +
  11 + /**
  12 + * 执行链式代理
  13 + *
  14 + * @param proxyChain 代理链
  15 + * @return 目标方法返回值
  16 + * @throws Throwable 异常
  17 + */
  18 + Object doProxy(ProxyChain proxyChain) throws Throwable;
  19 +}
src/main/java/org/smart4j/framework/aop/proxy/ProxyChain.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/aop/proxy/ProxyChain.java
  1 +package org.smart4j.framework.aop.proxy;
  2 +
  3 +import java.lang.reflect.Method;
  4 +import java.util.ArrayList;
  5 +import java.util.List;
  6 +import net.sf.cglib.proxy.MethodProxy;
  7 +
  8 +/**
  9 + * 代理链
  10 + *
  11 + * @author huangyong
  12 + * @since 2.0
  13 + */
  14 +public class ProxyChain {
  15 +
  16 + private final Class<?> targetClass;
  17 + private final Object targetObject;
  18 + private final Method targetMethod;
  19 + private final MethodProxy methodProxy;
  20 + private final Object[] methodParams;
  21 +
  22 + private List<Proxy> proxyList = new ArrayList<Proxy>();
  23 + private int proxyIndex = 0;
  24 +
  25 + public ProxyChain(Class<?> targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List<Proxy> proxyList) {
  26 + this.targetClass = targetClass;
  27 + this.targetObject = targetObject;
  28 + this.targetMethod = targetMethod;
  29 + this.methodProxy = methodProxy;
  30 + this.methodParams = methodParams;
  31 + this.proxyList = proxyList;
  32 + }
  33 +
  34 + public Object[] getMethodParams() {
  35 + return methodParams;
  36 + }
  37 +
  38 + public Class<?> getTargetClass() {
  39 + return targetClass;
  40 + }
  41 +
  42 + public Method getTargetMethod() {
  43 + return targetMethod;
  44 + }
  45 +
  46 + public Object doProxyChain() throws Throwable {
  47 + Object methodResult;
  48 + if (proxyIndex < proxyList.size()) {
  49 + methodResult = proxyList.get(proxyIndex++).doProxy(this);
  50 + } else {
  51 + methodResult = methodProxy.invokeSuper(targetObject, methodParams);
  52 + }
  53 + return methodResult;
  54 + }
  55 +}
src/main/java/org/smart4j/framework/aop/proxy/ProxyManager.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/aop/proxy/ProxyManager.java
  1 +package org.smart4j.framework.aop.proxy;
  2 +
  3 +import java.lang.reflect.Method;
  4 +import java.util.List;
  5 +import net.sf.cglib.proxy.Enhancer;
  6 +import net.sf.cglib.proxy.MethodInterceptor;
  7 +import net.sf.cglib.proxy.MethodProxy;
  8 +
  9 +/**
  10 + * 代理管理器
  11 + *
  12 + * @author huangyong
  13 + * @since 2.0
  14 + */
  15 +public class ProxyManager {
  16 +
  17 + @SuppressWarnings("unchecked")
  18 + public static <T> T createProxy(final Class<?> targetClass, final List<Proxy> proxyList) {
  19 + return (T) Enhancer.create(targetClass, new MethodInterceptor() {
  20 + @Override
  21 + public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable {
  22 + return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList).doProxyChain();
  23 + }
  24 + });
  25 + }
  26 +}
src/main/java/org/smart4j/framework/core/ClassHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/ClassHelper.java
  1 +package org.smart4j.framework.core;
  2 +
  3 +import java.lang.annotation.Annotation;
  4 +import java.util.List;
  5 +import org.smart4j.framework.InstanceFactory;
  6 +
  7 +/**
  8 + * 根据条件获取相关类
  9 + *
  10 + * @author huangyong
  11 + * @since 1.0
  12 + */
  13 +public class ClassHelper {
  14 +
  15 + /**
  16 + * 获取基础包名
  17 + */
  18 + private static final String basePackage = ConfigHelper.getString("smart.framework.app.base_package");
  19 +
  20 + /**
  21 + * 获取 ClassScanner
  22 + */
  23 + private static final ClassScanner classScanner = InstanceFactory.getClassScanner();
  24 +
  25 + /**
  26 + * 获取基础包名中的所有类
  27 + */
  28 + public static List<Class<?>> getClassList() {
  29 + return classScanner.getClassList(basePackage);
  30 + }
  31 +
  32 + /**
  33 + * 获取基础包名中指定父类或接口的相关类
  34 + */
  35 + public static List<Class<?>> getClassListBySuper(Class<?> superClass) {
  36 + return classScanner.getClassListBySuper(basePackage, superClass);
  37 + }
  38 +
  39 + /**
  40 + * 获取基础包名中指定注解的相关类
  41 + */
  42 + public static List<Class<?>> getClassListByAnnotation(Class<? extends Annotation> annotationClass) {
  43 + return classScanner.getClassListByAnnotation(basePackage, annotationClass);
  44 + }
  45 +}
src/main/java/org/smart4j/framework/core/ClassScanner.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/ClassScanner.java
  1 +package org.smart4j.framework.core;
  2 +
  3 +import java.lang.annotation.Annotation;
  4 +import java.util.List;
  5 +
  6 +/**
  7 + * 类扫描器
  8 + *
  9 + * @author huangyong
  10 + * @since 2.3
  11 + */
  12 +public interface ClassScanner {
  13 +
  14 + /**
  15 + * 获取指定包名中的所有类
  16 + */
  17 + List<Class<?>> getClassList(String packageName);
  18 +
  19 + /**
  20 + * 获取指定包名中指定注解的相关类
  21 + */
  22 + List<Class<?>> getClassListByAnnotation(String packageName, Class<? extends Annotation> annotationClass);
  23 +
  24 + /**
  25 + * 获取指定包名中指定父类或接口的相关类
  26 + */
  27 + List<Class<?>> getClassListBySuper(String packageName, Class<?> superClass);
  28 +}
src/main/java/org/smart4j/framework/core/ConfigHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/ConfigHelper.java
  1 +package org.smart4j.framework.core;
  2 +
  3 +import java.util.Map;
  4 +import java.util.Properties;
  5 +import org.smart4j.framework.FrameworkConstant;
  6 +import org.smart4j.framework.util.PropsUtil;
  7 +
  8 +/**
  9 + * 获取属性文件中的属性值
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +public class ConfigHelper {
  15 +
  16 + /**
  17 + * 属性文件对象
  18 + */
  19 + private static final Properties configProps = PropsUtil.loadProps(FrameworkConstant.CONFIG_PROPS);
  20 +
  21 + /**
  22 + * 获取 String 类型的属性值
  23 + */
  24 + public static String getString(String key) {
  25 + return PropsUtil.getString(configProps, key);
  26 + }
  27 +
  28 + /**
  29 + * 获取 String 类型的属性值(可指定默认值)
  30 + */
  31 + public static String getString(String key, String defaultValue) {
  32 + return PropsUtil.getString(configProps, key, defaultValue);
  33 + }
  34 +
  35 + /**
  36 + * 获取 int 类型的属性值
  37 + */
  38 + public static int getInt(String key) {
  39 + return PropsUtil.getNumber(configProps, key);
  40 + }
  41 +
  42 + /**
  43 + * 获取 int 类型的属性值(可指定默认值)
  44 + */
  45 + public static int getInt(String key, int defaultValue) {
  46 + return PropsUtil.getNumber(configProps, key, defaultValue);
  47 + }
  48 +
  49 + /**
  50 + * 获取 boolean 类型的属性值
  51 + */
  52 + public static boolean getBoolean(String key) {
  53 + return PropsUtil.getBoolean(configProps, key);
  54 + }
  55 +
  56 + /**
  57 + * 获取 int 类型的属性值(可指定默认值)
  58 + */
  59 + public static boolean getBoolean(String key, boolean defaultValue) {
  60 + return PropsUtil.getBoolean(configProps, key, defaultValue);
  61 + }
  62 +
  63 + /**
  64 + * 获取指定前缀的相关属性
  65 + *
  66 + * @since 2.2
  67 + */
  68 + public static Map<String, Object> getMap(String prefix) {
  69 + return PropsUtil.getMap(configProps, prefix);
  70 + }
  71 +}
src/main/java/org/smart4j/framework/core/bean/BaseBean.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/bean/BaseBean.java
  1 +package org.smart4j.framework.core.bean;
  2 +
  3 +import java.io.Serializable;
  4 +import org.apache.commons.lang.builder.EqualsBuilder;
  5 +import org.apache.commons.lang.builder.HashCodeBuilder;
  6 +import org.apache.commons.lang.builder.ToStringBuilder;
  7 +import org.apache.commons.lang.builder.ToStringStyle;
  8 +
  9 +/**
  10 + * 提供 Bean 类的基础特性
  11 + *
  12 + * @author huangyong
  13 + * @since 1.0
  14 + */
  15 +public abstract class BaseBean implements Serializable {
  16 +
  17 + @Override
  18 + public int hashCode() {
  19 + return HashCodeBuilder.reflectionHashCode(this);
  20 + }
  21 +
  22 + @Override
  23 + public boolean equals(Object obj) {
  24 + return EqualsBuilder.reflectionEquals(this, obj);
  25 + }
  26 +
  27 + @Override
  28 + public String toString() {
  29 + return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
  30 + }
  31 +}
src/main/java/org/smart4j/framework/core/fault/InitializationError.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/fault/InitializationError.java
  1 +package org.smart4j.framework.core.fault;
  2 +
  3 +/**
  4 + * 初始化错误
  5 + *
  6 + * @author huangyong
  7 + * @since 2.2
  8 + */
  9 +public class InitializationError extends Error {
  10 +
  11 + public InitializationError() {
  12 + super();
  13 + }
  14 +
  15 + public InitializationError(String message) {
  16 + super(message);
  17 + }
  18 +
  19 + public InitializationError(String message, Throwable cause) {
  20 + super(message, cause);
  21 + }
  22 +
  23 + public InitializationError(Throwable cause) {
  24 + super(cause);
  25 + }
  26 +}
src/main/java/org/smart4j/framework/core/impl/DefaultClassScanner.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/impl/DefaultClassScanner.java
  1 +package org.smart4j.framework.core.impl;
  2 +
  3 +import java.lang.annotation.Annotation;
  4 +import java.util.List;
  5 +import org.smart4j.framework.core.ClassScanner;
  6 +import org.smart4j.framework.core.impl.support.AnnotationClassTemplate;
  7 +import org.smart4j.framework.core.impl.support.ClassTemplate;
  8 +import org.smart4j.framework.core.impl.support.SupperClassTemplate;
  9 +
  10 +/**
  11 + * 默认类扫描器
  12 + *
  13 + * @author huangyong
  14 + * @since 2.3
  15 + */
  16 +public class DefaultClassScanner implements ClassScanner {
  17 +
  18 + @Override
  19 + public List<Class<?>> getClassList(String packageName) {
  20 + return new ClassTemplate(packageName) {
  21 + @Override
  22 + public boolean checkAddClass(Class<?> cls) {
  23 + String className = cls.getName();
  24 + String pkgName = className.substring(0, className.lastIndexOf("."));
  25 + return pkgName.startsWith(packageName);
  26 + }
  27 + }.getClassList();
  28 + }
  29 +
  30 + @Override
  31 + public List<Class<?>> getClassListByAnnotation(String packageName, Class<? extends Annotation> annotationClass) {
  32 + return new AnnotationClassTemplate(packageName, annotationClass) {
  33 + @Override
  34 + public boolean checkAddClass(Class<?> cls) {
  35 + return cls.isAnnotationPresent(annotationClass);
  36 + }
  37 + }.getClassList();
  38 + }
  39 +
  40 + @Override
  41 + public List<Class<?>> getClassListBySuper(String packageName, Class<?> superClass) {
  42 + return new SupperClassTemplate(packageName, superClass) {
  43 + @Override
  44 + public boolean checkAddClass(Class<?> cls) {
  45 + return superClass.isAssignableFrom(cls) && !superClass.equals(cls);
  46 + }
  47 + }.getClassList();
  48 + }
  49 +}
src/main/java/org/smart4j/framework/core/impl/support/AnnotationClassTemplate.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/impl/support/AnnotationClassTemplate.java
  1 +package org.smart4j.framework.core.impl.support;
  2 +
  3 +import java.lang.annotation.Annotation;
  4 +
  5 +/**
  6 + * 用于获取注解类的模板类
  7 + *
  8 + * @author huangyong
  9 + * @since 2.3
  10 + */
  11 +public abstract class AnnotationClassTemplate extends ClassTemplate {
  12 +
  13 + protected final Class<? extends Annotation> annotationClass;
  14 +
  15 + protected AnnotationClassTemplate(String packageName, Class<? extends Annotation> annotationClass) {
  16 + super(packageName);
  17 + this.annotationClass = annotationClass;
  18 + }
  19 +}
src/main/java/org/smart4j/framework/core/impl/support/ClassTemplate.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/impl/support/ClassTemplate.java
  1 +package org.smart4j.framework.core.impl.support;
  2 +
  3 +import java.io.File;
  4 +import java.io.FileFilter;
  5 +import java.net.JarURLConnection;
  6 +import java.net.URL;
  7 +import java.util.ArrayList;
  8 +import java.util.Enumeration;
  9 +import java.util.List;
  10 +import java.util.jar.JarEntry;
  11 +import java.util.jar.JarFile;
  12 +import org.slf4j.Logger;
  13 +import org.slf4j.LoggerFactory;
  14 +import org.smart4j.framework.util.ClassUtil;
  15 +import org.smart4j.framework.util.StringUtil;
  16 +
  17 +/**
  18 + * 用于获取类的模板类
  19 + *
  20 + * @author huangyong
  21 + * @since 2.3
  22 + */
  23 +public abstract class ClassTemplate {
  24 +
  25 + private static final Logger logger = LoggerFactory.getLogger(ClassTemplate.class);
  26 +
  27 + protected final String packageName;
  28 +
  29 + protected ClassTemplate(String packageName) {
  30 + this.packageName = packageName;
  31 + }
  32 +
  33 + public final List<Class<?>> getClassList() {
  34 + List<Class<?>> classList = new ArrayList<Class<?>>();
  35 + try {
  36 + // 从包名获取 URL 类型的资源
  37 + Enumeration<URL> urls = ClassUtil.getClassLoader().getResources(packageName.replace(".", "/"));
  38 + // 遍历 URL 资源
  39 + while (urls.hasMoreElements()) {
  40 + URL url = urls.nextElement();
  41 + if (url != null) {
  42 + // 获取协议名(分为 file 与 jar)
  43 + String protocol = url.getProtocol();
  44 + if (protocol.equals("file")) {
  45 + // 若在 class 目录中,则执行添加类操作
  46 + String packagePath = url.getPath().replaceAll("%20", " ");
  47 + addClass(classList, packagePath, packageName);
  48 + } else if (protocol.equals("jar")) {
  49 + // 若在 jar 包中,则解析 jar 包中的 entry
  50 + JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
  51 + JarFile jarFile = jarURLConnection.getJarFile();
  52 + Enumeration<JarEntry> jarEntries = jarFile.entries();
  53 + while (jarEntries.hasMoreElements()) {
  54 + JarEntry jarEntry = jarEntries.nextElement();
  55 + String jarEntryName = jarEntry.getName();
  56 + // 判断该 entry 是否为 class
  57 + if (jarEntryName.endsWith(".class")) {
  58 + // 获取类名
  59 + String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
  60 + // 执行添加类操作
  61 + doAddClass(classList, className);
  62 + }
  63 + }
  64 + }
  65 + }
  66 + }
  67 + } catch (Exception e) {
  68 + logger.error("获取类出错!", e);
  69 + }
  70 + return classList;
  71 + }
  72 +
  73 + private void addClass(List<Class<?>> classList, String packagePath, String packageName) {
  74 + try {
  75 + // 获取包名路径下的 class 文件或目录
  76 + File[] files = new File(packagePath).listFiles(new FileFilter() {
  77 + @Override
  78 + public boolean accept(File file) {
  79 + return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
  80 + }
  81 + });
  82 + // 遍历文件或目录
  83 + for (File file : files) {
  84 + String fileName = file.getName();
  85 + // 判断是否为文件或目录
  86 + if (file.isFile()) {
  87 + // 获取类名
  88 + String className = fileName.substring(0, fileName.lastIndexOf("."));
  89 + if (StringUtil.isNotEmpty(packageName)) {
  90 + className = packageName + "." + className;
  91 + }
  92 + // 执行添加类操作
  93 + doAddClass(classList, className);
  94 + } else {
  95 + // 获取子包
  96 + String subPackagePath = fileName;
  97 + if (StringUtil.isNotEmpty(packagePath)) {
  98 + subPackagePath = packagePath + "/" + subPackagePath;
  99 + }
  100 + // 子包名
  101 + String subPackageName = fileName;
  102 + if (StringUtil.isNotEmpty(packageName)) {
  103 + subPackageName = packageName + "." + subPackageName;
  104 + }
  105 + // 递归调用
  106 + addClass(classList, subPackagePath, subPackageName);
  107 + }
  108 + }
  109 + } catch (Exception e) {
  110 + logger.error("添加类出错!", e);
  111 + }
  112 + }
  113 +
  114 + private void doAddClass(List<Class<?>> classList, String className) {
  115 + // 加载类
  116 + Class<?> cls = ClassUtil.loadClass(className, false);
  117 + // 判断是否可以添加类
  118 + if (checkAddClass(cls)) {
  119 + // 添加类
  120 + classList.add(cls);
  121 + }
  122 + }
  123 +
  124 + /**
  125 + * 验证是否允许添加类
  126 + */
  127 + public abstract boolean checkAddClass(Class<?> cls);
  128 +}
0 \ No newline at end of file 129 \ No newline at end of file
src/main/java/org/smart4j/framework/core/impl/support/SupperClassTemplate.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/core/impl/support/SupperClassTemplate.java
  1 +package org.smart4j.framework.core.impl.support;
  2 +
  3 +/**
  4 + * 用于获取子类的模板类
  5 + *
  6 + * @author huangyong
  7 + * @since 2.3
  8 + */
  9 +public abstract class SupperClassTemplate extends ClassTemplate {
  10 +
  11 + protected final Class<?> superClass;
  12 +
  13 + protected SupperClassTemplate(String packageName, Class<?> superClass) {
  14 + super(packageName);
  15 + this.superClass = superClass;
  16 + }
  17 +}
src/main/java/org/smart4j/framework/dao/DataAccessor.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/dao/DataAccessor.java
  1 +package org.smart4j.framework.dao;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +
  7 +/**
  8 + * 数据访问器
  9 + *
  10 + * @author huangyong
  11 + * @since 2.3
  12 + */
  13 +public interface DataAccessor {
  14 +
  15 + /**
  16 + * 查询对应的实体,返回单条记录
  17 + */
  18 + <T> T queryEntity(Class<T> entityClass, String sql, Object... params);
  19 +
  20 + /**
  21 + * 查询对应的实体列表,返回多条记录
  22 + */
  23 + <T> List<T> queryEntityList(Class<T> entityClass, String sql, Object... params);
  24 +
  25 + /**
  26 + * 查询对应的实体列表,返回单条记录(主键 => 实体)
  27 + */
  28 + <K, V> Map<K, V> queryEntityMap(Class<V> entityClass, String sql, Object... params);
  29 +
  30 + /**
  31 + * 查询对应的数据,返回单条记录
  32 + */
  33 + Object[] queryArray(String sql, Object... params);
  34 +
  35 + /**
  36 + * 查询对应的数据,返回多条记录
  37 + */
  38 + List<Object[]> queryArrayList(String sql, Object... params);
  39 +
  40 + /**
  41 + * 查询对应的数据,返回单条记录(列名 => 数据)
  42 + */
  43 + Map<String, Object> queryMap(String sql, Object... params);
  44 +
  45 + /**
  46 + * 查询对应的数据,返回多条记录(列名 => 数据)
  47 + */
  48 + List<Map<String, Object>> queryMapList(String sql, Object... params);
  49 +
  50 + /**
  51 + * 查询对应的数据,返回单条数据(列名 => 数据)
  52 + */
  53 + <T> T queryColumn(String sql, Object... params);
  54 +
  55 + /**
  56 + * 查询对应的数据,返回多条数据(列名 => 数据)
  57 + */
  58 + <T> List<T> queryColumnList(String sql, Object... params);
  59 +
  60 + /**
  61 + * 查询指定列名对应的数据,返回多条数据(列名对应的数据 => 列名与数据的映射关系)
  62 + */
  63 + <T> Map<T, Map<String, Object>> queryColumnMap(String column, String sql, Object... params);
  64 +
  65 + /**
  66 + * 查询记录条数,返回总记录数
  67 + */
  68 + long queryCount(String sql, Object... params);
  69 +
  70 + /**
  71 + * 执行更新操作(包括:update、insert、delete),返回所更新的记录数
  72 + */
  73 + int update(String sql, Object... params);
  74 +
  75 + /**
  76 + * 插入一条记录,返回插入后的主键
  77 + */
  78 + Serializable insertReturnPK(String sql, Object... params);
  79 +}
src/main/java/org/smart4j/framework/dao/DatabaseHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/dao/DatabaseHelper.java
  1 +package org.smart4j.framework.dao;
  2 +
  3 +import java.io.File;
  4 +import java.io.Serializable;
  5 +import java.sql.Connection;
  6 +import java.sql.SQLException;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +import javax.sql.DataSource;
  10 +import org.apache.commons.io.FileUtils;
  11 +import org.slf4j.Logger;
  12 +import org.slf4j.LoggerFactory;
  13 +import org.smart4j.framework.InstanceFactory;
  14 +import org.smart4j.framework.core.ConfigHelper;
  15 +import org.smart4j.framework.ds.DataSourceFactory;
  16 +import org.smart4j.framework.util.ClassUtil;
  17 +
  18 +/**
  19 + * 封装数据库相关操作
  20 + *
  21 + * @author huangyong
  22 + * @since 1.0
  23 + */
  24 +public class DatabaseHelper {
  25 +
  26 + private static final Logger logger = LoggerFactory.getLogger(DatabaseHelper.class);
  27 +
  28 + /**
  29 + * 定义一个局部线程变量(使每个线程都拥有自己的连接)
  30 + */
  31 + private static final ThreadLocal<Connection> connContainer = new ThreadLocal<Connection>();
  32 +
  33 + /**
  34 + * 获取数据源工厂
  35 + */
  36 + private static final DataSourceFactory dataSourceFactory = InstanceFactory.getDataSourceFactory();
  37 +
  38 + /**
  39 + * 获取数据访问器
  40 + */
  41 + private static final DataAccessor dataAccessor = InstanceFactory.getDataAccessor();
  42 +
  43 + /**
  44 + * 数据库类型
  45 + */
  46 + private static final String databaseType = ConfigHelper.getString("smart.framework.jdbc.type");
  47 +
  48 + /**
  49 + * 获取数据库类型
  50 + */
  51 + public static String getDatabaseType() {
  52 + return databaseType;
  53 + }
  54 +
  55 + /**
  56 + * 获取数据源
  57 + */
  58 + public static DataSource getDataSource() {
  59 + return dataSourceFactory.getDataSource();
  60 + }
  61 +
  62 + /**
  63 + * 获取数据库连接
  64 + */
  65 + public static Connection getConnection() {
  66 + Connection conn;
  67 + try {
  68 + // 先从 ThreadLocal 中获取 Connection
  69 + conn = connContainer.get();
  70 + if (conn == null) {
  71 + // 若不存在,则从 DataSource 中获取 Connection
  72 + conn = getDataSource().getConnection();
  73 + // 将 Connection 放入 ThreadLocal 中
  74 + if (conn != null) {
  75 + connContainer.set(conn);
  76 + }
  77 + }
  78 + } catch (SQLException e) {
  79 + logger.error("获取数据库连接出错!", e);
  80 + throw new RuntimeException(e);
  81 + }
  82 + return conn;
  83 + }
  84 +
  85 + /**
  86 + * 开启事务
  87 + */
  88 + public static void beginTransaction() {
  89 + Connection conn = getConnection();
  90 + if (conn != null) {
  91 + try {
  92 + conn.setAutoCommit(false);
  93 + } catch (SQLException e) {
  94 + logger.error("开启事务出错!", e);
  95 + throw new RuntimeException(e);
  96 + } finally {
  97 + connContainer.set(conn);
  98 + }
  99 + }
  100 + }
  101 +
  102 + /**
  103 + * 提交事务
  104 + */
  105 + public static void commitTransaction() {
  106 + Connection conn = getConnection();
  107 + if (conn != null) {
  108 + try {
  109 + conn.commit();
  110 + conn.close();
  111 + } catch (SQLException e) {
  112 + logger.error("提交事务出错!", e);
  113 + throw new RuntimeException(e);
  114 + } finally {
  115 + connContainer.remove();
  116 + }
  117 + }
  118 + }
  119 +
  120 + /**
  121 + * 回滚事务
  122 + */
  123 + public static void rollbackTransaction() {
  124 + Connection conn = getConnection();
  125 + if (conn != null) {
  126 + try {
  127 + conn.rollback();
  128 + conn.close();
  129 + } catch (SQLException e) {
  130 + logger.error("回滚事务出错!", e);
  131 + throw new RuntimeException(e);
  132 + } finally {
  133 + connContainer.remove();
  134 + }
  135 + }
  136 + }
  137 +
  138 + /**
  139 + * 初始化 SQL 脚本
  140 + */
  141 + public static void initSQL(String sqlPath) {
  142 + try {
  143 + File sqlFile = new File(ClassUtil.getClassPath() + sqlPath);
  144 + List<String> sqlList = FileUtils.readLines(sqlFile);
  145 + for (String sql : sqlList) {
  146 + update(sql);
  147 + }
  148 + } catch (Exception e) {
  149 + logger.error("初始化 SQL 脚本出错!", e);
  150 + throw new RuntimeException(e);
  151 + }
  152 + }
  153 +
  154 + /**
  155 + * 根据 SQL 语句查询 Entity
  156 + */
  157 + public static <T> T queryEntity(Class<T> entityClass, String sql, Object... params) {
  158 + return dataAccessor.queryEntity(entityClass, sql, params);
  159 + }
  160 +
  161 + /**
  162 + * 根据 SQL 语句查询 Entity 列表
  163 + */
  164 + public static <T> List<T> queryEntityList(Class<T> entityClass, String sql, Object... params) {
  165 + return dataAccessor.queryEntityList(entityClass, sql, params);
  166 + }
  167 +
  168 + /**
  169 + * 根据 SQL 语句查询 Entity 映射(Field Name => Field Value)
  170 + */
  171 + public static <K, V> Map<K, V> queryEntityMap(Class<V> entityClass, String sql, Object... params) {
  172 + return dataAccessor.queryEntityMap(entityClass, sql, params);
  173 + }
  174 +
  175 + /**
  176 + * 根据 SQL 语句查询 Array 格式的字段(单条记录)
  177 + */
  178 + public static Object[] queryArray(String sql, Object... params) {
  179 + return dataAccessor.queryArray(sql, params);
  180 + }
  181 +
  182 + /**
  183 + * 根据 SQL 语句查询 Array 格式的字段列表(多条记录)
  184 + */
  185 + public static List<Object[]> queryArrayList(String sql, Object... params) {
  186 + return dataAccessor.queryArrayList(sql, params);
  187 + }
  188 +
  189 + /**
  190 + * 根据 SQL 语句查询 Map 格式的字段(单条记录)
  191 + */
  192 + public static Map<String, Object> queryMap(String sql, Object... params) {
  193 + return dataAccessor.queryMap(sql, params);
  194 + }
  195 +
  196 + /**
  197 + * 根据 SQL 语句查询 Map 格式的字段列表(多条记录)
  198 + */
  199 + public static List<Map<String, Object>> queryMapList(String sql, Object... params) {
  200 + return dataAccessor.queryMapList(sql, params);
  201 + }
  202 +
  203 + /**
  204 + * 根据 SQL 语句查询指定字段(单条记录)
  205 + */
  206 + public static <T> T queryColumn(String sql, Object... params) {
  207 + return dataAccessor.queryColumn(sql, params);
  208 + }
  209 +
  210 + /**
  211 + * 根据 SQL 语句查询指定字段列表(多条记录)
  212 + */
  213 + public static <T> List<T> queryColumnList(String sql, Object... params) {
  214 + return dataAccessor.queryColumnList(sql, params);
  215 + }
  216 +
  217 + /**
  218 + * 根据 SQL 语句查询指定字段映射(多条记录)
  219 + */
  220 + public static <T> Map<T, Map<String, Object>> queryColumnMap(String column, String sql, Object... params) {
  221 + return dataAccessor.queryColumnMap(column, sql, params);
  222 + }
  223 +
  224 + /**
  225 + * 根据 SQL 语句查询记录条数
  226 + */
  227 + public static long queryCount(String sql, Object... params) {
  228 + return dataAccessor.queryCount(sql, params);
  229 + }
  230 +
  231 + /**
  232 + * 执行更新语句(包括:update、insert、delete)
  233 + */
  234 + public static int update(String sql, Object... params) {
  235 + return dataAccessor.update(sql, params);
  236 + }
  237 +
  238 + /**
  239 + * 执行插入语句,返回插入后的主键
  240 + */
  241 + public static Serializable insertReturnPK(String sql, Object... params) {
  242 + return dataAccessor.insertReturnPK(sql, params);
  243 + }
  244 +}
src/main/java/org/smart4j/framework/dao/SqlHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/dao/SqlHelper.java
  1 +package org.smart4j.framework.dao;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.Map;
  5 +import java.util.Properties;
  6 +import org.smart4j.framework.FrameworkConstant;
  7 +import org.smart4j.framework.orm.EntityHelper;
  8 +import org.smart4j.framework.util.CollectionUtil;
  9 +import org.smart4j.framework.util.MapUtil;
  10 +import org.smart4j.framework.util.PropsUtil;
  11 +import org.smart4j.framework.util.StringUtil;
  12 +
  13 +/**
  14 + * 封装 SQL 语句相关操作
  15 + *
  16 + * @author huangyong
  17 + * @since 1.0
  18 + */
  19 +public class SqlHelper {
  20 +
  21 + /**
  22 + * SQL 属性文件对象
  23 + */
  24 + private static final Properties sqlProps = PropsUtil.loadProps(FrameworkConstant.SQL_PROPS);
  25 +
  26 + /**
  27 + * 从 SQL 属性文件中获取相应的 SQL 语句
  28 + */
  29 + public static String getSql(String key) {
  30 + String sql;
  31 + if (sqlProps.containsKey(key)) {
  32 + sql = sqlProps.getProperty(key);
  33 + } else {
  34 + throw new RuntimeException("无法在 " + FrameworkConstant.SQL_PROPS + " 文件中获取属性:" + key);
  35 + }
  36 + return sql;
  37 + }
  38 +
  39 + /**
  40 + * 生成 select 语句
  41 + */
  42 + public static String generateSelectSql(Class<?> entityClass, String condition, String sort) {
  43 + StringBuilder sql = new StringBuilder("select * from ").append(getTable(entityClass));
  44 + sql.append(generateWhere(condition));
  45 + sql.append(generateOrder(sort));
  46 + return sql.toString();
  47 + }
  48 +
  49 + /**
  50 + * 生成 insert 语句
  51 + */
  52 + public static String generateInsertSql(Class<?> entityClass, Collection<String> fieldNames) {
  53 + StringBuilder sql = new StringBuilder("insert into ").append(getTable(entityClass));
  54 + if (CollectionUtil.isNotEmpty(fieldNames)) {
  55 + int i = 0;
  56 + StringBuilder columns = new StringBuilder(" ");
  57 + StringBuilder values = new StringBuilder(" values ");
  58 + for (String fieldName : fieldNames) {
  59 + String columnName = EntityHelper.getColumnName(entityClass, fieldName);
  60 + if (i == 0) {
  61 + columns.append("(").append(columnName);
  62 + values.append("(?");
  63 + } else {
  64 + columns.append(", ").append(columnName);
  65 + values.append(", ?");
  66 + }
  67 + if (i == fieldNames.size() - 1) {
  68 + columns.append(")");
  69 + values.append(")");
  70 + }
  71 + i++;
  72 + }
  73 + sql.append(columns).append(values);
  74 + }
  75 + return sql.toString();
  76 + }
  77 +
  78 + /**
  79 + * 生成 delete 语句
  80 + */
  81 + public static String generateDeleteSql(Class<?> entityClass, String condition) {
  82 + StringBuilder sql = new StringBuilder("delete from ").append(getTable(entityClass));
  83 + sql.append(generateWhere(condition));
  84 + return sql.toString();
  85 + }
  86 +
  87 + /**
  88 + * 生成 update 语句
  89 + */
  90 + public static String generateUpdateSql(Class<?> entityClass, Map<String, Object> fieldMap, String condition) {
  91 + StringBuilder sql = new StringBuilder("update ").append(getTable(entityClass));
  92 + if (MapUtil.isNotEmpty(fieldMap)) {
  93 + sql.append(" set ");
  94 + int i = 0;
  95 + for (Map.Entry<String, Object> fieldEntry : fieldMap.entrySet()) {
  96 + String fieldName = fieldEntry.getKey();
  97 + String columnName = EntityHelper.getColumnName(entityClass, fieldName);
  98 + if (i == 0) {
  99 + sql.append(columnName).append(" = ?");
  100 + } else {
  101 + sql.append(", ").append(columnName).append(" = ?");
  102 + }
  103 + i++;
  104 + }
  105 + }
  106 + sql.append(generateWhere(condition));
  107 + return sql.toString();
  108 + }
  109 +
  110 + /**
  111 + * 生成 select count(*) 语句
  112 + */
  113 + public static String generateSelectSqlForCount(Class<?> entityClass, String condition) {
  114 + StringBuilder sql = new StringBuilder("select count(*) from ").append(getTable(entityClass));
  115 + sql.append(generateWhere(condition));
  116 + return sql.toString();
  117 + }
  118 +
  119 + /**
  120 + * 生成 select 分页语句(数据库类型为:mysql、oracle、mssql)
  121 + */
  122 + public static String generateSelectSqlForPager(int pageNumber, int pageSize, Class<?> entityClass, String condition, String sort) {
  123 + StringBuilder sql = new StringBuilder();
  124 + String table = getTable(entityClass);
  125 + String where = generateWhere(condition);
  126 + String order = generateOrder(sort);
  127 + String dbType = DatabaseHelper.getDatabaseType();
  128 + if (dbType.equalsIgnoreCase("mysql")) {
  129 + int pageStart = (pageNumber - 1) * pageSize;
  130 + appendSqlForMySql(sql, table, where, order, pageStart, pageSize);
  131 + } else if (dbType.equalsIgnoreCase("oracle")) {
  132 + int pageStart = (pageNumber - 1) * pageSize + 1;
  133 + int pageEnd = pageStart + pageSize;
  134 + appendSqlForOracle(sql, table, where, order, pageStart, pageEnd);
  135 + } else if (dbType.equalsIgnoreCase("mssql")) {
  136 + int pageStart = (pageNumber - 1) * pageSize;
  137 + appendSqlForMsSql(sql, table, where, order, pageStart, pageSize);
  138 + }
  139 + return sql.toString();
  140 + }
  141 +
  142 + private static String getTable(Class<?> entityClass) {
  143 + return EntityHelper.getTableName(entityClass);
  144 + }
  145 +
  146 + private static String generateWhere(String condition) {
  147 + String where = "";
  148 + if (StringUtil.isNotEmpty(condition)) {
  149 + where += " where " + condition;
  150 + }
  151 + return where;
  152 + }
  153 +
  154 + private static String generateOrder(String sort) {
  155 + String order = "";
  156 + if (StringUtil.isNotEmpty(sort)) {
  157 + order += " order by " + sort;
  158 + }
  159 + return order;
  160 + }
  161 +
  162 + private static void appendSqlForMySql(StringBuilder sql, String table, String where, String order, int pageStart, int pageEnd) {
  163 + /*
  164 + select * from 表名 where 条件 order by 排序 limit 开始位置, 结束位置
  165 + */
  166 + sql.append("select * from ").append(table);
  167 + sql.append(where);
  168 + sql.append(order);
  169 + sql.append(" limit ").append(pageStart).append(", ").append(pageEnd);
  170 + }
  171 +
  172 + private static void appendSqlForOracle(StringBuilder sql, String table, String where, String order, int pageStart, int pageEnd) {
  173 + /*
  174 + select a.* from (
  175 + select rownum rn, t.* from 表名 t where 条件 order by 排序
  176 + ) a
  177 + where a.rn >= 开始位置 and a.rn < 结束位置
  178 + */
  179 + sql.append("select a.* from (select rownum rn, t.* from ").append(table).append(" t");
  180 + sql.append(where);
  181 + sql.append(order);
  182 + sql.append(") a where a.rn >= ").append(pageStart).append(" and a.rn < ").append(pageEnd);
  183 + }
  184 +
  185 + private static void appendSqlForMsSql(StringBuilder sql, String table, String where, String order, int pageStart, int pageEnd) {
  186 + /*
  187 + select top 结束位置 * from 表名 where 条件 and id not in (
  188 + select top 开始位置 id from 表名 where 条件 order by 排序
  189 + ) order by 排序
  190 + */
  191 + sql.append("select top ").append(pageEnd).append(" * from ").append(table);
  192 + if (StringUtil.isNotEmpty(where)) {
  193 + sql.append(where).append(" and ");
  194 + } else {
  195 + sql.append(" where ");
  196 + }
  197 + sql.append("id not in (select top ").append(pageStart).append(" id from ").append(table);
  198 + sql.append(where);
  199 + sql.append(order);
  200 + sql.append(") ").append(order);
  201 + }
  202 +}
src/main/java/org/smart4j/framework/dao/bean/Pager.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/dao/bean/Pager.java
  1 +package org.smart4j.framework.dao.bean;
  2 +
  3 +import java.util.List;
  4 +import org.smart4j.framework.core.bean.BaseBean;
  5 +
  6 +/**
  7 + * 分页对象
  8 + *
  9 + * @author huangyong
  10 + * @since 1.0
  11 + */
  12 +public class Pager<T> extends BaseBean {
  13 +
  14 + private int pageNumber; // 页面编号
  15 + private int pageSize; // 每页条数
  16 + private long totalRecord; // 总记录数
  17 + private long totalPage; // 总页面数
  18 + private int next_cursor; // 下一页页标
  19 + private List<T> recordList; // 数据列表
  20 +
  21 + public Pager() {
  22 + }
  23 +
  24 + public Pager(int pageNumber, int pageSize, long totalRecord, List<T> recordList) {
  25 + this.pageNumber = pageNumber;
  26 + this.pageSize = pageSize;
  27 + this.totalRecord = totalRecord;
  28 + this.recordList = recordList;
  29 + if (pageSize != 0) {
  30 + totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize : totalRecord / pageSize + 1;
  31 + }
  32 + if (pageNumber < totalPage) {
  33 + this.next_cursor = pageNumber + 1;
  34 + }
  35 + }
  36 +
  37 + public int getNext_cursor() {
  38 + return next_cursor;
  39 + }
  40 +
  41 + public int getPageNumber() {
  42 + return pageNumber;
  43 + }
  44 +
  45 + public int getPageSize() {
  46 + return pageSize;
  47 + }
  48 +
  49 + public long getTotalRecord() {
  50 + return totalRecord;
  51 + }
  52 +
  53 + public long getTotalPage() {
  54 + return totalPage;
  55 + }
  56 +
  57 + public List<T> getRecordList() {
  58 + return recordList;
  59 + }
  60 +
  61 + public boolean isFirstPage() {
  62 + return pageNumber == 1;
  63 + }
  64 +
  65 + public boolean isLastPage() {
  66 + return pageNumber == totalPage;
  67 + }
  68 +
  69 + public boolean isPrevPage() {
  70 + return pageNumber > 1 && pageNumber <= totalPage;
  71 + }
  72 +
  73 + public boolean isNextPage() {
  74 + return pageNumber < totalPage;
  75 + }
  76 +}
src/main/java/org/smart4j/framework/dao/impl/DefaultDataAccessor.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/dao/impl/DefaultDataAccessor.java
  1 +package org.smart4j.framework.dao.impl;
  2 +
  3 +import java.io.Serializable;
  4 +import java.sql.Connection;
  5 +import java.sql.PreparedStatement;
  6 +import java.sql.ResultSet;
  7 +import java.sql.SQLException;
  8 +import java.util.List;
  9 +import java.util.Map;
  10 +
  11 +import javax.sql.DataSource;
  12 +
  13 +import org.apache.commons.dbutils.BasicRowProcessor;
  14 +import org.apache.commons.dbutils.BeanProcessor;
  15 +import org.apache.commons.dbutils.QueryRunner;
  16 +import org.apache.commons.dbutils.handlers.ArrayHandler;
  17 +import org.apache.commons.dbutils.handlers.ArrayListHandler;
  18 +import org.apache.commons.dbutils.handlers.BeanHandler;
  19 +import org.apache.commons.dbutils.handlers.BeanListHandler;
  20 +import org.apache.commons.dbutils.handlers.BeanMapHandler;
  21 +import org.apache.commons.dbutils.handlers.ColumnListHandler;
  22 +import org.apache.commons.dbutils.handlers.KeyedHandler;
  23 +import org.apache.commons.dbutils.handlers.MapHandler;
  24 +import org.apache.commons.dbutils.handlers.MapListHandler;
  25 +import org.apache.commons.dbutils.handlers.ScalarHandler;
  26 +import org.slf4j.Logger;
  27 +import org.slf4j.LoggerFactory;
  28 +import org.smart4j.framework.dao.DataAccessor;
  29 +import org.smart4j.framework.dao.DatabaseHelper;
  30 +import org.smart4j.framework.orm.EntityHelper;
  31 +import org.smart4j.framework.util.ArrayUtil;
  32 +import org.smart4j.framework.util.MapUtil;
  33 +
  34 +/**
  35 + * 默认数据访问器 <br/>
  36 + * 基于 Apache Commons DbUtils 实现
  37 + *
  38 + * @author huangyong
  39 + * @since 2.3
  40 + */
  41 +public class DefaultDataAccessor implements DataAccessor {
  42 +
  43 + private static final Logger logger = LoggerFactory.getLogger(DefaultDataAccessor.class);
  44 +
  45 + private final QueryRunner queryRunner;
  46 +
  47 + public DefaultDataAccessor() {
  48 + DataSource dataSource = DatabaseHelper.getDataSource();
  49 + queryRunner = new QueryRunner(dataSource);
  50 + }
  51 +
  52 + @Override
  53 + public <T> T queryEntity(Class<T> entityClass, String sql, Object... params) {
  54 + T result;
  55 + try {
  56 + Map<String, String> columnMap = EntityHelper.getColumnMap(entityClass);
  57 + if (MapUtil.isNotEmpty(columnMap)) {
  58 + result = queryRunner.query(sql, new BeanHandler<T>(entityClass, new BasicRowProcessor(new BeanProcessor(columnMap))), params);
  59 + } else {
  60 + result = queryRunner.query(sql, new BeanHandler<T>(entityClass), params);
  61 + }
  62 + } catch (SQLException e) {
  63 + logger.error("查询出错!", e);
  64 + throw new RuntimeException(e);
  65 + }
  66 + printSQL(sql);
  67 + return result;
  68 + }
  69 +
  70 + @Override
  71 + public <T> List<T> queryEntityList(Class<T> entityClass, String sql, Object... params) {
  72 + List<T> result;
  73 + try {
  74 + Map<String, String> columnMap = EntityHelper.getColumnMap(entityClass);
  75 + if (MapUtil.isNotEmpty(columnMap)) {
  76 + result = queryRunner.query(sql, new BeanListHandler<T>(entityClass, new BasicRowProcessor(new BeanProcessor(columnMap))), params);
  77 + } else {
  78 + result = queryRunner.query(sql, new BeanListHandler<T>(entityClass), params);
  79 + }
  80 + } catch (SQLException e) {
  81 + logger.error("查询出错!", e);
  82 + throw new RuntimeException(e);
  83 + }
  84 + printSQL(sql);
  85 + return result;
  86 + }
  87 +
  88 + @Override
  89 + public <K, V> Map<K, V> queryEntityMap(Class<V> entityClass, String sql, Object... params) {
  90 + Map<K, V> entityMap;
  91 + try {
  92 + entityMap = queryRunner.query(sql, new BeanMapHandler<K, V>(entityClass), params);
  93 + } catch (SQLException e) {
  94 + logger.error("查询出错!", e);
  95 + throw new RuntimeException(e);
  96 + }
  97 + printSQL(sql);
  98 + return entityMap;
  99 + }
  100 +
  101 + @Override
  102 + public Object[] queryArray(String sql, Object... params) {
  103 + Object[] array;
  104 + try {
  105 + array = queryRunner.query(sql, new ArrayHandler(), params);
  106 + } catch (SQLException e) {
  107 + logger.error("查询出错!", e);
  108 + throw new RuntimeException(e);
  109 + }
  110 + printSQL(sql);
  111 + return array;
  112 + }
  113 +
  114 + @Override
  115 + public List<Object[]> queryArrayList(String sql, Object... params) {
  116 + List<Object[]> arrayList;
  117 + try {
  118 + arrayList = queryRunner.query(sql, new ArrayListHandler(), params);
  119 + } catch (SQLException e) {
  120 + logger.error("查询出错!", e);
  121 + throw new RuntimeException(e);
  122 + }
  123 + printSQL(sql);
  124 + return arrayList;
  125 + }
  126 +
  127 + @Override
  128 + public Map<String, Object> queryMap(String sql, Object... params) {
  129 + Map<String, Object> map;
  130 + try {
  131 + map = queryRunner.query(sql, new MapHandler(), params);
  132 + } catch (SQLException e) {
  133 + logger.error("查询出错!", e);
  134 + throw new RuntimeException(e);
  135 + }
  136 + printSQL(sql);
  137 + return map;
  138 + }
  139 +
  140 + @Override
  141 + public List<Map<String, Object>> queryMapList(String sql, Object... params) {
  142 + List<Map<String, Object>> fieldMapList;
  143 + try {
  144 + fieldMapList = queryRunner.query(sql, new MapListHandler(), params);
  145 + } catch (SQLException e) {
  146 + logger.error("查询出错!", e);
  147 + throw new RuntimeException(e);
  148 + }
  149 + printSQL(sql);
  150 + return fieldMapList;
  151 + }
  152 +
  153 + @Override
  154 + public <T> T queryColumn(String sql, Object... params) {
  155 + T obj;
  156 + try {
  157 + obj = queryRunner.query(sql, new ScalarHandler<T>(), params);
  158 + } catch (SQLException e) {
  159 + logger.error("查询出错!", e);
  160 + throw new RuntimeException(e);
  161 + }
  162 + printSQL(sql);
  163 + return obj;
  164 + }
  165 +
  166 + @Override
  167 + public <T> List<T> queryColumnList(String sql, Object... params) {
  168 + List<T> list;
  169 + try {
  170 + list = queryRunner.query(sql, new ColumnListHandler<T>(), params);
  171 + } catch (SQLException e) {
  172 + logger.error("查询出错!", e);
  173 + throw new RuntimeException(e);
  174 + }
  175 + printSQL(sql);
  176 + return list;
  177 + }
  178 +
  179 + @Override
  180 + public <T> Map<T, Map<String, Object>> queryColumnMap(String column, String sql, Object... params) {
  181 + Map<T, Map<String, Object>> map;
  182 + try {
  183 + map = queryRunner.query(sql, new KeyedHandler<T>(column), params);
  184 + } catch (SQLException e) {
  185 + logger.error("查询出错!", e);
  186 + throw new RuntimeException(e);
  187 + }
  188 + printSQL(sql);
  189 + return map;
  190 + }
  191 +
  192 + @Override
  193 + public long queryCount(String sql, Object... params) {
  194 + long result;
  195 + try {
  196 + result = queryRunner.query(sql, new ScalarHandler<Long>("count(*)"), params);
  197 + } catch (SQLException e) {
  198 + logger.error("查询出错!", e);
  199 + throw new RuntimeException(e);
  200 + }
  201 + printSQL(sql);
  202 + return result;
  203 + }
  204 +
  205 + @Override
  206 + public int update(String sql, Object... params) {
  207 + int result;
  208 + try {
  209 + // Connection conn = DatabaseHelper.getConnection();
  210 + result = queryRunner.update(sql, params);
  211 + } catch (SQLException e) {
  212 + logger.error("更新出错!", e);
  213 + throw new RuntimeException(e);
  214 + }
  215 + printSQL(sql);
  216 + return result;
  217 + }
  218 +
  219 + @Override
  220 + public Serializable insertReturnPK(String sql, Object... params) {
  221 + Serializable key = null;
  222 + ResultSet rs = null;
  223 + Connection conn = null;
  224 + PreparedStatement pstmt = null;
  225 + try {
  226 + conn = DatabaseHelper.getConnection();
  227 + pstmt = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
  228 + if (ArrayUtil.isNotEmpty(params)) {
  229 + for (int i = 0; i < params.length; i++) {
  230 + pstmt.setObject(i + 1, params[i]);
  231 + }
  232 + }
  233 + int rows = pstmt.executeUpdate();
  234 + if (rows == 1) {
  235 + rs = pstmt.getGeneratedKeys();
  236 + if (rs.next()) {
  237 + key = (Serializable) rs.getObject(1);
  238 + }
  239 + }
  240 + } catch (SQLException e) {
  241 + logger.error("插入出错!", e);
  242 + throw new RuntimeException(e);
  243 + } finally {
  244 +// try {
  245 +// if (rs != null) {
  246 +// rs.close();
  247 +// }
  248 +// if (pstmt != null) {
  249 +// pstmt.close();
  250 +// }
  251 +// if (conn != null) {
  252 +// conn.close();
  253 +// }
  254 +// } catch (SQLException e) {
  255 +// e.printStackTrace();
  256 +// }
  257 + }
  258 + printSQL(sql);
  259 + return key;
  260 + }
  261 +
  262 + private static void printSQL(String sql) {
  263 + logger.debug("[Smart] SQL - {}", sql);
  264 + }
  265 +}
src/main/java/org/smart4j/framework/ds/DataSourceFactory.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/ds/DataSourceFactory.java
  1 +package org.smart4j.framework.ds;
  2 +
  3 +import javax.sql.DataSource;
  4 +
  5 +/**
  6 + * 数据源工厂
  7 + *
  8 + * @author huangyong
  9 + * @since 2.3
  10 + */
  11 +public interface DataSourceFactory {
  12 +
  13 + /**
  14 + * 获取数据源
  15 + *
  16 + * @return 数据源
  17 + */
  18 + DataSource getDataSource();
  19 +}
src/main/java/org/smart4j/framework/ds/impl/AbstractDataSourceFactory.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/ds/impl/AbstractDataSourceFactory.java
  1 +package org.smart4j.framework.ds.impl;
  2 +
  3 +import javax.sql.DataSource;
  4 +import org.smart4j.framework.core.ConfigHelper;
  5 +import org.smart4j.framework.ds.DataSourceFactory;
  6 +
  7 +/**
  8 + * 抽象数据源工厂
  9 + *
  10 + * @author huangyong
  11 + * @since 2.3
  12 + */
  13 +public abstract class AbstractDataSourceFactory<T extends DataSource> implements DataSourceFactory {
  14 +
  15 + protected final String driver = ConfigHelper.getString("smart.framework.jdbc.driver");
  16 + protected final String url = ConfigHelper.getString("smart.framework.jdbc.url");
  17 + protected final String username = ConfigHelper.getString("smart.framework.jdbc.username");
  18 + protected final String password = ConfigHelper.getString("smart.framework.jdbc.password");
  19 +
  20 + @Override
  21 + public final T getDataSource() {
  22 + // 创建数据源对象
  23 + T ds = createDataSource();
  24 + // 设置基础属性
  25 + setDriver(ds, driver);
  26 + setUrl(ds, url);
  27 + setUsername(ds, username);
  28 + setPassword(ds, password);
  29 + // 设置高级属性
  30 + setAdvancedConfig(ds);
  31 + return ds;
  32 + }
  33 +
  34 + public abstract T createDataSource();
  35 +
  36 + public abstract void setDriver(T ds, String driver);
  37 +
  38 + public abstract void setUrl(T ds, String url);
  39 +
  40 + public abstract void setUsername(T ds, String username);
  41 +
  42 + public abstract void setPassword(T ds, String password);
  43 +
  44 + public abstract void setAdvancedConfig(T ds);
  45 +}
src/main/java/org/smart4j/framework/ds/impl/DefaultDataSourceFactory.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/ds/impl/DefaultDataSourceFactory.java
  1 +package org.smart4j.framework.ds.impl;
  2 +
  3 +import org.apache.commons.dbcp.BasicDataSource;
  4 +
  5 +/**
  6 + * 默认数据源工厂 <br/>
  7 + * 基于 Apache Commons DBCP 实现
  8 + *
  9 + * @author huangyong
  10 + * @since 2.3
  11 + */
  12 +public class DefaultDataSourceFactory extends AbstractDataSourceFactory<BasicDataSource> {
  13 +
  14 + @Override
  15 + public BasicDataSource createDataSource() {
  16 + return new BasicDataSource();
  17 + }
  18 +
  19 + @Override
  20 + public void setDriver(BasicDataSource ds, String driver) {
  21 + ds.setDriverClassName(driver);
  22 + }
  23 +
  24 + @Override
  25 + public void setUrl(BasicDataSource ds, String url) {
  26 + ds.setUrl(url);
  27 + }
  28 +
  29 + @Override
  30 + public void setUsername(BasicDataSource ds, String username) {
  31 + ds.setUsername(username);
  32 + }
  33 +
  34 + @Override
  35 + public void setPassword(BasicDataSource ds, String password) {
  36 + ds.setPassword(password);
  37 + }
  38 +
  39 + @Override
  40 + public void setAdvancedConfig(BasicDataSource ds) {
  41 + // 解决 java.sql.SQLException: Already closed. 的问题(连接池会自动关闭长时间没有使用的连接)
  42 + // 用于检查connection的sql语句.
  43 + ds.setValidationQuery("select 1 from dual");
  44 + // ds.setTestOnBorrow(true);
  45 + /**
  46 + * :启动connection校验定时器,定时器运行时间间隔就是<br>
  47 + * 这里设定为1小时,只要小于mysql的wait_timeout就可以了
  48 + */
  49 + ds.setTimeBetweenEvictionRunsMillis(3600000);
  50 + // 表示检查idle的connection,false为不检查
  51 + ds.setTestWhileIdle(true);
  52 + }
  53 +}
src/main/java/org/smart4j/framework/ioc/BeanHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/ioc/BeanHelper.java
  1 +package org.smart4j.framework.ioc;
  2 +
  3 +import java.util.HashMap;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +import org.smart4j.framework.aop.annotation.Aspect;
  7 +import org.smart4j.framework.core.ClassHelper;
  8 +import org.smart4j.framework.core.fault.InitializationError;
  9 +import org.smart4j.framework.ioc.annotation.Bean;
  10 +import org.smart4j.framework.mvc.annotation.Action;
  11 +import org.smart4j.framework.tx.annotation.Service;
  12 +
  13 +/**
  14 + * 初始化相关 Bean 类
  15 + *
  16 + * @author huangyong
  17 + * @since 1.0
  18 + */
  19 +public class BeanHelper {
  20 +
  21 + /**
  22 + * Bean Map(Bean 类 => Bean 实例)
  23 + */
  24 + private static final Map<Class<?>, Object> beanMap = new HashMap<Class<?>, Object>();
  25 +
  26 + static {
  27 + try {
  28 + // 获取应用包路径下所有的类
  29 + List<Class<?>> classList = ClassHelper.getClassList();
  30 + for (Class<?> cls : classList) {
  31 + // 处理带有 Bean/Service/Action/Aspect 注解的类
  32 + if (cls.isAnnotationPresent(Bean.class) ||
  33 + cls.isAnnotationPresent(Service.class) ||
  34 + cls.isAnnotationPresent(Action.class) ||
  35 + cls.isAnnotationPresent(Aspect.class)) {
  36 + // 创建 Bean 实例
  37 + Object beanInstance = cls.newInstance();
  38 + // 将 Bean 实例放入 Bean Map 中(键为 Bean 类,值为 Bean 实例)
  39 + beanMap.put(cls, beanInstance);
  40 + }
  41 + }
  42 + } catch (Exception e) {
  43 + throw new InitializationError("初始化 BeanHelper 出错!", e);
  44 + }
  45 + }
  46 +
  47 + /**
  48 + * 获取 Bean Map
  49 + */
  50 + public static Map<Class<?>, Object> getBeanMap() {
  51 + return beanMap;
  52 + }
  53 +
  54 + /**
  55 + * 获取 Bean 实例
  56 + */
  57 + @SuppressWarnings("unchecked")
  58 + public static <T> T getBean(Class<T> cls) {
  59 + if (!beanMap.containsKey(cls)) {
  60 + throw new RuntimeException("无法根据类名获取实例!" + cls);
  61 + }
  62 + return (T) beanMap.get(cls);
  63 + }
  64 +
  65 + /**
  66 + * 设置 Bean 实例
  67 + */
  68 + public static void setBean(Class<?> cls, Object obj) {
  69 + beanMap.put(cls, obj);
  70 + }
  71 +}
src/main/java/org/smart4j/framework/ioc/IocHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/ioc/IocHelper.java
  1 +package org.smart4j.framework.ioc;
  2 +
  3 +import java.lang.reflect.Field;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +import org.smart4j.framework.core.ClassHelper;
  7 +import org.smart4j.framework.core.fault.InitializationError;
  8 +import org.smart4j.framework.ioc.annotation.Impl;
  9 +import org.smart4j.framework.ioc.annotation.Inject;
  10 +import org.smart4j.framework.util.ArrayUtil;
  11 +import org.smart4j.framework.util.CollectionUtil;
  12 +
  13 +/**
  14 + * 初始化 IOC 容器
  15 + *
  16 + * @author huangyong
  17 + * @since 1.0
  18 + */
  19 +public class IocHelper {
  20 +
  21 + static {
  22 + try {
  23 + // 获取并遍历所有的 Bean 类
  24 + Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
  25 + for (Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()) {
  26 + // 获取 Bean 类与 Bean 实例
  27 + Class<?> beanClass = beanEntry.getKey();
  28 + Object beanInstance = beanEntry.getValue();
  29 + // 获取 Bean 类中所有的字段(不包括父类中的方法)
  30 + Field[] beanFields = beanClass.getDeclaredFields();
  31 + if (ArrayUtil.isNotEmpty(beanFields)) {
  32 + // 遍历所有的 Bean 字段
  33 + for (Field beanField : beanFields) {
  34 + // 判断当前 Bean 字段是否带有 Inject 注解
  35 + if (beanField.isAnnotationPresent(Inject.class)) {
  36 + // 获取 Bean 字段对应的接口
  37 + Class<?> interfaceClass = beanField.getType();
  38 + // 获取 Bean 字段对应的实现类
  39 + Class<?> implementClass = findImplementClass(interfaceClass);
  40 + // 若存在实现类,则执行以下代码
  41 + if (implementClass != null) {
  42 + // 从 Bean Map 中获取该实现类对应的实现类实例
  43 + Object implementInstance = beanMap.get(implementClass);
  44 + // 设置该 Bean 字段的值
  45 + if (implementInstance != null) {
  46 + beanField.setAccessible(true); // 将字段设置为 public
  47 + beanField.set(beanInstance, implementInstance); // 设置字段初始值
  48 + } else {
  49 + throw new InitializationError("依赖注入失败!类名:" + beanClass.getSimpleName() + ",字段名:" + interfaceClass.getSimpleName());
  50 + }
  51 + }
  52 + }
  53 + }
  54 + }
  55 + }
  56 + } catch (Exception e) {
  57 + throw new InitializationError("初始化 IocHelper 出错!", e);
  58 + }
  59 + }
  60 +
  61 + /**
  62 + * 查找实现类
  63 + */
  64 + public static Class<?> findImplementClass(Class<?> interfaceClass) {
  65 + Class<?> implementClass = interfaceClass;
  66 + // 判断接口上是否标注了 Impl 注解
  67 + if (interfaceClass.isAnnotationPresent(Impl.class)) {
  68 + // 获取强制指定的实现类
  69 + implementClass = interfaceClass.getAnnotation(Impl.class).value();
  70 + } else {
  71 + // 获取该接口所有的实现类
  72 + List<Class<?>> implementClassList = ClassHelper.getClassListBySuper(interfaceClass);
  73 + if (CollectionUtil.isNotEmpty(implementClassList)) {
  74 + // 获取第一个实现类
  75 + implementClass = implementClassList.get(0);
  76 + }
  77 + }
  78 + // 返回实现类对象
  79 + return implementClass;
  80 + }
  81 +}
src/main/java/org/smart4j/framework/ioc/annotation/Bean.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/ioc/annotation/Bean.java
  1 +package org.smart4j.framework.ioc.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 定义需要 IOC 容器管理的 Bean 类
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +@Target(ElementType.TYPE)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Bean {
  17 +}
src/main/java/org/smart4j/framework/ioc/annotation/Impl.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/ioc/annotation/Impl.java
  1 +package org.smart4j.framework.ioc.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 指定接口的实现类
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +@Target(ElementType.TYPE)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Impl {
  17 +
  18 + Class<?> value();
  19 +}
src/main/java/org/smart4j/framework/ioc/annotation/Inject.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/ioc/annotation/Inject.java
  1 +package org.smart4j.framework.ioc.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 依赖注入
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +@Target(ElementType.FIELD)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Inject {
  17 +}
src/main/java/org/smart4j/framework/mvc/ActionHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/ActionHelper.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import java.lang.reflect.Method;
  4 +import java.util.HashMap;
  5 +import java.util.LinkedHashMap;
  6 +import java.util.List;
  7 +import java.util.Map;
  8 +import org.smart4j.framework.core.ClassHelper;
  9 +import org.smart4j.framework.mvc.annotation.Action;
  10 +import org.smart4j.framework.mvc.annotation.Request;
  11 +import org.smart4j.framework.util.ArrayUtil;
  12 +import org.smart4j.framework.util.CollectionUtil;
  13 +import org.smart4j.framework.util.StringUtil;
  14 +
  15 +/**
  16 + * 初始化 Action 配置
  17 + *
  18 + * @author huangyong
  19 + * @since 1.0
  20 + */
  21 +public class ActionHelper {
  22 +
  23 + /**
  24 + * Action Map(HTTP 请求与 Action 方法的映射)
  25 + */
  26 + private static final Map<Requester, Handler> actionMap = new LinkedHashMap<Requester, Handler>();
  27 +
  28 + static {
  29 + // 获取所有 Action 类
  30 + List<Class<?>> actionClassList = ClassHelper.getClassListByAnnotation(Action.class);
  31 + if (CollectionUtil.isNotEmpty(actionClassList)) {
  32 + // 定义两个 Action Map
  33 + Map<Requester, Handler> commonActionMap = new HashMap<Requester, Handler>(); // 存放普通 Action Map
  34 + Map<Requester, Handler> regexpActionMap = new HashMap<Requester, Handler>(); // 存放带有正则表达式的 Action Map
  35 + // 遍历 Action 类
  36 + for (Class<?> actionClass : actionClassList) {
  37 + // 获取并遍历该 Action 类中所有的方法
  38 + Method[] actionMethods = actionClass.getDeclaredMethods();
  39 + if (ArrayUtil.isNotEmpty(actionMethods)) {
  40 + for (Method actionMethod : actionMethods) {
  41 + // 处理 Action 方法
  42 + handleActionMethod(actionClass, actionMethod, commonActionMap, regexpActionMap);
  43 + }
  44 + }
  45 + }
  46 + // 初始化最终的 Action Map(将 Common 放在 Regexp 前面)
  47 + actionMap.putAll(commonActionMap);
  48 + actionMap.putAll(regexpActionMap);
  49 + }
  50 + }
  51 +
  52 + private static void handleActionMethod(Class<?> actionClass, Method actionMethod, Map<Requester, Handler> commonActionMap, Map<Requester, Handler> regexpActionMap) {
  53 + // 判断当前 Action 方法是否带有 Request 注解
  54 + if (actionMethod.isAnnotationPresent(Request.Get.class)) {
  55 + String requestPath = actionMethod.getAnnotation(Request.Get.class).value();
  56 + putActionMap("GET", requestPath, actionClass, actionMethod, commonActionMap, regexpActionMap);
  57 + } else if (actionMethod.isAnnotationPresent(Request.Post.class)) {
  58 + String requestPath = actionMethod.getAnnotation(Request.Post.class).value();
  59 + putActionMap("POST", requestPath, actionClass, actionMethod, commonActionMap, regexpActionMap);
  60 + } else if (actionMethod.isAnnotationPresent(Request.Put.class)) {
  61 + String requestPath = actionMethod.getAnnotation(Request.Put.class).value();
  62 + putActionMap("PUT", requestPath, actionClass, actionMethod, commonActionMap, regexpActionMap);
  63 + } else if (actionMethod.isAnnotationPresent(Request.Delete.class)) {
  64 + String requestPath = actionMethod.getAnnotation(Request.Delete.class).value();
  65 + putActionMap("DELETE", requestPath, actionClass, actionMethod, commonActionMap, regexpActionMap);
  66 + }
  67 + }
  68 +
  69 + private static void putActionMap(String requestMethod, String requestPath, Class<?> actionClass, Method actionMethod, Map<Requester, Handler> commonActionMap, Map<Requester, Handler> regexpActionMap) {
  70 + // 判断 Request Path 中是否带有占位符
  71 + if (requestPath.matches(".+\\{\\w+\\}.*")) {
  72 + // 将请求路径中的占位符 {\w+} 转换为正则表达式 (\\w+)
  73 + requestPath = StringUtil.replaceAll(requestPath, "\\{\\w+\\}", "(\\\\w+)");
  74 + // 将 Requester 与 Handler 放入 Regexp Action Map 中
  75 + regexpActionMap.put(new Requester(requestMethod, requestPath), new Handler(actionClass, actionMethod));
  76 + } else {
  77 + // 将 Requester 与 Handler 放入 Common Action Map 中
  78 + commonActionMap.put(new Requester(requestMethod, requestPath), new Handler(actionClass, actionMethod));
  79 + }
  80 + }
  81 +
  82 + /**
  83 + * 获取 Action Map
  84 + */
  85 + public static Map<Requester, Handler> getActionMap() {
  86 + return actionMap;
  87 + }
  88 +}
src/main/java/org/smart4j/framework/mvc/ContainerListener.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/ContainerListener.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import java.util.List;
  4 +import javax.servlet.ServletContext;
  5 +import javax.servlet.ServletContextEvent;
  6 +import javax.servlet.ServletContextListener;
  7 +import javax.servlet.ServletRegistration;
  8 +import javax.servlet.annotation.WebListener;
  9 +import org.smart4j.framework.FrameworkConstant;
  10 +import org.smart4j.framework.HelperLoader;
  11 +import org.smart4j.framework.plugin.Plugin;
  12 +import org.smart4j.framework.plugin.PluginHelper;
  13 +import org.smart4j.framework.plugin.WebPlugin;
  14 +import org.smart4j.framework.util.StringUtil;
  15 +
  16 +/**
  17 + * 容器监听器 .启动即加载
  18 + */
  19 +@WebListener
  20 +public class ContainerListener implements ServletContextListener {
  21 +
  22 + /**
  23 + * 当容器初始化时调用
  24 + */
  25 + @Override
  26 + public void contextInitialized(ServletContextEvent sce) {
  27 + // 获取 ServletContext
  28 + ServletContext servletContext = sce.getServletContext();
  29 + // 初始化相关 Helper 类
  30 + HelperLoader.init();
  31 + // 添加 Servlet 映射
  32 + addServletMapping(servletContext);
  33 + // 注册 WebPlugin
  34 + registerWebPlugin(servletContext);
  35 + }
  36 +
  37 + /**
  38 + * 当容器销毁时调用
  39 + */
  40 + @Override
  41 + public void contextDestroyed(ServletContextEvent sce) {
  42 + // 销毁插件
  43 + destroyPlugin();
  44 + }
  45 +
  46 + private void addServletMapping(ServletContext context) {
  47 + // 用 DefaultServlet 映射所有静态资源
  48 + registerDefaultServlet(context);
  49 + // 用 JspServlet 映射所有 JSP 请求
  50 + registerJspServlet(context);
  51 + }
  52 +
  53 + private void registerDefaultServlet(ServletContext context) {
  54 + ServletRegistration defaultServlet = context.getServletRegistration("default");
  55 + defaultServlet.addMapping("/index.html");
  56 + defaultServlet.addMapping("/favicon.ico");
  57 + String wwwPath = FrameworkConstant.WWW_PATH;
  58 + if (StringUtil.isNotEmpty(wwwPath)) {
  59 + defaultServlet.addMapping(wwwPath + "*");
  60 + }
  61 + }
  62 +
  63 + private void registerJspServlet(ServletContext context) {
  64 + ServletRegistration jspServlet = context.getServletRegistration("jsp");
  65 + jspServlet.addMapping("/index.jsp");
  66 + String jspPath = FrameworkConstant.JSP_PATH;
  67 + if (StringUtil.isNotEmpty(jspPath)) {
  68 + jspServlet.addMapping(jspPath + "*");
  69 + }
  70 + }
  71 +
  72 + private void registerWebPlugin(ServletContext servletContext) {
  73 + List<Plugin> pluginList = PluginHelper.getPluginList();
  74 + for (Plugin plugin : pluginList) {
  75 + if (plugin instanceof WebPlugin) {
  76 + WebPlugin webPlugin = (WebPlugin) plugin;
  77 + webPlugin.register(servletContext);
  78 + }
  79 + }
  80 + }
  81 +
  82 + private void destroyPlugin() {
  83 + List<Plugin> pluginList = PluginHelper.getPluginList();
  84 + for (Plugin plugin : pluginList) {
  85 + plugin.destroy();
  86 + }
  87 + }
  88 +}
src/main/java/org/smart4j/framework/mvc/DataContext.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/DataContext.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import java.util.Enumeration;
  4 +import java.util.HashMap;
  5 +import java.util.Map;
  6 +import javax.servlet.http.HttpServletRequest;
  7 +import javax.servlet.http.HttpServletResponse;
  8 +import javax.servlet.http.HttpSession;
  9 +import org.smart4j.framework.util.ArrayUtil;
  10 +import org.smart4j.framework.util.CastUtil;
  11 +import org.smart4j.framework.util.CodecUtil;
  12 +
  13 +/**
  14 + * 数据上下文
  15 + *
  16 + * @author huangyong
  17 + * @since 1.0
  18 + */
  19 +public class DataContext {
  20 +
  21 + /**
  22 + * 使每个线程拥有各自的 DataContext 实例
  23 + */
  24 + private static final ThreadLocal<DataContext> dataContextContainer = new ThreadLocal<DataContext>();
  25 +
  26 + private HttpServletRequest request;
  27 + private HttpServletResponse response;
  28 +
  29 + /**
  30 + * 初始化
  31 + */
  32 + public static void init(HttpServletRequest request, HttpServletResponse response) {
  33 + DataContext dataContext = new DataContext();
  34 + dataContext.request = request;
  35 + dataContext.response = response;
  36 + dataContextContainer.set(dataContext);
  37 + }
  38 +
  39 + /**
  40 + * 销毁
  41 + */
  42 + public static void destroy() {
  43 + dataContextContainer.remove();
  44 + }
  45 +
  46 + /**
  47 + * 获取 DataContext 实例
  48 + */
  49 + public static DataContext getInstance() {
  50 + return dataContextContainer.get();
  51 + }
  52 +
  53 + /**
  54 + * 获取 Request 对象
  55 + */
  56 + public static HttpServletRequest getRequest() {
  57 + return getInstance().request;
  58 + }
  59 +
  60 + /**
  61 + * 获取 Response 对象
  62 + */
  63 + public static HttpServletResponse getResponse() {
  64 + return getInstance().response;
  65 + }
  66 +
  67 + /**
  68 + * 获取 Session 对象
  69 + */
  70 + public static HttpSession getSession() {
  71 + return getRequest().getSession();
  72 + }
  73 +
  74 + /**
  75 + * 获取 Servlet Context 对象
  76 + */
  77 + public static javax.servlet.ServletContext getServletContext() {
  78 + return getRequest().getServletContext();
  79 + }
  80 +
  81 + /**
  82 + * 封装 Request 相关操作
  83 + */
  84 + public static class Request {
  85 +
  86 + /**
  87 + * 将数据放入 Request 中
  88 + */
  89 + public static void put(String key, Object value) {
  90 + getRequest().setAttribute(key, value);
  91 + }
  92 +
  93 + /**
  94 + * 从 Request 中获取数据
  95 + */
  96 + @SuppressWarnings("unchecked")
  97 + public static <T> T get(String key) {
  98 + return (T) getRequest().getAttribute(key);
  99 + }
  100 +
  101 + /**
  102 + * 移除 Request 中的数据
  103 + */
  104 + public static void remove(String key) {
  105 + getRequest().removeAttribute(key);
  106 + }
  107 +
  108 + /**
  109 + * 从 Request 中获取所有数据
  110 + */
  111 + public static Map<String, Object> getAll() {
  112 + Map<String, Object> map = new HashMap<String, Object>();
  113 + Enumeration<String> names = getRequest().getAttributeNames();
  114 + while (names.hasMoreElements()) {
  115 + String name = names.nextElement();
  116 + map.put(name, getRequest().getAttribute(name));
  117 + }
  118 + return map;
  119 + }
  120 + }
  121 +
  122 + /**
  123 + * 封装 Response 相关操作
  124 + */
  125 + public static class Response {
  126 +
  127 + /**
  128 + * 将数据放入 Response 中
  129 + */
  130 + public static void put(String key, Object value) {
  131 + getResponse().setHeader(key, CastUtil.castString(value));
  132 + }
  133 +
  134 + /**
  135 + * 从 Response 中获取数据
  136 + */
  137 + @SuppressWarnings("unchecked")
  138 + public static <T> T get(String key) {
  139 + return (T) getResponse().getHeader(key);
  140 + }
  141 +
  142 + /**
  143 + * 从 Response 中获取所有数据
  144 + */
  145 + public static Map<String, Object> getAll() {
  146 + Map<String, Object> map = new HashMap<String, Object>();
  147 + for (String name : getResponse().getHeaderNames()) {
  148 + map.put(name, getResponse().getHeader(name));
  149 + }
  150 + return map;
  151 + }
  152 + }
  153 +
  154 + /**
  155 + * 封装 Session 相关操作
  156 + */
  157 + public static class Session {
  158 +
  159 + /**
  160 + * 将数据放入 Session 中
  161 + */
  162 + public static void put(String key, Object value) {
  163 + getSession().setAttribute(key, value);
  164 + }
  165 +
  166 + /**
  167 + * 从 Session 中获取数据
  168 + */
  169 + @SuppressWarnings("unchecked")
  170 + public static <T> T get(String key) {
  171 + return (T) getSession().getAttribute(key);
  172 + }
  173 +
  174 + /**
  175 + * 移除 Session 中的数据
  176 + */
  177 + public static void remove(String key) {
  178 + getSession().removeAttribute(key);
  179 + }
  180 +
  181 + /**
  182 + * 从 Session 中获取所有数据
  183 + */
  184 + public static Map<String, Object> getAll() {
  185 + Map<String, Object> map = new HashMap<String, Object>();
  186 + Enumeration<String> names = getSession().getAttributeNames();
  187 + while (names.hasMoreElements()) {
  188 + String name = names.nextElement();
  189 + map.put(name, getSession().getAttribute(name));
  190 + }
  191 + return map;
  192 + }
  193 +
  194 + /**
  195 + * 移除 Session 中所有的数据
  196 + */
  197 + public static void removeAll() {
  198 + getSession().invalidate();
  199 + }
  200 + }
  201 +
  202 + /**
  203 + * 封装 Cookie 相关操作
  204 + */
  205 + public static class Cookie {
  206 +
  207 + /**
  208 + * 将数据放入 Cookie 中
  209 + */
  210 + public static void put(String key, Object value) {
  211 + String strValue = CodecUtil.encodeURL(CastUtil.castString(value));
  212 + javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(key, strValue);
  213 + getResponse().addCookie(cookie);
  214 + }
  215 +
  216 + /**
  217 + * 从 Cookie 中获取数据
  218 + */
  219 + @SuppressWarnings("unchecked")
  220 + public static <T> T get(String key) {
  221 + T value = null;
  222 + javax.servlet.http.Cookie[] cookieArray = getRequest().getCookies();
  223 + if (ArrayUtil.isNotEmpty(cookieArray)) {
  224 + for (javax.servlet.http.Cookie cookie : cookieArray) {
  225 + if (key.equals(cookie.getName())) {
  226 + value = (T) CodecUtil.decodeURL(cookie.getValue());
  227 + break;
  228 + }
  229 + }
  230 + }
  231 + return value;
  232 + }
  233 +
  234 + /**
  235 + * 从 Cookie 中获取所有数据
  236 + */
  237 + public static Map<String, Object> getAll() {
  238 + Map<String, Object> map = new HashMap<String, Object>();
  239 + javax.servlet.http.Cookie[] cookieArray = getRequest().getCookies();
  240 + if (ArrayUtil.isNotEmpty(cookieArray)) {
  241 + for (javax.servlet.http.Cookie cookie : cookieArray) {
  242 + map.put(cookie.getName(), cookie.getValue());
  243 + }
  244 + }
  245 + return map;
  246 + }
  247 + }
  248 +
  249 + /**
  250 + * 封装 ServletContext 相关操作
  251 + */
  252 + public static class ServletContext {
  253 +
  254 + /**
  255 + * 将数据放入 ServletContext 中
  256 + */
  257 + public static void put(String key, Object value) {
  258 + getServletContext().setAttribute(key, value);
  259 + }
  260 +
  261 + /**
  262 + * 从 ServletContext 中获取数据
  263 + */
  264 + @SuppressWarnings("unchecked")
  265 + public static <T> T get(String key) {
  266 + return (T) getServletContext().getAttribute(key);
  267 + }
  268 +
  269 + /**
  270 + * 移除 ServletContext 中的数据
  271 + */
  272 + public static void remove(String key) {
  273 + getServletContext().removeAttribute(key);
  274 + }
  275 +
  276 + /**
  277 + * 从 ServletContext 中获取所有数据
  278 + */
  279 + public static Map<String, Object> getAll() {
  280 + Map<String, Object> map = new HashMap<String, Object>();
  281 + Enumeration<String> names = getServletContext().getAttributeNames();
  282 + while (names.hasMoreElements()) {
  283 + String name = names.nextElement();
  284 + map.put(name, getServletContext().getAttribute(name));
  285 + }
  286 + return map;
  287 + }
  288 + }
  289 +}
src/main/java/org/smart4j/framework/mvc/DispatcherServlet.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/DispatcherServlet.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import java.io.IOException;
  4 +
  5 +import javax.servlet.ServletConfig;
  6 +import javax.servlet.ServletContext;
  7 +import javax.servlet.ServletException;
  8 +import javax.servlet.annotation.WebServlet;
  9 +import javax.servlet.http.HttpServlet;
  10 +import javax.servlet.http.HttpServletRequest;
  11 +import javax.servlet.http.HttpServletResponse;
  12 +
  13 +import org.slf4j.Logger;
  14 +import org.slf4j.LoggerFactory;
  15 +import org.smart4j.framework.FrameworkConstant;
  16 +import org.smart4j.framework.InstanceFactory;
  17 +import org.smart4j.framework.util.WebUtil;
  18 +
  19 +@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
  20 +public class DispatcherServlet extends HttpServlet {
  21 +
  22 + private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class);
  23 +
  24 + private HandlerMapping handlerMapping = InstanceFactory.getHandlerMapping();
  25 + private HandlerInvoker handlerInvoker = InstanceFactory.getHandlerInvoker();
  26 + private HandlerExceptionResolver handlerExceptionResolver = InstanceFactory.getHandlerExceptionResolver();
  27 +
  28 + @Override
  29 + public void init(ServletConfig config) throws ServletException {
  30 + // 初始化相关配置
  31 + ServletContext servletContext = config.getServletContext();
  32 + UploadHelper.init(servletContext);
  33 + }
  34 +
  35 + @Override
  36 + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  37 + // 设置请求编码方式
  38 + request.setCharacterEncoding(FrameworkConstant.UTF_8);
  39 + // 获取当前请求相关数据
  40 + String currentRequestMethod = request.getMethod();
  41 + String currentRequestPath = WebUtil.getRequestPath(request);
  42 + logger.debug(getRemoteUserIp(request)+"[Smart] {}:{}", currentRequestMethod, currentRequestPath);
  43 + // 将“/”请求重定向到首页
  44 + if (currentRequestPath.equals("/")) {
  45 + WebUtil.redirectRequest(FrameworkConstant.HOME_PAGE, request, response);
  46 + return;
  47 + }
  48 + // 去掉当前请求路径末尾的“/”
  49 + if (currentRequestPath.endsWith("/")) {
  50 + currentRequestPath = currentRequestPath.substring(0, currentRequestPath.length() - 1);
  51 + }
  52 + // 获取 Handler
  53 + Handler handler = handlerMapping.getHandler(currentRequestMethod, currentRequestPath);
  54 + // 若未找到 Action,则跳转到 404 页面
  55 + if (handler == null) {
  56 + WebUtil.sendError(HttpServletResponse.SC_NOT_FOUND, "", response);
  57 + return;
  58 + }
  59 + // 初始化 DataContext
  60 + DataContext.init(request, response);
  61 + try {
  62 + // 调用 Handler
  63 + handlerInvoker.invokeHandler(request, response, handler);
  64 + } catch (Exception e) {
  65 + // 处理 Action 异常
  66 + handlerExceptionResolver.resolveHandlerException(request, response, e);
  67 + } finally {
  68 + // 销毁 DataContext
  69 + DataContext.destroy();
  70 + }
  71 + }
  72 + private String getRemoteUserIp(HttpServletRequest request) {
  73 + String ip = request.getHeader("x-forwarded-for");
  74 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  75 + ip = request.getHeader("Proxy-Client-IP");
  76 + }
  77 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  78 + ip = request.getHeader("WL-Proxy-Client-IP");
  79 + }
  80 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  81 + ip = request.getRemoteAddr();
  82 + }
  83 + if (ip.contains(",")) {
  84 + ip = ip.split(",")[0];
  85 + }
  86 + if (ip.equals("0:0:0:0:0:0:0:1")) {
  87 + ip = "127.0.0.1";
  88 + }
  89 + return ip;
  90 + }
  91 +}
src/main/java/org/smart4j/framework/mvc/Handler.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/Handler.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import java.lang.reflect.Method;
  4 +import java.util.regex.Matcher;
  5 +
  6 +/**
  7 + * 封装 Action 方法相关信息
  8 + *
  9 + * @author huangyong
  10 + * @since 1.0
  11 + */
  12 +public class Handler {
  13 +
  14 + private Class<?> actionClass;
  15 + private Method actionMethod;
  16 + private Matcher requestPathMatcher;
  17 +
  18 + public Handler(Class<?> actionClass, Method actionMethod) {
  19 + this.actionClass = actionClass;
  20 + this.actionMethod = actionMethod;
  21 + }
  22 +
  23 + public Class<?> getActionClass() {
  24 + return actionClass;
  25 + }
  26 +
  27 + public Method getActionMethod() {
  28 + return actionMethod;
  29 + }
  30 +
  31 + public Matcher getRequestPathMatcher() {
  32 + return requestPathMatcher;
  33 + }
  34 +
  35 + public void setRequestPathMatcher(Matcher requestPathMatcher) {
  36 + this.requestPathMatcher = requestPathMatcher;
  37 + }
  38 +}
0 \ No newline at end of file 39 \ No newline at end of file
src/main/java/org/smart4j/framework/mvc/HandlerExceptionResolver.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/HandlerExceptionResolver.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +import javax.servlet.http.HttpServletResponse;
  5 +
  6 +/**
  7 + * Handler 异常解析器
  8 + *
  9 + * @author huangyong
  10 + * @since 2.3
  11 + */
  12 +public interface HandlerExceptionResolver {
  13 +
  14 + /**
  15 + * 解析 Handler 异常
  16 + *
  17 + * @param request 请求对象
  18 + * @param response 响应对象
  19 + * @param e 异常
  20 + */
  21 + void resolveHandlerException(HttpServletRequest request, HttpServletResponse response, Exception e);
  22 +}
src/main/java/org/smart4j/framework/mvc/HandlerInvoker.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/HandlerInvoker.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +import javax.servlet.http.HttpServletResponse;
  5 +
  6 +/**
  7 + * Handler 调用器
  8 + *
  9 + * @author huangyong
  10 + * @since 2.3
  11 + */
  12 +public interface HandlerInvoker {
  13 +
  14 + /**
  15 + * 调用 Handler
  16 + *
  17 + * @param request 请求对象
  18 + * @param response 响应对象
  19 + * @param handler Handler
  20 + * @throws Exception 异常
  21 + */
  22 + void invokeHandler(HttpServletRequest request, HttpServletResponse response, Handler handler) throws Exception;
  23 +}
src/main/java/org/smart4j/framework/mvc/HandlerMapping.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/HandlerMapping.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +/**
  4 + * 处理器映射
  5 + *
  6 + * @author huangyong
  7 + * @since 2.3
  8 + */
  9 +public interface HandlerMapping {
  10 +
  11 + /**
  12 + * 获取 Handler
  13 + *
  14 + * @param currentRequestMethod 当前请求方法
  15 + * @param currentRequestPath 当前请求路径
  16 + * @return Handler
  17 + */
  18 + Handler getHandler(String currentRequestMethod, String currentRequestPath);
  19 +}
src/main/java/org/smart4j/framework/mvc/Requester.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/Requester.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +/**
  4 + * 封装 Request 对象相关信息
  5 + *
  6 + * @author huangyong
  7 + * @since 1.0
  8 + */
  9 +public class Requester {
  10 +
  11 + private String requestMethod;
  12 + private String requestPath;
  13 +
  14 + public Requester(String requestMethod, String requestPath) {
  15 + this.requestMethod = requestMethod;
  16 + this.requestPath = requestPath;
  17 + }
  18 +
  19 + public String getRequestMethod() {
  20 + return requestMethod;
  21 + }
  22 +
  23 + public String getRequestPath() {
  24 + return requestPath;
  25 + }
  26 +}
0 \ No newline at end of file 27 \ No newline at end of file
src/main/java/org/smart4j/framework/mvc/UploadHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/UploadHelper.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import java.io.BufferedInputStream;
  4 +import java.io.BufferedOutputStream;
  5 +import java.io.File;
  6 +import java.io.FileOutputStream;
  7 +import java.io.InputStream;
  8 +import java.io.OutputStream;
  9 +import java.util.ArrayList;
  10 +import java.util.HashMap;
  11 +import java.util.List;
  12 +import java.util.Map;
  13 +import javax.servlet.ServletContext;
  14 +import javax.servlet.http.HttpServletRequest;
  15 +import org.apache.commons.fileupload.FileItem;
  16 +import org.apache.commons.fileupload.FileUploadBase;
  17 +import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  18 +import org.apache.commons.fileupload.servlet.ServletFileUpload;
  19 +import org.slf4j.Logger;
  20 +import org.slf4j.LoggerFactory;
  21 +import org.smart4j.framework.FrameworkConstant;
  22 +import org.smart4j.framework.mvc.bean.Multipart;
  23 +import org.smart4j.framework.mvc.bean.Multiparts;
  24 +import org.smart4j.framework.mvc.bean.Params;
  25 +import org.smart4j.framework.mvc.fault.UploadException;
  26 +import org.smart4j.framework.util.FileUtil;
  27 +import org.smart4j.framework.util.StreamUtil;
  28 +import org.smart4j.framework.util.StringUtil;
  29 +
  30 +/**
  31 + * 封装文件上传相关操作
  32 + *
  33 + * @author huangyong
  34 + * @since 2.1
  35 + */
  36 +public class UploadHelper {
  37 +
  38 + private static final Logger logger = LoggerFactory.getLogger(UploadHelper.class);
  39 +
  40 + /**
  41 + * FileUpload 对象(用于解析所上传的文件)
  42 + */
  43 + private static ServletFileUpload fileUpload;
  44 +
  45 + /**
  46 + * 初始化
  47 + */
  48 + public static void init(ServletContext servletContext) {
  49 + // 获取一个临时目录(使用 Tomcat 的 work 目录)
  50 + File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
  51 + // 创建 FileUpload 对象
  52 + fileUpload = new ServletFileUpload(new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, repository));
  53 + System.out.println("fileUpload.getFileSizeMax()"+fileUpload.getFileSizeMax());
  54 + // 设置上传限制
  55 + int uploadLimit = FrameworkConstant.UPLOAD_LIMIT;
  56 + System.out.println(uploadLimit);
  57 +// if (uploadLimit != 0) {
  58 +// fileUpload.setSizeMax(uploadLimit * 1024 * 1024);
  59 +// fileUpload.setFileSizeMax(uploadLimit * 1024 * 1024); // 单位为 M
  60 +// System.out.println(fileUpload.getFileSizeMax());
  61 +// }
  62 + }
  63 +
  64 + /**
  65 + * 判断请求是否为 multipart 类型
  66 + */
  67 + public static boolean isMultipart(HttpServletRequest request) {
  68 + // 判断上传文件的内容是否为 multipart 类型
  69 + return ServletFileUpload.isMultipartContent(request);
  70 + }
  71 +
  72 + /**
  73 + * 创建 multipart 请求参数列表
  74 + */
  75 + public static List<Object> createMultipartParamList(HttpServletRequest request) throws Exception {
  76 + // 定义参数列表
  77 + List<Object> paramList = new ArrayList<Object>();
  78 + // 创建两个对象,分别对应 普通字段 与 文件字段
  79 + Map<String, Object> fieldMap = new HashMap<String, Object>();
  80 + List<Multipart> multipartList = new ArrayList<Multipart>();
  81 + // 获取并遍历表单项
  82 + List<FileItem> fileItemList=null;
  83 + try {
  84 + fileItemList = fileUpload.parseRequest(request);
  85 + } catch (FileUploadBase.FileSizeLimitExceededException e) {
  86 + e.printStackTrace();
  87 + }
  88 + for (FileItem fileItem : fileItemList) {
  89 + // 分两种情况处理表单项
  90 + String fieldName = fileItem.getFieldName();
  91 + if (fileItem.isFormField()) {
  92 + // 处理普通字段
  93 + String fieldValue = fileItem.getString(FrameworkConstant.UTF_8);
  94 + fieldMap.put(fieldName, fieldValue);
  95 + } else {
  96 + // 处理文件字段
  97 + String fileName = FileUtil.getRealFileName(fileItem.getName());
  98 + if (StringUtil.isNotEmpty(fileName)) {
  99 + long fileSize = fileItem.getSize();
  100 + String contentType = fileItem.getContentType();
  101 + InputStream inputSteam = fileItem.getInputStream();
  102 + // 创建 Multipart 对象,并将其添加到 multipartList 中
  103 + Multipart multipart = new Multipart(fieldName, fileName, fileSize, contentType, inputSteam);
  104 + multipartList.add(multipart);
  105 + }
  106 + }
  107 + }
  108 + // 初始化参数列表
  109 + paramList.add(new Params(fieldMap));
  110 + paramList.add(new Multiparts(multipartList));
  111 + // 返回参数列表
  112 + return paramList;
  113 + }
  114 +
  115 + /**
  116 + * 上传文件
  117 + */
  118 + public static void uploadFile(String basePath, Multipart multipart) {
  119 + try {
  120 + if (multipart != null) {
  121 + // 创建文件路径(绝对路径)
  122 + System.out.println("创建文件路径(绝对路径)创建文件路径(绝对路径)");
  123 + String filePath = basePath + multipart.getFileName();
  124 + FileUtil.createFile(filePath);
  125 + // 执行流复制操作
  126 + InputStream inputStream = new BufferedInputStream(multipart.getInputStream());
  127 + OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(filePath));
  128 + StreamUtil.copyStream(inputStream, outputStream);
  129 + }
  130 + } catch (Exception e) {
  131 + e.printStackTrace();
  132 + logger.error("上传文件出错!", e);
  133 + throw new RuntimeException(e);
  134 + }
  135 + }
  136 +
  137 + /**
  138 + * 批量上传文件
  139 + */
  140 + public static void uploadFiles(String basePath, Multiparts multiparts) {
  141 + for (Multipart multipart : multiparts.getAll()) {
  142 + uploadFile(basePath, multipart);
  143 + }
  144 + }
  145 +}
src/main/java/org/smart4j/framework/mvc/ViewResolver.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/ViewResolver.java
  1 +package org.smart4j.framework.mvc;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +import javax.servlet.http.HttpServletResponse;
  5 +
  6 +/**
  7 + * 视图解析器
  8 + *
  9 + * @author huangyong
  10 + * @since 2.3
  11 + */
  12 +public interface ViewResolver {
  13 +
  14 + /**
  15 + * 解析视图
  16 + *
  17 + * @param request 请求对象
  18 + * @param response 响应对象
  19 + * @param actionMethodResult Action 方法返回值
  20 + */
  21 + void resolveView(HttpServletRequest request, HttpServletResponse response, Object actionMethodResult);
  22 +}
src/main/java/org/smart4j/framework/mvc/annotation/Action.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/annotation/Action.java
  1 +package org.smart4j.framework.mvc.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 定义 Action 类
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +@Target(ElementType.TYPE)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Action {
  17 +}
src/main/java/org/smart4j/framework/mvc/annotation/Request.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/annotation/Request.java
  1 +package org.smart4j.framework.mvc.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 定义请求
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +@Target(ElementType.METHOD)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Request {
  17 +
  18 + /**
  19 + * 定义 GET 请求
  20 + *
  21 + * @author huangyong
  22 + * @since 2.1
  23 + */
  24 + @Target(ElementType.METHOD)
  25 + @Retention(RetentionPolicy.RUNTIME)
  26 + public @interface Get {
  27 +
  28 + String value();
  29 + }
  30 +
  31 + /**
  32 + * 定义 POST 请求
  33 + *
  34 + * @author huangyong
  35 + * @since 2.1
  36 + */
  37 + @Target(ElementType.METHOD)
  38 + @Retention(RetentionPolicy.RUNTIME)
  39 + public @interface Post {
  40 +
  41 + String value();
  42 + }
  43 +
  44 + /**
  45 + * 定义 PUT 请求
  46 + *
  47 + * @author huangyong
  48 + * @since 2.1
  49 + */
  50 + @Target(ElementType.METHOD)
  51 + @Retention(RetentionPolicy.RUNTIME)
  52 + public @interface Put {
  53 +
  54 + String value();
  55 + }
  56 +
  57 + /**
  58 + * 定义 DELETE 请求
  59 + *
  60 + * @author huangyong
  61 + * @since 2.1
  62 + */
  63 + @Target(ElementType.METHOD)
  64 + @Retention(RetentionPolicy.RUNTIME)
  65 + public @interface Delete {
  66 +
  67 + String value();
  68 + }
  69 +}
src/main/java/org/smart4j/framework/mvc/bean/ApiBean.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/bean/ApiBean.java
  1 +/**
  2 + * Project Name:smart-framework
  3 + * File Name:ApiBean.java
  4 + * Package Name:org.smart4j.framework.mvc.bean
  5 + * Date:2016年5月24日上午9:17:36
  6 + * Copyright (c) 2016, cnlive.com All Rights Reserved.
  7 + *
  8 + */
  9 +
  10 +package org.smart4j.framework.mvc.bean;
  11 +
  12 +import org.smart4j.framework.core.bean.BaseBean;
  13 +
  14 +/**
  15 + * TODO: 这里用一句话描述当前类的作用 Date: 2016年5月24日 上午9:17:36 <br/>
  16 + *
  17 + * @author liujicheng
  18 + * @version V1.0
  19 + * @since JDK 1.6
  20 + */
  21 +public class ApiBean extends BaseBean {
  22 + private String message;
  23 + private Object data;
  24 + private int code;
  25 + private int next_cursor;
  26 +
  27 + public String getMessage() {
  28 + return message;
  29 + }
  30 +
  31 + public void setMessage(String message) {
  32 + this.message = message;
  33 + }
  34 +
  35 + public Object getData() {
  36 + return data;
  37 + }
  38 +
  39 + public void setData(Object data) {
  40 + this.data = data;
  41 + }
  42 +
  43 + public int getCode() {
  44 + return code;
  45 + }
  46 +
  47 + public void setCode(int code) {
  48 + this.code = code;
  49 + }
  50 +
  51 +}
src/main/java/org/smart4j/framework/mvc/bean/Multipart.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/bean/Multipart.java
  1 +package org.smart4j.framework.mvc.bean;
  2 +
  3 +import java.io.InputStream;
  4 +import org.smart4j.framework.core.bean.BaseBean;
  5 +
  6 +/**
  7 + * 封装文件上传对象相关属性
  8 + *
  9 + * @author huangyong
  10 + * @since 1.0
  11 + */
  12 +public class Multipart extends BaseBean {
  13 +
  14 + private String fieldName;
  15 + private String fileName;
  16 + private long fileSize;
  17 + private String contentType;
  18 + private InputStream inputStream;
  19 +
  20 + public Multipart(String fieldName, String fileName, long fileSize, String contentType, InputStream inputStream) {
  21 + this.fieldName = fieldName;
  22 + this.fileName = fileName;
  23 + this.fileSize = fileSize;
  24 + this.contentType = contentType;
  25 + this.inputStream = inputStream;
  26 + }
  27 +
  28 + public String getFieldName() {
  29 + return fieldName;
  30 + }
  31 +
  32 + public String getFileName() {
  33 + return fileName;
  34 + }
  35 +
  36 + public long getFileSize() {
  37 + return fileSize;
  38 + }
  39 +
  40 + public String getContentType() {
  41 + return contentType;
  42 + }
  43 +
  44 + public InputStream getInputStream() {
  45 + return inputStream;
  46 + }
  47 +}
src/main/java/org/smart4j/framework/mvc/bean/Multiparts.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/bean/Multiparts.java
  1 +package org.smart4j.framework.mvc.bean;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.List;
  5 +import org.smart4j.framework.core.bean.BaseBean;
  6 +
  7 +/**
  8 + * 封装批量文件上传对象
  9 + *
  10 + * @author huangyong
  11 + * @since 1.0
  12 + */
  13 +public class Multiparts extends BaseBean {
  14 +
  15 + private List<Multipart> multipartList = new ArrayList<Multipart>();
  16 +
  17 + public Multiparts(List<Multipart> multipartList) {
  18 + this.multipartList = multipartList;
  19 + }
  20 +
  21 + public int size() {
  22 + return multipartList.size();
  23 + }
  24 +
  25 + public List<Multipart> getAll() {
  26 + return multipartList;
  27 + }
  28 +
  29 + public Multipart getOne() {
  30 + return size() == 1 ? multipartList.get(0) : null;
  31 + }
  32 +}
src/main/java/org/smart4j/framework/mvc/bean/Params.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/bean/Params.java
  1 +package org.smart4j.framework.mvc.bean;
  2 +
  3 +import java.util.Map;
  4 +import org.smart4j.framework.core.bean.BaseBean;
  5 +import org.smart4j.framework.util.CastUtil;
  6 +
  7 +/**
  8 + * 封装请求参数
  9 + *
  10 + * @author huangyong
  11 + * @since 2.2
  12 + */
  13 +public class Params extends BaseBean {
  14 +
  15 + private final Map<String, Object> fieldMap;
  16 +
  17 + public Params(Map<String, Object> fieldMap) {
  18 + this.fieldMap = fieldMap;
  19 + }
  20 +
  21 + public Map<String, Object> getFieldMap() {
  22 + return fieldMap;
  23 + }
  24 +
  25 + public String getString(String name) {
  26 + return CastUtil.castString(get(name));
  27 + }
  28 +
  29 + public double getDouble(String name) {
  30 + return CastUtil.castDouble(get(name));
  31 + }
  32 +
  33 + public long getLong(String name) {
  34 + return CastUtil.castLong(get(name));
  35 + }
  36 +
  37 + public int getInt(String name) {
  38 + return CastUtil.castInt(get(name));
  39 + }
  40 +
  41 + private Object get(String name) {
  42 + return fieldMap.get(name);
  43 + }
  44 +}
src/main/java/org/smart4j/framework/mvc/bean/Redirect.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/bean/Redirect.java
  1 +package org.smart4j.framework.mvc.bean;
  2 +
  3 +public class Redirect {
  4 + private String redirectUrl;
  5 + private String message;
  6 + private int code;
  7 +
  8 + public String getMessage() {
  9 + return message;
  10 + }
  11 +
  12 + public void setMessage(String message) {
  13 + this.message = message;
  14 + }
  15 +
  16 + public int getCode() {
  17 + return code;
  18 + }
  19 +
  20 + public void setCode(int code) {
  21 + this.code = code;
  22 + }
  23 +
  24 + public String getRedirectUrl() {
  25 + return redirectUrl;
  26 + }
  27 +
  28 + public void setRedirectUrl(String redirectUrl) {
  29 + this.redirectUrl = redirectUrl;
  30 + }
  31 +
  32 +}
src/main/java/org/smart4j/framework/mvc/bean/Result.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/bean/Result.java
  1 +package org.smart4j.framework.mvc.bean;
  2 +
  3 +import org.smart4j.framework.core.bean.BaseBean;
  4 +
  5 +/**
  6 + * 封装返回数据
  7 + *
  8 + * @author huangyong
  9 + * @since 1.0
  10 + */
  11 +public class Result extends BaseBean {
  12 +
  13 + private boolean success; // 成功标志
  14 + private int error; // 错误代码
  15 + private Object data; // 相关数据
  16 +
  17 + public Result(boolean success) {
  18 + this.success = success;
  19 + }
  20 +
  21 + public Result error(int error) {
  22 + this.error = error;
  23 + return this;
  24 + }
  25 +
  26 + public Result data(Object data) {
  27 + this.data = data;
  28 + return this;
  29 + }
  30 +
  31 + public boolean isSuccess() {
  32 + return success;
  33 + }
  34 +
  35 + public void setSuccess(boolean success) {
  36 + this.success = success;
  37 + }
  38 +
  39 + public int getError() {
  40 + return error;
  41 + }
  42 +
  43 + public void setError(int error) {
  44 + this.error = error;
  45 + }
  46 +
  47 + public Object getData() {
  48 + return data;
  49 + }
  50 +
  51 + public void setData(Object data) {
  52 + this.data = data;
  53 + }
  54 +}
src/main/java/org/smart4j/framework/mvc/bean/ResultBean.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/bean/ResultBean.java
  1 +/**
  2 + * Project Name:smart-framework
  3 + * File Name:ApiBean.java
  4 + * Package Name:org.smart4j.framework.mvc.bean
  5 + * Date:2016年5月24日上午9:17:36
  6 + * Copyright (c) 2016, cnlive.com All Rights Reserved.
  7 + *
  8 + */
  9 +
  10 +package org.smart4j.framework.mvc.bean;
  11 +
  12 +import org.smart4j.framework.core.bean.BaseBean;
  13 +
  14 +
  15 +public class ResultBean extends BaseBean {
  16 + private String errorMessage;
  17 + private Object data;
  18 + private String errorCode;
  19 + public String getErrorMessage() {
  20 + return errorMessage;
  21 + }
  22 + public void setErrorMessage(String errorMessage) {
  23 + this.errorMessage = errorMessage;
  24 + }
  25 + public Object getData() {
  26 + return data;
  27 + }
  28 + public void setData(Object data) {
  29 + this.data = data;
  30 + }
  31 + public String getErrorCode() {
  32 + return errorCode;
  33 + }
  34 + public void setErrorCode(String errorCode) {
  35 + this.errorCode = errorCode;
  36 + }
  37 +
  38 +}
src/main/java/org/smart4j/framework/mvc/bean/View.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/bean/View.java
  1 +package org.smart4j.framework.mvc.bean;
  2 +
  3 +import java.util.HashMap;
  4 +import java.util.Map;
  5 +import org.smart4j.framework.core.bean.BaseBean;
  6 +
  7 +/**
  8 + * 封装视图对象
  9 + *
  10 + * @author huangyong
  11 + * @since 1.0
  12 + */
  13 +public class View extends BaseBean {
  14 +
  15 + private String path; // 视图路径
  16 + private Map<String, Object> data; // 相关数据
  17 +
  18 + public View(String path) {
  19 + this.path = path;
  20 + data = new HashMap<String, Object>();
  21 + }
  22 +
  23 + public View data(String key, Object value) {
  24 + data.put(key, value);
  25 + return this;
  26 + }
  27 +
  28 + public boolean isRedirect() {
  29 + return path.startsWith("/");
  30 + }
  31 +
  32 + public String getPath() {
  33 + return path;
  34 + }
  35 +
  36 + public void setPath(String path) {
  37 + this.path = path;
  38 + }
  39 +
  40 + public Map<String, Object> getData() {
  41 + return data;
  42 + }
  43 +
  44 + public void setData(Map<String, Object> data) {
  45 + this.data = data;
  46 + }
  47 +}
src/main/java/org/smart4j/framework/mvc/fault/AuthcException.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/fault/AuthcException.java
  1 +package org.smart4j.framework.mvc.fault;
  2 +
  3 +/**
  4 + * 认证异常(当非法访问时抛出)
  5 + *
  6 + * @author huangyong
  7 + * @since 2.1
  8 + */
  9 +public class AuthcException extends RuntimeException {
  10 +
  11 + public AuthcException() {
  12 + super();
  13 + }
  14 +
  15 + public AuthcException(String message) {
  16 + super(message);
  17 + }
  18 +
  19 + public AuthcException(String message, Throwable cause) {
  20 + super(message, cause);
  21 + }
  22 +
  23 + public AuthcException(Throwable cause) {
  24 + super(cause);
  25 + }
  26 +}
src/main/java/org/smart4j/framework/mvc/fault/AuthzException.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/fault/AuthzException.java
  1 +package org.smart4j.framework.mvc.fault;
  2 +
  3 +/**
  4 + * 授权异常(当权限无效时抛出)
  5 + *
  6 + * @author huangyong
  7 + * @since 2.1
  8 + */
  9 +public class AuthzException extends RuntimeException {
  10 +
  11 + public AuthzException() {
  12 + super();
  13 + }
  14 +
  15 + public AuthzException(String message) {
  16 + super(message);
  17 + }
  18 +
  19 + public AuthzException(String message, Throwable cause) {
  20 + super(message, cause);
  21 + }
  22 +
  23 + public AuthzException(Throwable cause) {
  24 + super(cause);
  25 + }
  26 +}
src/main/java/org/smart4j/framework/mvc/fault/UploadException.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/fault/UploadException.java
  1 +package org.smart4j.framework.mvc.fault;
  2 +
  3 +/**
  4 + * 上传异常(当文件上传失败时抛出)
  5 + *
  6 + * @author huangyong
  7 + * @since 2.1
  8 + */
  9 +public class UploadException extends RuntimeException {
  10 +
  11 + public UploadException() {
  12 + super();
  13 + }
  14 +
  15 + public UploadException(String message) {
  16 + super(message);
  17 + }
  18 +
  19 + public UploadException(String message, Throwable cause) {
  20 + super(message, cause);
  21 + }
  22 +
  23 + public UploadException(Throwable cause) {
  24 + super(cause);
  25 + }
  26 +}
src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerExceptionResolver.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerExceptionResolver.java
  1 +package org.smart4j.framework.mvc.impl;
  2 +
  3 +import javax.servlet.http.HttpServletRequest;
  4 +import javax.servlet.http.HttpServletResponse;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
  7 +import org.smart4j.framework.FrameworkConstant;
  8 +import org.smart4j.framework.mvc.HandlerExceptionResolver;
  9 +import org.smart4j.framework.mvc.fault.AuthcException;
  10 +import org.smart4j.framework.mvc.fault.AuthzException;
  11 +import org.smart4j.framework.util.WebUtil;
  12 +
  13 +/**
  14 + * 默认 Handler 异常解析器
  15 + *
  16 + * @author huangyong
  17 + * @since 2.3
  18 + */
  19 +public class DefaultHandlerExceptionResolver implements HandlerExceptionResolver {
  20 +
  21 + private static final Logger logger = LoggerFactory.getLogger(DefaultHandlerExceptionResolver.class);
  22 +
  23 + @Override
  24 + public void resolveHandlerException(HttpServletRequest request, HttpServletResponse response, Exception e) {
  25 + // 判断异常原因
  26 + e.printStackTrace();
  27 + Throwable cause = e.getCause();
  28 + if (cause == null) {
  29 + logger.error(e.getMessage(), e);
  30 + return;
  31 + }
  32 + if (cause instanceof AuthcException) {
  33 + // 分两种情况进行处理
  34 + if (WebUtil.isAJAX(request)) {
  35 + // 跳转到 403 页面
  36 + WebUtil.sendError(HttpServletResponse.SC_FORBIDDEN, "", response);
  37 + } else {
  38 + // 重定向到首页
  39 + WebUtil.redirectRequest(FrameworkConstant.HOME_PAGE, request, response);
  40 + }
  41 + } else if (cause instanceof AuthzException) {
  42 + // 跳转到 403 页面
  43 + WebUtil.sendError(HttpServletResponse.SC_FORBIDDEN, "", response);
  44 + } else {
  45 + // 跳转到 500 页面
  46 + WebUtil.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, cause.getMessage(), response);
  47 + }
  48 + }
  49 +}
src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerInvoker.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerInvoker.java
  1 +package org.smart4j.framework.mvc.impl;
  2 +
  3 +import java.lang.reflect.InvocationTargetException;
  4 +import java.lang.reflect.Method;
  5 +import java.util.ArrayList;
  6 +import java.util.List;
  7 +import java.util.Map;
  8 +import java.util.regex.Matcher;
  9 +import javax.servlet.http.HttpServletRequest;
  10 +import javax.servlet.http.HttpServletResponse;
  11 +import org.smart4j.framework.InstanceFactory;
  12 +import org.smart4j.framework.ioc.BeanHelper;
  13 +import org.smart4j.framework.mvc.Handler;
  14 +import org.smart4j.framework.mvc.HandlerInvoker;
  15 +import org.smart4j.framework.mvc.UploadHelper;
  16 +import org.smart4j.framework.mvc.ViewResolver;
  17 +import org.smart4j.framework.mvc.bean.Params;
  18 +import org.smart4j.framework.util.CastUtil;
  19 +import org.smart4j.framework.util.ClassUtil;
  20 +import org.smart4j.framework.util.MapUtil;
  21 +import org.smart4j.framework.util.WebUtil;
  22 +
  23 +/**
  24 + * 默认 Handler 调用器
  25 + *
  26 + * @author huangyong
  27 + * @since 2.3
  28 + */
  29 +public class DefaultHandlerInvoker implements HandlerInvoker {
  30 +
  31 + private ViewResolver viewResolver = InstanceFactory.getViewResolver();
  32 +
  33 + @Override
  34 + public void invokeHandler(HttpServletRequest request, HttpServletResponse response, Handler handler) throws Exception {
  35 + // 获取 Action 相关信息
  36 + Class<?> actionClass = handler.getActionClass();
  37 + Method actionMethod = handler.getActionMethod();
  38 + // 从 BeanHelper 中创建 Action 实例
  39 + Object actionInstance = BeanHelper.getBean(actionClass);
  40 + // 创建 Action 方法的参数列表
  41 + List<Object> actionMethodParamList = createActionMethodParamList(request, handler);
  42 + // 检查参数列表是否合法
  43 + checkParamList(actionMethod, actionMethodParamList);
  44 + // 调用 Action 方法
  45 + Object actionMethodResult = invokeActionMethod(actionMethod, actionInstance, actionMethodParamList);
  46 + // 解析视图
  47 + viewResolver.resolveView(request, response, actionMethodResult);
  48 + }
  49 +
  50 + public List<Object> createActionMethodParamList(HttpServletRequest request, Handler handler) throws Exception {
  51 + // 定义参数列表
  52 + List<Object> paramList = new ArrayList<Object>();
  53 + // 获取 Action 方法参数类型
  54 + Class<?>[] actionParamTypes = handler.getActionMethod().getParameterTypes();
  55 + // 添加路径参数列表(请求路径中的带占位符参数)
  56 + paramList.addAll(createPathParamList(handler.getRequestPathMatcher(), actionParamTypes));
  57 + // 分两种情况进行处理
  58 + if (UploadHelper.isMultipart(request)) {
  59 + // 添加 Multipart 请求参数列表
  60 + paramList.addAll(UploadHelper.createMultipartParamList(request));
  61 + } else {
  62 + // 添加普通请求参数列表(包括 Query String 与 Form Data)
  63 + Map<String, Object> requestParamMap = WebUtil.getRequestParamMap(request);
  64 + if (MapUtil.isNotEmpty(requestParamMap)) {
  65 + paramList.add(new Params(requestParamMap));
  66 + }
  67 + }
  68 + // 返回参数列表
  69 + return paramList;
  70 + }
  71 +
  72 + private List<Object> createPathParamList(Matcher requestPathMatcher, Class<?>[] actionParamTypes) {
  73 + // 定义参数列表
  74 + List<Object> paramList = new ArrayList<Object>();
  75 + // 遍历正则表达式中所匹配的组
  76 + for (int i = 1; i <= requestPathMatcher.groupCount(); i++) {
  77 + // 获取请求参数
  78 + String param = requestPathMatcher.group(i);
  79 + // 获取参数类型(支持四种类型:int/Integer、long/Long、double/Double、String)
  80 + Class<?> paramType = actionParamTypes[i - 1];
  81 + if (ClassUtil.isInt(paramType)) {
  82 + paramList.add(CastUtil.castInt(param));
  83 + } else if (ClassUtil.isLong(paramType)) {
  84 + paramList.add(CastUtil.castLong(param));
  85 + } else if (ClassUtil.isDouble(paramType)) {
  86 + paramList.add(CastUtil.castDouble(param));
  87 + } else if (ClassUtil.isString(paramType)) {
  88 + paramList.add(param);
  89 + }
  90 + }
  91 + // 返回参数列表
  92 + return paramList;
  93 + }
  94 +
  95 + private Object invokeActionMethod(Method actionMethod, Object actionInstance, List<Object> actionMethodParamList) throws IllegalAccessException, InvocationTargetException {
  96 + // 通过反射调用 Action 方法
  97 + actionMethod.setAccessible(true); // 取消类型安全检测(可提高反射性能)
  98 + return actionMethod.invoke(actionInstance, actionMethodParamList.toArray());
  99 + }
  100 +
  101 + private void checkParamList(Method actionMethod, List<Object> actionMethodParamList) {
  102 + // 判断 Action 方法参数的个数是否匹配
  103 + Class<?>[] actionMethodParameterTypes = actionMethod.getParameterTypes();
  104 + if (actionMethodParameterTypes.length != actionMethodParamList.size()) {
  105 + String message = String.format("因为参数个数不匹配,所以无法调用 Action 方法!原始参数个数:%d,实际参数个数:%d", actionMethodParameterTypes.length, actionMethodParamList.size());
  106 + throw new RuntimeException(message);
  107 + }
  108 + }
  109 +}
src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerMapping.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/impl/DefaultHandlerMapping.java
  1 +package org.smart4j.framework.mvc.impl;
  2 +
  3 +import java.util.Map;
  4 +import java.util.regex.Matcher;
  5 +import java.util.regex.Pattern;
  6 +import org.smart4j.framework.mvc.ActionHelper;
  7 +import org.smart4j.framework.mvc.Handler;
  8 +import org.smart4j.framework.mvc.HandlerMapping;
  9 +import org.smart4j.framework.mvc.Requester;
  10 +
  11 +/**
  12 + * 默认处理器映射,负责处理请求url和action 的方法对应
  13 + *
  14 + * @author huangyong
  15 + * @since 2.3
  16 + */
  17 +public class DefaultHandlerMapping implements HandlerMapping {
  18 +
  19 + @Override
  20 + public Handler getHandler(String currentRequestMethod, String currentRequestPath) {
  21 + // 定义一个 Handler
  22 + Handler handler = null;
  23 + // 获取并遍历 Action 映射
  24 + Map<Requester, Handler> actionMap = ActionHelper.getActionMap();
  25 + for (Map.Entry<Requester, Handler> actionEntry : actionMap.entrySet()) {
  26 + // 从 Requester 中获取 Request 相关属性
  27 + Requester requester = actionEntry.getKey();
  28 + String requestMethod = requester.getRequestMethod();
  29 + String requestPath = requester.getRequestPath(); // 正则表达式
  30 + // 获取请求路径匹配器(使用正则表达式匹配请求路径并从中获取相应的请求参数)
  31 + Matcher requestPathMatcher = Pattern.compile(requestPath).matcher(currentRequestPath);
  32 + // 判断请求方法与请求路径是否同时匹配
  33 + if (requestMethod.equalsIgnoreCase(currentRequestMethod) && requestPathMatcher.matches()) {
  34 + // 获取 Handler 及其相关属性
  35 + handler = actionEntry.getValue();
  36 + // 设置请求路径匹配器
  37 + if (handler != null) {
  38 + handler.setRequestPathMatcher(requestPathMatcher);
  39 + }
  40 + // 若成功匹配,则终止循环
  41 + break;
  42 + }
  43 + }
  44 + // 返回该 Handler
  45 + return handler;
  46 + }
  47 +}
src/main/java/org/smart4j/framework/mvc/impl/DefaultViewResolver.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/mvc/impl/DefaultViewResolver.java
  1 +package org.smart4j.framework.mvc.impl;
  2 +
  3 +import java.util.Map;
  4 +
  5 +import javax.servlet.http.HttpServletRequest;
  6 +import javax.servlet.http.HttpServletResponse;
  7 +
  8 +import org.smart4j.framework.FrameworkConstant;
  9 +import org.smart4j.framework.mvc.UploadHelper;
  10 +import org.smart4j.framework.mvc.ViewResolver;
  11 +import org.smart4j.framework.mvc.bean.ApiBean;
  12 +import org.smart4j.framework.mvc.bean.Redirect;
  13 +import org.smart4j.framework.mvc.bean.Result;
  14 +import org.smart4j.framework.mvc.bean.ResultBean;
  15 +import org.smart4j.framework.mvc.bean.View;
  16 +import org.smart4j.framework.util.MapUtil;
  17 +import org.smart4j.framework.util.WebUtil;
  18 +
  19 +/**
  20 + * 默认视图解析器
  21 + *
  22 + * @author huangyong
  23 + * @since 2.3
  24 + */
  25 +public class DefaultViewResolver implements ViewResolver {
  26 +
  27 + @Override
  28 + public void resolveView(HttpServletRequest request, HttpServletResponse response, Object actionMethodResult) {
  29 + if (actionMethodResult != null) {
  30 + // Action 返回值可为 View 或 Result
  31 + if (actionMethodResult instanceof View) {
  32 + // 若为 View,则需考虑两种视图类型(重定向 或 转发)
  33 + View view = (View) actionMethodResult;
  34 + if (view.isRedirect()) {
  35 + // 获取路径
  36 + String path = view.getPath();
  37 + // 重定向请求
  38 + WebUtil.redirectRequest(path, request, response);
  39 + } else {
  40 + // 获取路径
  41 + String path = FrameworkConstant.JSP_PATH + view.getPath();
  42 + // 初始化请求属性
  43 + Map<String, Object> data = view.getData();
  44 + if (MapUtil.isNotEmpty(data)) {
  45 + for (Map.Entry<String, Object> entry : data.entrySet()) {
  46 + request.setAttribute(entry.getKey(), entry.getValue());
  47 + }
  48 + }
  49 + // 转发请求
  50 + WebUtil.forwardRequest(path, request, response);
  51 + }
  52 + } else if (actionMethodResult instanceof ApiBean) {
  53 + ApiBean api = (ApiBean) actionMethodResult;
  54 + // 对于其它类型,统一转换为 JSON 格式并写入响应中
  55 + WebUtil.writeJSON(response, api);
  56 + }else if (actionMethodResult instanceof ResultBean) {
  57 + ResultBean api = (ResultBean) actionMethodResult;
  58 + WebUtil.writeJSON(response, api);
  59 + } else if (actionMethodResult instanceof Redirect) {
  60 + Redirect api = (Redirect) actionMethodResult;
  61 + WebUtil.redirect(response, api);
  62 + } else {
  63 + // 若为 Result,则需考虑两种请求类型(文件上传 或 普通请求)
  64 + Result result = (Result) actionMethodResult;
  65 + if (UploadHelper.isMultipart(request)) {
  66 + // 对于 multipart 类型,说明是文件上传,需要转换为 HTML 格式并写入响应中
  67 + WebUtil.writeHTML(response, result);
  68 + } else {
  69 + // 对于其它类型,统一转换为 JSON 格式并写入响应中
  70 + WebUtil.writeJSON(response, result);
  71 + }
  72 + }
  73 + }
  74 + }
  75 +}
src/main/java/org/smart4j/framework/orm/DataSet.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/orm/DataSet.java
  1 +package org.smart4j.framework.orm;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.ArrayList;
  5 +import java.util.Iterator;
  6 +import java.util.LinkedHashMap;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +import java.util.Set;
  10 +
  11 +import org.apache.commons.lang.StringUtils;
  12 +import org.smart4j.framework.FrameworkConstant;
  13 +import org.smart4j.framework.dao.DatabaseHelper;
  14 +import org.smart4j.framework.dao.SqlHelper;
  15 +import org.smart4j.framework.orm.bean.Condition;
  16 +import org.smart4j.framework.util.ArrayUtil;
  17 +import org.smart4j.framework.util.MapUtil;
  18 +import org.smart4j.framework.util.ObjectUtil;
  19 +
  20 +/**
  21 + * 提供与实体相关的数据库操作
  22 + *
  23 + * @author huangyong
  24 + * @since 1.0
  25 + */
  26 +public class DataSet {
  27 +
  28 + /**
  29 + * 查询单条数据,并转为相应类型的实体
  30 + */
  31 + public static <T> T select(Class<T> entityClass, String condition, Object... params) {
  32 + String sql = SqlHelper.generateSelectSql(entityClass, condition, "");
  33 + return DatabaseHelper.queryEntity(entityClass, sql, params);
  34 + }
  35 +
  36 + /**
  37 + * 查询多条数据,并转为相应类型的实体列表
  38 + */
  39 + public static <T> List<T> selectList(Class<T> entityClass) {
  40 + return selectListWithConditionAndSort(entityClass, "", "");
  41 + }
  42 +
  43 + /**
  44 + * 查询多条数据,并转为相应类型的实体列表(带有查询条件与查询参数)
  45 + */
  46 + public static <T> List<T> selectListWithCondition(Class<T> entityClass, String condition, Object... params) {
  47 + return selectListWithConditionAndSort(entityClass, condition, "", params);
  48 + }
  49 +
  50 + /**
  51 + * 查询多条数据,并转为相应类型的实体列表(带有排序方式)
  52 + */
  53 + public static <T> List<T> selectListWithSort(Class<T> entityClass, String sort) {
  54 + return selectListWithConditionAndSort(entityClass, "", sort);
  55 + }
  56 +
  57 + /**
  58 + * 查询多条数据,并转为相应类型的实体列表(带有查询条件、排序方式与查询参数)
  59 + */
  60 + public static <T> List<T> selectListWithConditionAndSort(Class<T> entityClass, String condition, String sort,
  61 + Object... params) {
  62 + String sql = SqlHelper.generateSelectSql(entityClass, condition, sort);
  63 + return DatabaseHelper.queryEntityList(entityClass, sql, params);
  64 + }
  65 +
  66 + /**
  67 + * 查询数据条数
  68 + */
  69 + public static long selectCount(Class<?> entityClass, String condition, Object... params) {
  70 + String sql = SqlHelper.generateSelectSqlForCount(entityClass, condition);
  71 + return DatabaseHelper.queryCount(sql, params);
  72 + }
  73 +
  74 + /**
  75 + * @param sql
  76 + * @param params
  77 + * @return
  78 + */
  79 + public static List<Map<String, Object>> selectMapWithSql(String sql, Object... params) {
  80 + return DatabaseHelper.queryMapList(sql, params);
  81 + }
  82 +
  83 + /**
  84 + * 适合于搜索查询 统计数
  85 + *
  86 + * @param entityClass
  87 + * @param conditions
  88 + * @return
  89 + */
  90 + public static long selectCount(Class<?> entityClass, List<Condition> conditions) {
  91 + String conditionSql = "";
  92 + List<String> list = new ArrayList<String>();
  93 + // 移除值为空的条件
  94 + List<Condition> cons = new ArrayList<Condition>();
  95 + for (int i = 0; i < conditions.size(); i++) {
  96 + Condition con = conditions.get(i);
  97 + String value = con.getValue();
  98 + if (StringUtils.isNotEmpty(value) && StringUtils.isNotEmpty(value.replace("%", ""))) {
  99 + cons.add(con);
  100 + }
  101 + }
  102 + for (int i = 0; i < cons.size(); i++) {
  103 + Condition con = cons.get(i);
  104 + String condition = con.getCondition();
  105 + String operator = con.getOperator();
  106 + String value = con.getValue();
  107 + if (i == cons.size() - 1) {
  108 + conditionSql += condition;
  109 + } else {
  110 + conditionSql += condition + " " + operator + " ";
  111 + }
  112 + list.add(value);
  113 + }
  114 + String sql = SqlHelper.generateSelectSqlForCount(entityClass, conditionSql);
  115 + return DatabaseHelper.queryCount(sql, list.toArray());
  116 + }
  117 +
  118 + /**
  119 + * 适合于搜索查询
  120 + *
  121 + * @param pageNumber
  122 + * @param pageSize
  123 + * @param entityClass
  124 + * @param conditions
  125 + * @param sort
  126 + * @return
  127 + */
  128 + public static <T> List<T> selectListForPager(int pageNumber, int pageSize, Class<T> entityClass,
  129 + List<Condition> conditions, String sort) {
  130 + String conditionSql = "";
  131 + // 移除值为空的条件
  132 + List<Condition> cons = new ArrayList<Condition>();
  133 + for (int i = 0; i < conditions.size(); i++) {
  134 + Condition con = conditions.get(i);
  135 + String value = con.getValue();
  136 + if (StringUtils.isNotEmpty(value) && StringUtils.isNotEmpty(value.replace("%", ""))) {
  137 + cons.add(con);
  138 + }
  139 + }
  140 +
  141 + List<String> list = new ArrayList<String>();
  142 + for (int i = 0; i < cons.size(); i++) {
  143 + Condition con = cons.get(i);
  144 + String condition = con.getCondition();
  145 + String operator = con.getOperator();
  146 + String value = con.getValue();
  147 + if (i == cons.size() - 1) {
  148 + conditionSql += condition;
  149 + } else {
  150 + conditionSql += condition + " " + operator + " ";
  151 + }
  152 + list.add(value);
  153 + }
  154 + String sql = SqlHelper.generateSelectSqlForPager(pageNumber, pageSize, entityClass, conditionSql, sort);
  155 + return DatabaseHelper.queryEntityList(entityClass, sql, list.toArray());
  156 + }
  157 +
  158 + /**
  159 + * 查询多条数据,并转为列表(分页方式)
  160 + */
  161 + public static <T> List<T> selectListForPager(int pageNumber, int pageSize, Class<T> entityClass, String condition,
  162 + String sort, Object... params) {
  163 + String sql = SqlHelper.generateSelectSqlForPager(pageNumber, pageSize, entityClass, condition, sort);
  164 + return DatabaseHelper.queryEntityList(entityClass, sql, params);
  165 + }
  166 +
  167 + /**
  168 + * 查询多条数据,并转为映射
  169 + */
  170 + public static <T> Map<Long, T> selectMap(Class<T> entityClass) {
  171 + return selectMapWithPK(entityClass, FrameworkConstant.PK_NAME, "", "");
  172 + }
  173 +
  174 + /**
  175 + * 查询多条数据,并转为映射(带有查询条件与查询参数)
  176 + */
  177 + public static <T> Map<Long, T> selectMapWithCondition(Class<T> entityClass, String condition, Object... params) {
  178 + return selectMapWithPK(entityClass, FrameworkConstant.PK_NAME, condition, "", params);
  179 + }
  180 +
  181 + /**
  182 + * 查询多条数据,并转为映射(带有排序方式与查询参数)
  183 + *
  184 + * @since 2.3.3
  185 + */
  186 + public static <T> Map<Long, T> selectMapWithSort(Class<T> entityClass, String sort) {
  187 + return selectMapWithPK(entityClass, FrameworkConstant.PK_NAME, "", sort);
  188 + }
  189 +
  190 + /**
  191 + * 查询多条数据,并转为映射(带有查询条件、排序方式与查询参数)
  192 + */
  193 + public static <T> Map<Long, T> selectMapWithConditionAndSort(Class<T> entityClass, String condition, String sort,
  194 + Object... params) {
  195 + return selectMapWithPK(entityClass, FrameworkConstant.PK_NAME, condition, sort, params);
  196 + }
  197 +
  198 + /**
  199 + * 查询多条数据,并转为映射(带有主键名)
  200 + */
  201 + @SuppressWarnings("unchecked")
  202 + public static <PK, T> Map<PK, T> selectMapWithPK(Class<T> entityClass, String pkName, String condition,
  203 + String sort, Object... params) {
  204 + Map<PK, T> map = new LinkedHashMap<PK, T>();
  205 + List<T> list = selectListWithConditionAndSort(entityClass, condition, sort, params);
  206 + for (T obj : list) {
  207 + PK pk = (PK) ObjectUtil.getFieldValue(obj, pkName);
  208 + map.put(pk, obj);
  209 + }
  210 + return map;
  211 + }
  212 +
  213 + /**
  214 + * 根据列名查询单条数据,并转为相应类型的实体
  215 + */
  216 + public static <T> T selectColumn(Class<?> entityClass, String columnName, String condition, Object... params) {
  217 + String sql = SqlHelper.generateSelectSql(entityClass, condition, "");
  218 + sql = sql.replace("*", columnName);
  219 + return DatabaseHelper.queryColumn(sql, params);
  220 + }
  221 +
  222 + /**
  223 + * 根据列名查询多条数据,并转为相应类型的实体列表
  224 + */
  225 + public static <T> List<T> selectColumnList(Class<?> entityClass, String columnName, String condition, String sort,
  226 + Object... params) {
  227 + String sql = SqlHelper.generateSelectSql(entityClass, condition, sort);
  228 + sql = sql.replace("*", columnName);
  229 + return DatabaseHelper.queryColumnList(sql, params);
  230 + }
  231 +
  232 + /**
  233 + * 插入一条数据
  234 + */
  235 + public static boolean insert(Class<?> entityClass, Map<String, Object> fieldMap) {
  236 + if (MapUtil.isEmpty(fieldMap)) {
  237 + return true;
  238 + }
  239 + String sql = SqlHelper.generateInsertSql(entityClass, fieldMap.keySet());
  240 + int rows = DatabaseHelper.update(sql, fieldMap.values().toArray());
  241 + return rows > 0;
  242 + }
  243 +
  244 + /**
  245 + * 插入一条数据
  246 + */
  247 + public static Serializable insertForKeys(Class<?> entityClass, Map<String, Object> fieldMap) {
  248 + if (MapUtil.isEmpty(fieldMap)) {
  249 + return -1;
  250 + }
  251 + String sql = SqlHelper.generateInsertSql(entityClass, fieldMap.keySet());
  252 + return DatabaseHelper.insertReturnPK(sql, fieldMap.values().toArray());
  253 + }
  254 +
  255 + /**
  256 + * 插入一个实体
  257 + */
  258 + public static boolean insert(Object entity) {
  259 + if (entity == null) {
  260 + throw new IllegalArgumentException();
  261 + }
  262 + Class<?> entityClass = entity.getClass();
  263 + Map<String, Object> fieldMap = ObjectUtil.getFieldMap(entity);
  264 + return insert(entityClass, fieldMap);
  265 + }
  266 +
  267 + public static Serializable insertForKeys(Object entity) {
  268 + if (entity == null) {
  269 + throw new IllegalArgumentException();
  270 + }
  271 + Class<?> entityClass = entity.getClass();
  272 + Map<String, Object> fieldMap = ObjectUtil.getFieldMap(entity);
  273 + return insertForKeys(entityClass, fieldMap);
  274 + }
  275 +
  276 + /**
  277 + * 更新相关数据
  278 + */
  279 + public static boolean update(Class<?> entityClass, Map<String, Object> fieldMap, String condition, Object... params) {
  280 + if (MapUtil.isEmpty(fieldMap)) {
  281 + return true;
  282 + }
  283 + String sql = SqlHelper.generateUpdateSql(entityClass, fieldMap, condition);
  284 + int rows = DatabaseHelper.update(sql, ArrayUtil.concat(fieldMap.values().toArray(), params));
  285 + return rows > 0;
  286 + }
  287 +
  288 + /**
  289 + * 更新一个实体
  290 + */
  291 + public static boolean update(Object entity) {
  292 + return update(entity, FrameworkConstant.PK_NAME);
  293 + }
  294 +
  295 + /**
  296 + * 更新一个实体(带有主键名)
  297 + */
  298 + public static boolean update(Object entityObject, String pkName) {
  299 + if (entityObject == null) {
  300 + throw new IllegalArgumentException();
  301 + }
  302 + Class<?> entityClass = entityObject.getClass();
  303 + Map<String, Object> fieldMap = ObjectUtil.getFieldMap(entityObject);
  304 + String condition = pkName + " = ?";
  305 + Object[] params = { ObjectUtil.getFieldValue(entityObject, pkName) };
  306 + return update(entityClass, fieldMap, condition, params);
  307 + }
  308 +
  309 + /**
  310 + * 删除相关数据
  311 + */
  312 + public static boolean delete(Class<?> entityClass, String condition, Object... params) {
  313 + String sql = SqlHelper.generateDeleteSql(entityClass, condition);
  314 + int rows = DatabaseHelper.update(sql, params);
  315 + return rows > 0;
  316 + }
  317 +
  318 + /**
  319 + * 删除一个实体
  320 + */
  321 + public static boolean delete(Object entityObject) {
  322 + return delete(entityObject, FrameworkConstant.PK_NAME);
  323 + }
  324 +
  325 + /**
  326 + * 删除一个实体(可指定主键名)
  327 + */
  328 + public static boolean delete(Object entityObject, String pkName) {
  329 + if (entityObject == null) {
  330 + throw new IllegalArgumentException();
  331 + }
  332 + Class<?> entityClass = entityObject.getClass();
  333 + String condition = pkName + " = ?";
  334 + Object[] params = { ObjectUtil.getFieldValue(entityObject, pkName) };
  335 + return delete(entityClass, condition, params);
  336 + }
  337 +}
src/main/java/org/smart4j/framework/orm/EntityHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/orm/EntityHelper.java
  1 +package org.smart4j.framework.orm;
  2 +
  3 +import java.lang.reflect.Field;
  4 +import java.util.HashMap;
  5 +import java.util.List;
  6 +import java.util.Map;
  7 +
  8 +import org.smart4j.framework.core.ClassHelper;
  9 +import org.smart4j.framework.orm.annotation.Column;
  10 +import org.smart4j.framework.orm.annotation.Entity;
  11 +import org.smart4j.framework.orm.annotation.Table;
  12 +import org.smart4j.framework.util.ArrayUtil;
  13 +import org.smart4j.framework.util.MapUtil;
  14 +import org.smart4j.framework.util.StringUtil;
  15 +
  16 +/**
  17 + * 负责处理数据库表明和实体类文件的对应</br>
  18 + * 同时也完成数据库字段和类属性的对应map集合中存放map(数据库字段--属性)
  19 + */
  20 +public class EntityHelper {
  21 +
  22 + /**
  23 + * 实体类 => 表名
  24 + */
  25 + private static final Map<Class<?>, String> entityClassTableNameMap = new HashMap<Class<?>, String>();
  26 +
  27 + /**
  28 + * 实体类 => (字段名 => 列名)
  29 + */
  30 + private static final Map<Class<?>, Map<String, String>> entityClassFieldMapMap = new HashMap<Class<?>, Map<String, String>>();
  31 +
  32 + static {
  33 + // 获取并遍历所有实体类
  34 + List<Class<?>> entityClassList = ClassHelper.getClassListByAnnotation(Entity.class);
  35 + for (Class<?> entityClass : entityClassList) {
  36 + initEntityNameMap(entityClass);
  37 + initEntityFieldMapMap(entityClass);
  38 + }
  39 + }
  40 +
  41 + private static void initEntityNameMap(Class<?> entityClass) {
  42 + // 判断该实体类上是否存在 Table 注解
  43 + String tableName;
  44 + if (entityClass.isAnnotationPresent(Table.class)) {
  45 + // 若已存在,则使用该注解中定义的表名
  46 + tableName = entityClass.getAnnotation(Table.class).value();
  47 + } else {
  48 + // 若不存在,则将实体类名转换为下划线风格的表名
  49 + tableName = StringUtil.camelhumpToUnderline(entityClass.getSimpleName());
  50 + }
  51 + entityClassTableNameMap.put(entityClass, tableName);
  52 + }
  53 +
  54 + private static void initEntityFieldMapMap(Class<?> entityClass) {
  55 + // 获取并遍历该实体类中所有的字段(不包括父类中的方法)
  56 + Field[] fields = entityClass.getDeclaredFields();
  57 + if (ArrayUtil.isNotEmpty(fields)) {
  58 + // 创建一个 fieldMap(用于存放列名与字段名的映射关系)
  59 + Map<String, String> fieldMap = new HashMap<String, String>();
  60 + for (Field field : fields) {
  61 + String fieldName = field.getName();
  62 + String columnName;
  63 + // 判断该字段上是否存在 Column 注解
  64 + if (field.isAnnotationPresent(Column.class)) {
  65 + // 若已存在,则使用该注解中定义的列名
  66 + columnName = field.getAnnotation(Column.class).value();
  67 + } else {
  68 + // 若不存在,则将字段名转换为下划线风格的列名
  69 + columnName = StringUtil.camelhumpToUnderline(fieldName);
  70 + }
  71 + fieldMap.put(fieldName, columnName);
  72 + }
  73 + entityClassFieldMapMap.put(entityClass, fieldMap);
  74 + }
  75 + }
  76 +
  77 + public static String getTableName(Class<?> entityClass) {
  78 + return entityClassTableNameMap.get(entityClass);
  79 + }
  80 +
  81 + public static Map<String, String> getFieldMap(Class<?> entityClass) {
  82 + return entityClassFieldMapMap.get(entityClass);
  83 + }
  84 +
  85 + public static Map<String, String> getColumnMap(Class<?> entityClass) {
  86 + return MapUtil.invert(getFieldMap(entityClass));
  87 + }
  88 +
  89 + public static String getColumnName(Class<?> entityClass, String fieldName) {
  90 + String columnName = getFieldMap(entityClass).get(fieldName);
  91 + return StringUtil.isNotEmpty(columnName) ? columnName : fieldName;
  92 + }
  93 +}
src/main/java/org/smart4j/framework/orm/annotation/Column.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/orm/annotation/Column.java
  1 +package org.smart4j.framework.orm.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 定义列名
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +@Target(ElementType.FIELD)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Column {
  17 +
  18 + String value();
  19 +}
src/main/java/org/smart4j/framework/orm/annotation/Entity.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/orm/annotation/Entity.java
  1 +package org.smart4j.framework.orm.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 定义 Entity 类
  10 + *
  11 + * @author huangyong
  12 + * @since 2.3
  13 + */
  14 +@Target(ElementType.TYPE)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Entity {
  17 +}
src/main/java/org/smart4j/framework/orm/annotation/Table.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/orm/annotation/Table.java
  1 +package org.smart4j.framework.orm.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * 定义表名
  10 + *
  11 + * @author huangyong
  12 + * @since 1.0
  13 + */
  14 +@Target(ElementType.TYPE)
  15 +@Retention(RetentionPolicy.RUNTIME)
  16 +public @interface Table {
  17 +
  18 + String value();
  19 +}
src/main/java/org/smart4j/framework/orm/bean/Condition.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/orm/bean/Condition.java
  1 +/**
  2 + * Project Name:smart-framework
  3 + * File Name:Condition.java
  4 + * Package Name:org.smart4j.framework.orm.bean
  5 + * Date:2016年3月8日下午9:51:05
  6 + * Copyright (c) 2016, cnlive.com All Rights Reserved.
  7 + *
  8 + */
  9 +
  10 +package org.smart4j.framework.orm.bean;
  11 +
  12 +/**
  13 + * TODO: 这里用一句话描述当前类的作用 Date: 2016年3月8日 下午9:51:05 <br/>
  14 + *
  15 + * @author liujicheng
  16 + * @version V1.0
  17 + * @since JDK 1.6
  18 + */
  19 +public class Condition {
  20 + //name=?
  21 + private String condition;
  22 + //and
  23 + private String operator;
  24 + //liujicheng
  25 + private String value;
  26 +
  27 + public Condition(String condition, String value, String operator) {
  28 + this.condition = condition;
  29 + this.value = value;
  30 + this.operator = operator;
  31 +
  32 + }
  33 +
  34 + public String getCondition() {
  35 + return condition;
  36 + }
  37 +
  38 + public void setCondition(String condition) {
  39 + this.condition = condition;
  40 + }
  41 +
  42 + public String getOperator() {
  43 + return operator;
  44 + }
  45 +
  46 + public void setOperator(String operator) {
  47 + this.operator = operator;
  48 + }
  49 +
  50 + public String getValue() {
  51 + return value;
  52 + }
  53 +
  54 + public void setValue(String value) {
  55 + this.value = value;
  56 + }
  57 +
  58 +}
src/main/java/org/smart4j/framework/plugin/Plugin.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/plugin/Plugin.java
  1 +package org.smart4j.framework.plugin;
  2 +
  3 +/**
  4 + * 插件接口
  5 + *
  6 + * @author huangyong
  7 + * @since 2.0
  8 + */
  9 +public interface Plugin {
  10 +
  11 + /**
  12 + * 初始化插件
  13 + */
  14 + void init();
  15 +
  16 + /**
  17 + * 销毁插件
  18 + */
  19 + void destroy();
  20 +}
src/main/java/org/smart4j/framework/plugin/PluginHelper.java 0 → 100644
  1 +++ a/src/main/java/org/smart4j/framework/plugin/PluginHelper.java
  1 +package org.smart4j.framework.plugin;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.List;
  5 +import org.smart4j.framework.FrameworkConstant;
  6 +import org.smart4j.framework.InstanceFactory;
  7 +import org.smart4j.framework.core.ClassScanner;
  8 +import org.smart4j.framework.core.fault.InitializationError;
  9 +
  10 +/**
  11 + * 初始化插件
  12 + *
  13 + * @author huangyong
  14 + * @since 2.0
  15 + */
  16 +public class PluginHelper {
  17 +
  18 + /**
  19 + * 创建一个插件列表(用于存放插件实例)
  20 + */
  21 + private static final List<Plugin> pluginList = new ArrayList<Plugin>();
  22 +
  23 + /**
  24 + * 获取 ClassScanner
  25 + */
  26 + private static final ClassScanner classScanner = InstanceFactory.getClassScanner();
  27 +
  28 + static {
  29 + try {
  30 + // 获取并遍历所有的插件类(实现了 Plugin 接口的类)
  31 + List<Class<?>> pluginClassList = classScanner.getClassListBySuper(FrameworkConstant.PLUGIN_PACKAGE, Plugin.class);
  32 + for (Class<?> pluginClass : pluginClassList) {
  33 + // 创建插件实例
  34 + Plugin plugin = (Plugin) pluginClass.newInstance();
  35 + // 调用初始化方法
  36 + plugin.init();
  37 + // 将插件实例添加到插件列表中
  38 + pluginList.add(plugin);
  39 + }
  40 + } catch (Exception e) {
  41 + throw new InitializationError("初始化 PluginHelper 出错!", e);
  42 + }
  43 + }
  44 +
  45 + /**
  46 + * 获取所有插件
  47 + */
  48 + public static List<Plugin> getPluginList() {
  49 + return pluginList;
  50 + }
  51 +}