Commit 24efae760546a9f4bf9bd8ba8a986d6795d9cbb1
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
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 | +} |