Commit 24efae760546a9f4bf9bd8ba8a986d6795d9cbb1
0 parents
init
Showing
90 changed files
with
6659 additions
and
0 deletions
.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 | 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 | 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 | 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 | 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 | 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 | +} | ... | ... |
src/main/java/org/smart4j/framework/plugin/PluginProxy.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/plugin/PluginProxy.java | |
| 1 | +package org.smart4j.framework.plugin; | |
| 2 | + | |
| 3 | +import java.util.List; | |
| 4 | +import org.smart4j.framework.aop.proxy.Proxy; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * 插件代理 | |
| 8 | + * | |
| 9 | + * @author huangyong | |
| 10 | + * @since 2.0 | |
| 11 | + */ | |
| 12 | +public abstract class PluginProxy implements Proxy { | |
| 13 | + | |
| 14 | + public abstract List<Class<?>> getTargetClassList(); | |
| 15 | +} | ... | ... |
src/main/java/org/smart4j/framework/plugin/WebPlugin.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/plugin/WebPlugin.java | |
| 1 | +package org.smart4j.framework.plugin; | |
| 2 | + | |
| 3 | +import javax.servlet.ServletContext; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * 基于 Web 的插件抽象实现,拥有 Plugin 接口的所有功能 | |
| 7 | + * <br/> | |
| 8 | + * 可在子类中注册 Servlet、Filter、Listener 等 | |
| 9 | + * | |
| 10 | + * @author huangyong | |
| 11 | + * @since 2.3 | |
| 12 | + */ | |
| 13 | +public abstract class WebPlugin implements Plugin { | |
| 14 | + | |
| 15 | + @Override | |
| 16 | + public void init() { | |
| 17 | + } | |
| 18 | + | |
| 19 | + @Override | |
| 20 | + public void destroy() { | |
| 21 | + } | |
| 22 | + | |
| 23 | + public abstract void register(ServletContext servletContext); | |
| 24 | +} | ... | ... |
src/main/java/org/smart4j/framework/tx/TransactionProxy.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/tx/TransactionProxy.java | |
| 1 | +package org.smart4j.framework.tx; | |
| 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 | +import org.smart4j.framework.dao.DatabaseHelper; | |
| 9 | +import org.smart4j.framework.tx.annotation.Transaction; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 事务代理 | |
| 13 | + * | |
| 14 | + * @author huangyong | |
| 15 | + * @since 2.0 | |
| 16 | + */ | |
| 17 | +public class TransactionProxy implements Proxy { | |
| 18 | + | |
| 19 | + private static final Logger logger = LoggerFactory.getLogger(TransactionProxy.class); | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 定义一个线程局部变量,用于保存当前线程中是否进行了事务处理,默认为 false(未处理) | |
| 23 | + */ | |
| 24 | + private static final ThreadLocal<Boolean> flagContainer = new ThreadLocal<Boolean>() { | |
| 25 | + @Override | |
| 26 | + protected Boolean initialValue() { | |
| 27 | + return false; | |
| 28 | + } | |
| 29 | + }; | |
| 30 | + | |
| 31 | + @Override | |
| 32 | + public Object doProxy(ProxyChain proxyChain) throws Throwable { | |
| 33 | + Object result; | |
| 34 | + // 判断当前线程是否进行了事务处理 | |
| 35 | + boolean flag = flagContainer.get(); | |
| 36 | + // 获取目标方法 | |
| 37 | + Method method = proxyChain.getTargetMethod(); | |
| 38 | + // 若当前线程未进行事务处理,且在目标方法上定义了 Transaction 注解,则说明该方法需要进行事务处理 | |
| 39 | + if (!flag && method.isAnnotationPresent(Transaction.class)) { | |
| 40 | + // 设置当前线程已进行事务处理 | |
| 41 | + flagContainer.set(true); | |
| 42 | + try { | |
| 43 | + // 开启事务 | |
| 44 | + DatabaseHelper.beginTransaction(); | |
| 45 | + logger.debug("[Smart] begin transaction"); | |
| 46 | + // 执行目标方法 | |
| 47 | + result = proxyChain.doProxyChain(); | |
| 48 | + // 提交事务 | |
| 49 | + DatabaseHelper.commitTransaction(); | |
| 50 | + logger.debug("[Smart] commit transaction"); | |
| 51 | + } catch (Exception e) { | |
| 52 | + // 回滚事务 | |
| 53 | + DatabaseHelper.rollbackTransaction(); | |
| 54 | + logger.debug("[Smart] rollback transaction"); | |
| 55 | + throw e; | |
| 56 | + } finally { | |
| 57 | + // 移除线程局部变量 | |
| 58 | + flagContainer.remove(); | |
| 59 | + } | |
| 60 | + } else { | |
| 61 | + // 执行目标方法 | |
| 62 | + result = proxyChain.doProxyChain(); | |
| 63 | + } | |
| 64 | + return result; | |
| 65 | + } | |
| 66 | +} | ... | ... |
src/main/java/org/smart4j/framework/tx/annotation/Service.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/tx/annotation/Service.java | |
| 1 | +package org.smart4j.framework.tx.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 | + * 定义 Service 类 | |
| 10 | + * | |
| 11 | + * @author huangyong | |
| 12 | + * @since 1.0 | |
| 13 | + */ | |
| 14 | +@Target(ElementType.TYPE) | |
| 15 | +@Retention(RetentionPolicy.RUNTIME) | |
| 16 | +public @interface Service { | |
| 17 | +} | ... | ... |
src/main/java/org/smart4j/framework/tx/annotation/Transaction.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/tx/annotation/Transaction.java | |
| 1 | +package org.smart4j.framework.tx.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 Transaction { | |
| 17 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/ArrayUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/ArrayUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import org.apache.commons.lang.ArrayUtils; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * 数组操作工具类 | |
| 7 | + * | |
| 8 | + * @author huangyong | |
| 9 | + * @since 1.0 | |
| 10 | + */ | |
| 11 | +public class ArrayUtil { | |
| 12 | + | |
| 13 | + /** | |
| 14 | + * 判断数组是否非空 | |
| 15 | + */ | |
| 16 | + public static boolean isNotEmpty(Object[] array) { | |
| 17 | + return !ArrayUtils.isEmpty(array); | |
| 18 | + } | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 判断数组是否为空 | |
| 22 | + */ | |
| 23 | + public static boolean isEmpty(Object[] array) { | |
| 24 | + return ArrayUtils.isEmpty(array); | |
| 25 | + } | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * 连接数组 | |
| 29 | + */ | |
| 30 | + public static Object[] concat(Object[] array1, Object[] array2) { | |
| 31 | + return ArrayUtils.addAll(array1, array2); | |
| 32 | + } | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 判断对象是否在数组中 | |
| 36 | + */ | |
| 37 | + public static <T> boolean contains(T[] array, T obj) { | |
| 38 | + return ArrayUtils.contains(array, obj); | |
| 39 | + } | |
| 40 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/CastUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/CastUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 转型操作工具类 | |
| 5 | + * | |
| 6 | + * @author huangyong | |
| 7 | + * @since 1.0 | |
| 8 | + */ | |
| 9 | +public class CastUtil { | |
| 10 | + | |
| 11 | + /** | |
| 12 | + * 转为 String 型 | |
| 13 | + */ | |
| 14 | + public static String castString(Object obj) { | |
| 15 | + return CastUtil.castString(obj, ""); | |
| 16 | + } | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 转为 String 型(提供默认值) | |
| 20 | + */ | |
| 21 | + public static String castString(Object obj, String defaultValue) { | |
| 22 | + return obj != null ? String.valueOf(obj) : defaultValue; | |
| 23 | + } | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 转为 double 型 | |
| 27 | + */ | |
| 28 | + public static double castDouble(Object obj) { | |
| 29 | + return CastUtil.castDouble(obj, 0); | |
| 30 | + } | |
| 31 | + | |
| 32 | + /** | |
| 33 | + * 转为 double 型(提供默认值) | |
| 34 | + */ | |
| 35 | + public static double castDouble(Object obj, double defaultValue) { | |
| 36 | + double doubleValue = defaultValue; | |
| 37 | + if (obj != null) { | |
| 38 | + String strValue = castString(obj); | |
| 39 | + if (StringUtil.isNotEmpty(strValue)) { | |
| 40 | + try { | |
| 41 | + doubleValue = Double.parseDouble(strValue); | |
| 42 | + } catch (NumberFormatException e) { | |
| 43 | + doubleValue = defaultValue; | |
| 44 | + } | |
| 45 | + } | |
| 46 | + } | |
| 47 | + return doubleValue; | |
| 48 | + } | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * 转为 long 型 | |
| 52 | + */ | |
| 53 | + public static long castLong(Object obj) { | |
| 54 | + return CastUtil.castLong(obj, 0); | |
| 55 | + } | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * 转为 long 型(提供默认值) | |
| 59 | + */ | |
| 60 | + public static long castLong(Object obj, long defaultValue) { | |
| 61 | + long longValue = defaultValue; | |
| 62 | + if (obj != null) { | |
| 63 | + String strValue = castString(obj); | |
| 64 | + if (StringUtil.isNotEmpty(strValue)) { | |
| 65 | + try { | |
| 66 | + longValue = Long.parseLong(strValue); | |
| 67 | + } catch (NumberFormatException e) { | |
| 68 | + longValue = defaultValue; | |
| 69 | + } | |
| 70 | + } | |
| 71 | + } | |
| 72 | + return longValue; | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * 转为 int 型 | |
| 77 | + */ | |
| 78 | + public static int castInt(Object obj) { | |
| 79 | + return CastUtil.castInt(obj, 0); | |
| 80 | + } | |
| 81 | + | |
| 82 | + /** | |
| 83 | + * 转为 int 型(提供默认值) | |
| 84 | + */ | |
| 85 | + public static int castInt(Object obj, int defaultValue) { | |
| 86 | + int intValue = defaultValue; | |
| 87 | + if (obj != null) { | |
| 88 | + String strValue = castString(obj); | |
| 89 | + if (StringUtil.isNotEmpty(strValue)) { | |
| 90 | + try { | |
| 91 | + intValue = Integer.parseInt(strValue); | |
| 92 | + } catch (NumberFormatException e) { | |
| 93 | + intValue = defaultValue; | |
| 94 | + } | |
| 95 | + } | |
| 96 | + } | |
| 97 | + return intValue; | |
| 98 | + } | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * 转为 boolean 型 | |
| 102 | + */ | |
| 103 | + public static boolean castBoolean(Object obj) { | |
| 104 | + return CastUtil.castBoolean(obj, false); | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * 转为 boolean 型(提供默认值) | |
| 109 | + */ | |
| 110 | + public static boolean castBoolean(Object obj, boolean defaultValue) { | |
| 111 | + boolean booleanValue = defaultValue; | |
| 112 | + if (obj != null) { | |
| 113 | + booleanValue = Boolean.parseBoolean(castString(obj)); | |
| 114 | + } | |
| 115 | + return booleanValue; | |
| 116 | + } | |
| 117 | + | |
| 118 | + /** | |
| 119 | + * 转为 String[] 型 | |
| 120 | + */ | |
| 121 | + public static String[] castStringArray(Object[] objArray) { | |
| 122 | + if (objArray == null) { | |
| 123 | + objArray = new Object[0]; | |
| 124 | + } | |
| 125 | + String[] strArray = new String[objArray.length]; | |
| 126 | + if (ArrayUtil.isNotEmpty(objArray)) { | |
| 127 | + for (int i = 0; i < objArray.length; i++) { | |
| 128 | + strArray[i] = castString(objArray[i]); | |
| 129 | + } | |
| 130 | + } | |
| 131 | + return strArray; | |
| 132 | + } | |
| 133 | + | |
| 134 | + /** | |
| 135 | + * 转为 double[] 型 | |
| 136 | + */ | |
| 137 | + public static double[] castDoubleArray(Object[] objArray) { | |
| 138 | + if (objArray == null) { | |
| 139 | + objArray = new Object[0]; | |
| 140 | + } | |
| 141 | + double[] doubleArray = new double[objArray.length]; | |
| 142 | + if (!ArrayUtil.isEmpty(objArray)) { | |
| 143 | + for (int i = 0; i < objArray.length; i++) { | |
| 144 | + doubleArray[i] = castDouble(objArray[i]); | |
| 145 | + } | |
| 146 | + } | |
| 147 | + return doubleArray; | |
| 148 | + } | |
| 149 | + | |
| 150 | + /** | |
| 151 | + * 转为 long[] 型 | |
| 152 | + */ | |
| 153 | + public static long[] castLongArray(Object[] objArray) { | |
| 154 | + if (objArray == null) { | |
| 155 | + objArray = new Object[0]; | |
| 156 | + } | |
| 157 | + long[] longArray = new long[objArray.length]; | |
| 158 | + if (!ArrayUtil.isEmpty(objArray)) { | |
| 159 | + for (int i = 0; i < objArray.length; i++) { | |
| 160 | + longArray[i] = castLong(objArray[i]); | |
| 161 | + } | |
| 162 | + } | |
| 163 | + return longArray; | |
| 164 | + } | |
| 165 | + | |
| 166 | + /** | |
| 167 | + * 转为 int[] 型 | |
| 168 | + */ | |
| 169 | + public static int[] castIntArray(Object[] objArray) { | |
| 170 | + if (objArray == null) { | |
| 171 | + objArray = new Object[0]; | |
| 172 | + } | |
| 173 | + int[] intArray = new int[objArray.length]; | |
| 174 | + if (!ArrayUtil.isEmpty(objArray)) { | |
| 175 | + for (int i = 0; i < objArray.length; i++) { | |
| 176 | + intArray[i] = castInt(objArray[i]); | |
| 177 | + } | |
| 178 | + } | |
| 179 | + return intArray; | |
| 180 | + } | |
| 181 | + | |
| 182 | + /** | |
| 183 | + * 转为 boolean[] 型 | |
| 184 | + */ | |
| 185 | + public static boolean[] castBooleanArray(Object[] objArray) { | |
| 186 | + if (objArray == null) { | |
| 187 | + objArray = new Object[0]; | |
| 188 | + } | |
| 189 | + boolean[] booleanArray = new boolean[objArray.length]; | |
| 190 | + if (!ArrayUtil.isEmpty(objArray)) { | |
| 191 | + for (int i = 0; i < objArray.length; i++) { | |
| 192 | + booleanArray[i] = castBoolean(objArray[i]); | |
| 193 | + } | |
| 194 | + } | |
| 195 | + return booleanArray; | |
| 196 | + } | |
| 197 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/ClassUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/ClassUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.net.URL; | |
| 4 | +import org.slf4j.Logger; | |
| 5 | +import org.slf4j.LoggerFactory; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 类操作工具类 | |
| 9 | + * | |
| 10 | + * @author huangyong | |
| 11 | + * @since 1.0 | |
| 12 | + */ | |
| 13 | +public class ClassUtil { | |
| 14 | + | |
| 15 | + private static final Logger logger = LoggerFactory.getLogger(ClassUtil.class); | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 获取类加载器 | |
| 19 | + */ | |
| 20 | + public static ClassLoader getClassLoader() { | |
| 21 | + return Thread.currentThread().getContextClassLoader(); | |
| 22 | + } | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * 获取类路径 | |
| 26 | + */ | |
| 27 | + public static String getClassPath() { | |
| 28 | + String classpath = ""; | |
| 29 | + URL resource = getClassLoader().getResource(""); | |
| 30 | + if (resource != null) { | |
| 31 | + classpath = resource.getPath(); | |
| 32 | + } | |
| 33 | + return classpath; | |
| 34 | + } | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * 加载类(将自动初始化) | |
| 38 | + */ | |
| 39 | + public static Class<?> loadClass(String className) { | |
| 40 | + return loadClass(className, true); | |
| 41 | + } | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 加载类 | |
| 45 | + */ | |
| 46 | + public static Class<?> loadClass(String className, boolean isInitialized) { | |
| 47 | + Class<?> cls; | |
| 48 | + try { | |
| 49 | + cls = Class.forName(className, isInitialized, getClassLoader()); | |
| 50 | + } catch (ClassNotFoundException e) { | |
| 51 | + logger.error("加载类出错!", e); | |
| 52 | + throw new RuntimeException(e); | |
| 53 | + } | |
| 54 | + return cls; | |
| 55 | + } | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * 是否为 int 类型(包括 Integer 类型) | |
| 59 | + */ | |
| 60 | + public static boolean isInt(Class<?> type) { | |
| 61 | + return type.equals(int.class) || type.equals(Integer.class); | |
| 62 | + } | |
| 63 | + | |
| 64 | + /** | |
| 65 | + * 是否为 long 类型(包括 Long 类型) | |
| 66 | + */ | |
| 67 | + public static boolean isLong(Class<?> type) { | |
| 68 | + return type.equals(long.class) || type.equals(Long.class); | |
| 69 | + } | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * 是否为 double 类型(包括 Double 类型) | |
| 73 | + */ | |
| 74 | + public static boolean isDouble(Class<?> type) { | |
| 75 | + return type.equals(double.class) || type.equals(Double.class); | |
| 76 | + } | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * 是否为 String 类型 | |
| 80 | + */ | |
| 81 | + public static boolean isString(Class<?> type) { | |
| 82 | + return type.equals(String.class); | |
| 83 | + } | |
| 84 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/CodecUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/CodecUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.io.UnsupportedEncodingException; | |
| 4 | +import java.net.URLDecoder; | |
| 5 | +import java.net.URLEncoder; | |
| 6 | +import java.util.UUID; | |
| 7 | +import org.apache.commons.codec.binary.Base64; | |
| 8 | +import org.apache.commons.codec.digest.DigestUtils; | |
| 9 | +import org.apache.commons.lang.RandomStringUtils; | |
| 10 | +import org.slf4j.Logger; | |
| 11 | +import org.slf4j.LoggerFactory; | |
| 12 | +import org.smart4j.framework.FrameworkConstant; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 编码与解码操作工具类 | |
| 16 | + * | |
| 17 | + * @author huangyong | |
| 18 | + * @since 1.0 | |
| 19 | + */ | |
| 20 | +public class CodecUtil { | |
| 21 | + | |
| 22 | + private static final Logger logger = LoggerFactory.getLogger(CodecUtil.class); | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * 将 URL 编码 | |
| 26 | + */ | |
| 27 | + public static String encodeURL(String str) { | |
| 28 | + String target; | |
| 29 | + try { | |
| 30 | + target = URLEncoder.encode(str, FrameworkConstant.UTF_8); | |
| 31 | + } catch (Exception e) { | |
| 32 | + logger.error("编码出错!", e); | |
| 33 | + throw new RuntimeException(e); | |
| 34 | + } | |
| 35 | + return target; | |
| 36 | + } | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * 将 URL 解码 | |
| 40 | + */ | |
| 41 | + public static String decodeURL(String str) { | |
| 42 | + String target; | |
| 43 | + try { | |
| 44 | + target = URLDecoder.decode(str, FrameworkConstant.UTF_8); | |
| 45 | + } catch (Exception e) { | |
| 46 | + logger.error("解码出错!", e); | |
| 47 | + throw new RuntimeException(e); | |
| 48 | + } | |
| 49 | + return target; | |
| 50 | + } | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * 将字符串 Base64 编码 | |
| 54 | + */ | |
| 55 | + public static String encodeBASE64(String str) { | |
| 56 | + String target; | |
| 57 | + try { | |
| 58 | + target = Base64.encodeBase64URLSafeString(str.getBytes(FrameworkConstant.UTF_8)); | |
| 59 | + } catch (UnsupportedEncodingException e) { | |
| 60 | + logger.error("编码出错!", e); | |
| 61 | + throw new RuntimeException(e); | |
| 62 | + } | |
| 63 | + return target; | |
| 64 | + } | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * 将字符串 Base64 解码 | |
| 68 | + */ | |
| 69 | + public static String decodeBASE64(String str) { | |
| 70 | + String target; | |
| 71 | + try { | |
| 72 | + target = new String(Base64.decodeBase64(str), FrameworkConstant.UTF_8); | |
| 73 | + } catch (UnsupportedEncodingException e) { | |
| 74 | + logger.error("解码出错!", e); | |
| 75 | + throw new RuntimeException(e); | |
| 76 | + } | |
| 77 | + return target; | |
| 78 | + } | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * 将字符串 MD5 加密 | |
| 82 | + */ | |
| 83 | + public static String encryptMD5(String str) { | |
| 84 | + return DigestUtils.md5Hex(str); | |
| 85 | + } | |
| 86 | + | |
| 87 | + /** | |
| 88 | + * 将字符串 SHA 加密 | |
| 89 | + */ | |
| 90 | + public static String encryptSHA(String str) { | |
| 91 | + return DigestUtils.sha1Hex(str); | |
| 92 | + } | |
| 93 | + | |
| 94 | + /** | |
| 95 | + * 创建随机数 | |
| 96 | + */ | |
| 97 | + public static String createRandom(int count) { | |
| 98 | + return RandomStringUtils.randomNumeric(count); | |
| 99 | + } | |
| 100 | + | |
| 101 | + /** | |
| 102 | + * 获取 UUID(32位) | |
| 103 | + */ | |
| 104 | + public static String createUUID() { | |
| 105 | + return UUID.randomUUID().toString().replaceAll("-", ""); | |
| 106 | + } | |
| 107 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/CollectionUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/CollectionUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.util.Collection; | |
| 4 | +import org.apache.commons.collections.CollectionUtils; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * 集合操作工具类 | |
| 8 | + * | |
| 9 | + * @author huangyong | |
| 10 | + * @since 1.0 | |
| 11 | + */ | |
| 12 | +public class CollectionUtil { | |
| 13 | + | |
| 14 | + /** | |
| 15 | + * 判断集合是否非空 | |
| 16 | + */ | |
| 17 | + public static boolean isNotEmpty(Collection<?> collection) { | |
| 18 | + return CollectionUtils.isNotEmpty(collection); | |
| 19 | + } | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 判断集合是否为空 | |
| 23 | + */ | |
| 24 | + public static boolean isEmpty(Collection<?> collection) { | |
| 25 | + return CollectionUtils.isEmpty(collection); | |
| 26 | + } | |
| 27 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/DateUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/DateUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.text.ParseException; | |
| 4 | +import java.text.SimpleDateFormat; | |
| 5 | +import java.util.Date; | |
| 6 | +import org.slf4j.Logger; | |
| 7 | +import org.slf4j.LoggerFactory; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 日期操作工具类 | |
| 11 | + * | |
| 12 | + * @author huangyong | |
| 13 | + * @since 1.0 | |
| 14 | + */ | |
| 15 | +public class DateUtil { | |
| 16 | + | |
| 17 | + private static final Logger logger = LoggerFactory.getLogger(DateUtil.class); | |
| 18 | + | |
| 19 | + private static final SimpleDateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| 20 | + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); | |
| 21 | + private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 格式化日期与时间 | |
| 25 | + */ | |
| 26 | + public static String formatDatetime(long timestamp) { | |
| 27 | + return datetimeFormat.format(new Date(timestamp)); | |
| 28 | + } | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * 格式化日期 | |
| 32 | + */ | |
| 33 | + public static String formatDate(long timestamp) { | |
| 34 | + return dateFormat.format(new Date(timestamp)); | |
| 35 | + } | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * 格式化时间 | |
| 39 | + */ | |
| 40 | + public static String formatTime(long timestamp) { | |
| 41 | + return timeFormat.format(new Date(timestamp)); | |
| 42 | + } | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * 获取当前日期与时间 | |
| 46 | + */ | |
| 47 | + public static String getCurrentDatetime() { | |
| 48 | + return datetimeFormat.format(new Date()); | |
| 49 | + } | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * 获取当前日期 | |
| 53 | + */ | |
| 54 | + public static String getCurrentDate() { | |
| 55 | + return dateFormat.format(new Date()); | |
| 56 | + } | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * 获取当前时间 | |
| 60 | + */ | |
| 61 | + public static String getCurrentTime() { | |
| 62 | + return timeFormat.format(new Date()); | |
| 63 | + } | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 解析日期与时间 | |
| 67 | + */ | |
| 68 | + public static Date parseDatetime(String str) { | |
| 69 | + Date date = null; | |
| 70 | + try { | |
| 71 | + date = datetimeFormat.parse(str); | |
| 72 | + } catch (ParseException e) { | |
| 73 | + logger.error("解析日期字符串出错!格式:yyyy-MM-dd HH:mm:ss", e); | |
| 74 | + } | |
| 75 | + return date; | |
| 76 | + } | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * 解析日期 | |
| 80 | + */ | |
| 81 | + public static Date parseDate(String str) { | |
| 82 | + Date date = null; | |
| 83 | + try { | |
| 84 | + date = dateFormat.parse(str); | |
| 85 | + } catch (ParseException e) { | |
| 86 | + logger.error("解析日期字符串出错!格式:yyyy-MM-dd", e); | |
| 87 | + } | |
| 88 | + return date; | |
| 89 | + } | |
| 90 | + | |
| 91 | + /** | |
| 92 | + * 解析时间 | |
| 93 | + */ | |
| 94 | + public static Date parseTime(String str) { | |
| 95 | + Date date = null; | |
| 96 | + try { | |
| 97 | + date = timeFormat.parse(str); | |
| 98 | + } catch (ParseException e) { | |
| 99 | + logger.error("解析日期字符串出错!格式:HH:mm:ss", e); | |
| 100 | + } | |
| 101 | + return date; | |
| 102 | + } | |
| 103 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/FileUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/FileUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.io.BufferedOutputStream; | |
| 4 | +import java.io.File; | |
| 5 | +import java.io.FileOutputStream; | |
| 6 | +import java.io.OutputStream; | |
| 7 | +import java.io.OutputStreamWriter; | |
| 8 | +import java.io.Writer; | |
| 9 | +import org.apache.commons.io.FileUtils; | |
| 10 | +import org.apache.commons.io.FilenameUtils; | |
| 11 | +import org.slf4j.Logger; | |
| 12 | +import org.slf4j.LoggerFactory; | |
| 13 | +import org.smart4j.framework.FrameworkConstant; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * 文件操作工具类 | |
| 17 | + * | |
| 18 | + * @author huangyong | |
| 19 | + * @since 1.0 | |
| 20 | + */ | |
| 21 | +public class FileUtil { | |
| 22 | + | |
| 23 | + private static final Logger logger = LoggerFactory.getLogger(FileUtil.class); | |
| 24 | + | |
| 25 | + /** | |
| 26 | + * 创建目录 | |
| 27 | + */ | |
| 28 | + public static File createDir(String dirPath) { | |
| 29 | + File dir; | |
| 30 | + try { | |
| 31 | + dir = new File(dirPath); | |
| 32 | + if (!dir.exists()) { | |
| 33 | + FileUtils.forceMkdir(dir); | |
| 34 | + } | |
| 35 | + } catch (Exception e) { | |
| 36 | + logger.error("创建目录出错!", e); | |
| 37 | + throw new RuntimeException(e); | |
| 38 | + } | |
| 39 | + return dir; | |
| 40 | + } | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * 创建文件 | |
| 44 | + */ | |
| 45 | + public static File createFile(String filePath) { | |
| 46 | + File file; | |
| 47 | + try { | |
| 48 | + file = new File(filePath); | |
| 49 | + File parentDir = file.getParentFile(); | |
| 50 | + if (!parentDir.exists()) { | |
| 51 | + FileUtils.forceMkdir(parentDir); | |
| 52 | + } | |
| 53 | + } catch (Exception e) { | |
| 54 | + logger.error("创建文件出错!", e); | |
| 55 | + throw new RuntimeException(e); | |
| 56 | + } | |
| 57 | + return file; | |
| 58 | + } | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * 复制目录(不会复制空目录) | |
| 62 | + */ | |
| 63 | + public static void copyDir(String srcPath, String destPath) { | |
| 64 | + try { | |
| 65 | + File srcDir = new File(srcPath); | |
| 66 | + File destDir = new File(destPath); | |
| 67 | + if (srcDir.exists() && srcDir.isDirectory()) { | |
| 68 | + FileUtils.copyDirectoryToDirectory(srcDir, destDir); | |
| 69 | + } | |
| 70 | + } catch (Exception e) { | |
| 71 | + logger.error("复制目录出错!", e); | |
| 72 | + throw new RuntimeException(e); | |
| 73 | + } | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * 复制文件 | |
| 78 | + */ | |
| 79 | + public static void copyFile(String srcPath, String destPath) { | |
| 80 | + try { | |
| 81 | + File srcFile = new File(srcPath); | |
| 82 | + File destDir = new File(destPath); | |
| 83 | + if (srcFile.exists() && srcFile.isFile()) { | |
| 84 | + FileUtils.copyFileToDirectory(srcFile, destDir); | |
| 85 | + } | |
| 86 | + } catch (Exception e) { | |
| 87 | + logger.error("复制文件出错!", e); | |
| 88 | + throw new RuntimeException(e); | |
| 89 | + } | |
| 90 | + } | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * 删除目录 | |
| 94 | + */ | |
| 95 | + public static void deleteDir(String dirPath) { | |
| 96 | + try { | |
| 97 | + File dir = new File(dirPath); | |
| 98 | + if (dir.exists() && dir.isDirectory()) { | |
| 99 | + FileUtils.deleteDirectory(dir); | |
| 100 | + } | |
| 101 | + } catch (Exception e) { | |
| 102 | + logger.error("删除目录出错!", e); | |
| 103 | + throw new RuntimeException(e); | |
| 104 | + } | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * 删除文件 | |
| 109 | + */ | |
| 110 | + public static void deleteFile(String filePath) { | |
| 111 | + try { | |
| 112 | + File file = new File(filePath); | |
| 113 | + if (file.exists() && file.isFile()) { | |
| 114 | + FileUtils.forceDelete(file); | |
| 115 | + } | |
| 116 | + } catch (Exception e) { | |
| 117 | + logger.error("删除文件出错!", e); | |
| 118 | + throw new RuntimeException(e); | |
| 119 | + } | |
| 120 | + } | |
| 121 | + | |
| 122 | + /** | |
| 123 | + * 重命名文件 | |
| 124 | + */ | |
| 125 | + public static void renameFile(String srcPath, String destPath) { | |
| 126 | + File srcFile = new File(srcPath); | |
| 127 | + if (srcFile.exists()) { | |
| 128 | + File newFile = new File(destPath); | |
| 129 | + boolean result = srcFile.renameTo(newFile); | |
| 130 | + if (!result) { | |
| 131 | + throw new RuntimeException("重命名文件出错!" + newFile); | |
| 132 | + } | |
| 133 | + } | |
| 134 | + } | |
| 135 | + | |
| 136 | + /** | |
| 137 | + * 将字符串写入文件 | |
| 138 | + */ | |
| 139 | + public static void writeFile(String filePath, String fileContent) { | |
| 140 | + OutputStream os = null; | |
| 141 | + Writer w = null; | |
| 142 | + try { | |
| 143 | + FileUtil.createFile(filePath); | |
| 144 | + os = new BufferedOutputStream(new FileOutputStream(filePath)); | |
| 145 | + w = new OutputStreamWriter(os, FrameworkConstant.UTF_8); | |
| 146 | + w.write(fileContent); | |
| 147 | + w.flush(); | |
| 148 | + } catch (Exception e) { | |
| 149 | + logger.error("写入文件出错!", e); | |
| 150 | + throw new RuntimeException(e); | |
| 151 | + } finally { | |
| 152 | + try { | |
| 153 | + if (os != null) { | |
| 154 | + os.close(); | |
| 155 | + } | |
| 156 | + if (w != null) { | |
| 157 | + w.close(); | |
| 158 | + } | |
| 159 | + } catch (Exception e) { | |
| 160 | + logger.error("释放资源出错!", e); | |
| 161 | + } | |
| 162 | + } | |
| 163 | + } | |
| 164 | + | |
| 165 | + /** | |
| 166 | + * 获取真实文件名(去掉文件路径) | |
| 167 | + */ | |
| 168 | + public static String getRealFileName(String fileName) { | |
| 169 | + return FilenameUtils.getName(fileName); | |
| 170 | + } | |
| 171 | + | |
| 172 | + /** | |
| 173 | + * 判断文件是否存在 | |
| 174 | + */ | |
| 175 | + public static boolean checkFileExists(String filePath) { | |
| 176 | + return new File(filePath).exists(); | |
| 177 | + } | |
| 178 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/JsonUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/JsonUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import org.codehaus.jackson.map.ObjectMapper; | |
| 4 | +import org.slf4j.Logger; | |
| 5 | +import org.slf4j.LoggerFactory; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * JSON 操作工具类 | |
| 9 | + * | |
| 10 | + * @author huangyong | |
| 11 | + * @since 1.0 | |
| 12 | + */ | |
| 13 | +public class JsonUtil { | |
| 14 | + | |
| 15 | + private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class); | |
| 16 | + | |
| 17 | + private static final ObjectMapper objectMapper = new ObjectMapper(); | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 将 Java 对象转为 JSON 字符串 | |
| 21 | + */ | |
| 22 | + public static <T> String toJSON(T obj) { | |
| 23 | + String jsonStr; | |
| 24 | + try { | |
| 25 | + jsonStr = objectMapper.writeValueAsString(obj); | |
| 26 | + } catch (Exception e) { | |
| 27 | + logger.error("Java 转 JSON 出错!", e); | |
| 28 | + throw new RuntimeException(e); | |
| 29 | + } | |
| 30 | + return jsonStr; | |
| 31 | + } | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 将 JSON 字符串转为 Java 对象 | |
| 35 | + */ | |
| 36 | + public static <T> T fromJSON(String json, Class<T> type) { | |
| 37 | + T obj; | |
| 38 | + try { | |
| 39 | + obj = objectMapper.readValue(json, type); | |
| 40 | + } catch (Exception e) { | |
| 41 | + logger.error("JSON 转 Java 出错!", e); | |
| 42 | + throw new RuntimeException(e); | |
| 43 | + } | |
| 44 | + return obj; | |
| 45 | + } | |
| 46 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/MapUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/MapUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.util.LinkedHashMap; | |
| 4 | +import java.util.Map; | |
| 5 | +import org.apache.commons.collections.MapUtils; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 映射操作工具类 | |
| 9 | + * | |
| 10 | + * @author huangyong | |
| 11 | + * @since 1.0 | |
| 12 | + */ | |
| 13 | +public class MapUtil { | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 判断 Map 是否非空 | |
| 17 | + */ | |
| 18 | + public static boolean isNotEmpty(Map<?, ?> map) { | |
| 19 | + return MapUtils.isNotEmpty(map); | |
| 20 | + } | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 判断 Map 是否为空 | |
| 24 | + */ | |
| 25 | + public static boolean isEmpty(Map<?, ?> map) { | |
| 26 | + return MapUtils.isEmpty(map); | |
| 27 | + } | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 转置 Map | |
| 31 | + */ | |
| 32 | + public static <K, V> Map<V, K> invert(Map<K, V> source) { | |
| 33 | + Map<V, K> target = null; | |
| 34 | + if (isNotEmpty(source)) { | |
| 35 | + target = new LinkedHashMap<V, K>(source.size()); | |
| 36 | + for (Map.Entry<K, V> entry : source.entrySet()) { | |
| 37 | + target.put(entry.getValue(), entry.getKey()); | |
| 38 | + } | |
| 39 | + } | |
| 40 | + return target; | |
| 41 | + } | |
| 42 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/ObjectUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/ObjectUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.lang.reflect.Field; | |
| 4 | +import java.lang.reflect.Modifier; | |
| 5 | +import java.util.LinkedHashMap; | |
| 6 | +import java.util.Map; | |
| 7 | +import org.apache.commons.beanutils.PropertyUtils; | |
| 8 | +import org.slf4j.Logger; | |
| 9 | +import org.slf4j.LoggerFactory; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 对象操作工具类 | |
| 13 | + * | |
| 14 | + * @author huangyong | |
| 15 | + * @since 1.0 | |
| 16 | + */ | |
| 17 | +public class ObjectUtil { | |
| 18 | + | |
| 19 | + private static final Logger logger = LoggerFactory.getLogger(ObjectUtil.class); | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 设置成员变量 | |
| 23 | + */ | |
| 24 | + public static void setField(Object obj, String fieldName, Object fieldValue) { | |
| 25 | + try { | |
| 26 | + if (PropertyUtils.isWriteable(obj, fieldName)) { | |
| 27 | + PropertyUtils.setProperty(obj, fieldName, fieldValue); | |
| 28 | + } | |
| 29 | + } catch (Exception e) { | |
| 30 | + logger.error("设置成员变量出错!", e); | |
| 31 | + throw new RuntimeException(e); | |
| 32 | + } | |
| 33 | + } | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * 获取成员变量 | |
| 37 | + */ | |
| 38 | + public static Object getFieldValue(Object obj, String fieldName) { | |
| 39 | + Object propertyValue = null; | |
| 40 | + try { | |
| 41 | + if (PropertyUtils.isReadable(obj, fieldName)) { | |
| 42 | + propertyValue = PropertyUtils.getProperty(obj, fieldName); | |
| 43 | + } | |
| 44 | + } catch (Exception e) { | |
| 45 | + logger.error("获取成员变量出错!", e); | |
| 46 | + throw new RuntimeException(e); | |
| 47 | + } | |
| 48 | + return propertyValue; | |
| 49 | + } | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * 复制所有成员变量 | |
| 53 | + */ | |
| 54 | + public static void copyFields(Object source, Object target) { | |
| 55 | + try { | |
| 56 | + for (Field field : source.getClass().getDeclaredFields()) { | |
| 57 | + // 若不为 static 成员变量,则进行复制操作 | |
| 58 | + if (!Modifier.isStatic(field.getModifiers())) { | |
| 59 | + field.setAccessible(true); // 可操作私有成员变量 | |
| 60 | + field.set(target, field.get(source)); | |
| 61 | + } | |
| 62 | + } | |
| 63 | + } catch (Exception e) { | |
| 64 | + logger.error("复制成员变量出错!", e); | |
| 65 | + throw new RuntimeException(e); | |
| 66 | + } | |
| 67 | + } | |
| 68 | + | |
| 69 | + /** | |
| 70 | + * 通过反射创建实例 | |
| 71 | + */ | |
| 72 | + @SuppressWarnings("unchecked") | |
| 73 | + public static <T> T newInstance(String className) { | |
| 74 | + T instance; | |
| 75 | + try { | |
| 76 | + Class<?> commandClass = ClassUtil.loadClass(className); | |
| 77 | + instance = (T) commandClass.newInstance(); | |
| 78 | + } catch (Exception e) { | |
| 79 | + logger.error("创建实例出错!", e); | |
| 80 | + throw new RuntimeException(e); | |
| 81 | + } | |
| 82 | + return instance; | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * 获取对象的字段映射(字段名 => 字段值),忽略 static 字段 | |
| 87 | + */ | |
| 88 | + public static Map<String, Object> getFieldMap(Object obj) { | |
| 89 | + return getFieldMap(obj, true); | |
| 90 | + } | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * 获取对象的字段映射(字段名 => 字段值) | |
| 94 | + */ | |
| 95 | + public static Map<String, Object> getFieldMap(Object obj, boolean isStaticIgnored) { | |
| 96 | + Map<String, Object> fieldMap = new LinkedHashMap<String, Object>(); | |
| 97 | + Field[] fields = obj.getClass().getDeclaredFields(); | |
| 98 | + for (Field field : fields) { | |
| 99 | + if (isStaticIgnored && Modifier.isStatic(field.getModifiers())) { | |
| 100 | + continue; | |
| 101 | + } | |
| 102 | + String fieldName = field.getName(); | |
| 103 | + Object fieldValue = ObjectUtil.getFieldValue(obj, fieldName); | |
| 104 | + fieldMap.put(fieldName, fieldValue); | |
| 105 | + } | |
| 106 | + return fieldMap; | |
| 107 | + } | |
| 108 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/PropsUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/PropsUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.io.IOException; | |
| 4 | +import java.io.InputStream; | |
| 5 | +import java.util.HashMap; | |
| 6 | +import java.util.LinkedHashMap; | |
| 7 | +import java.util.Map; | |
| 8 | +import java.util.Properties; | |
| 9 | +import java.util.Set; | |
| 10 | +import org.slf4j.Logger; | |
| 11 | +import org.slf4j.LoggerFactory; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * 属性文件操作工具类 | |
| 15 | + * | |
| 16 | + * @author huangyong | |
| 17 | + * @since 1.0 | |
| 18 | + */ | |
| 19 | +public class PropsUtil { | |
| 20 | + | |
| 21 | + private static final Logger logger = LoggerFactory.getLogger(PropsUtil.class); | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 加载属性文件 | |
| 25 | + */ | |
| 26 | + public static Properties loadProps(String propsPath) { | |
| 27 | + Properties props = new Properties(); | |
| 28 | + InputStream is = null; | |
| 29 | + try { | |
| 30 | + if (StringUtil.isEmpty(propsPath)) { | |
| 31 | + throw new IllegalArgumentException(); | |
| 32 | + } | |
| 33 | + String suffix = ".properties"; | |
| 34 | + if (propsPath.lastIndexOf(suffix) == -1) { | |
| 35 | + propsPath += suffix; | |
| 36 | + } | |
| 37 | + is = ClassUtil.getClassLoader().getResourceAsStream(propsPath); | |
| 38 | + if (is != null) { | |
| 39 | + props.load(is); | |
| 40 | + } | |
| 41 | + } catch (Exception e) { | |
| 42 | + logger.error("加载属性文件出错!", e); | |
| 43 | + throw new RuntimeException(e); | |
| 44 | + } finally { | |
| 45 | + try { | |
| 46 | + if (is != null) { | |
| 47 | + is.close(); | |
| 48 | + } | |
| 49 | + } catch (IOException e) { | |
| 50 | + logger.error("释放资源出错!", e); | |
| 51 | + } | |
| 52 | + } | |
| 53 | + return props; | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * 加载属性文件,并转为 Map | |
| 58 | + */ | |
| 59 | + public static Map<String, String> loadPropsToMap(String propsPath) { | |
| 60 | + Map<String, String> map = new HashMap<String, String>(); | |
| 61 | + Properties props = loadProps(propsPath); | |
| 62 | + for (String key : props.stringPropertyNames()) { | |
| 63 | + map.put(key, props.getProperty(key)); | |
| 64 | + } | |
| 65 | + return map; | |
| 66 | + } | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * 获取字符型属性 | |
| 70 | + */ | |
| 71 | + public static String getString(Properties props, String key) { | |
| 72 | + String value = ""; | |
| 73 | + if (props.containsKey(key)) { | |
| 74 | + value = props.getProperty(key); | |
| 75 | + } | |
| 76 | + return value; | |
| 77 | + } | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * 获取字符型属性(带有默认值) | |
| 81 | + */ | |
| 82 | + public static String getString(Properties props, String key, String defalutValue) { | |
| 83 | + String value = defalutValue; | |
| 84 | + if (props.containsKey(key)) { | |
| 85 | + value = props.getProperty(key); | |
| 86 | + } | |
| 87 | + return value; | |
| 88 | + } | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * 获取数值型属性 | |
| 92 | + */ | |
| 93 | + public static int getNumber(Properties props, String key) { | |
| 94 | + int value = 0; | |
| 95 | + if (props.containsKey(key)) { | |
| 96 | + value = CastUtil.castInt(props.getProperty(key)); | |
| 97 | + } | |
| 98 | + return value; | |
| 99 | + } | |
| 100 | + | |
| 101 | + // 获取数值型属性(带有默认值) | |
| 102 | + public static int getNumber(Properties props, String key, int defaultValue) { | |
| 103 | + int value = defaultValue; | |
| 104 | + if (props.containsKey(key)) { | |
| 105 | + value = CastUtil.castInt(props.getProperty(key)); | |
| 106 | + } | |
| 107 | + return value; | |
| 108 | + } | |
| 109 | + | |
| 110 | + /** | |
| 111 | + * 获取布尔型属性 | |
| 112 | + */ | |
| 113 | + public static boolean getBoolean(Properties props, String key) { | |
| 114 | + return getBoolean(props, key, false); | |
| 115 | + } | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * 获取布尔型属性(带有默认值) | |
| 119 | + */ | |
| 120 | + public static boolean getBoolean(Properties props, String key, boolean defalutValue) { | |
| 121 | + boolean value = defalutValue; | |
| 122 | + if (props.containsKey(key)) { | |
| 123 | + value = CastUtil.castBoolean(props.getProperty(key)); | |
| 124 | + } | |
| 125 | + return value; | |
| 126 | + } | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * 获取指定前缀的相关属性 | |
| 130 | + */ | |
| 131 | + public static Map<String, Object> getMap(Properties props, String prefix) { | |
| 132 | + Map<String, Object> kvMap = new LinkedHashMap<String, Object>(); | |
| 133 | + Set<String> keySet = props.stringPropertyNames(); | |
| 134 | + if (CollectionUtil.isNotEmpty(keySet)) { | |
| 135 | + for (String key : keySet) { | |
| 136 | + if (key.startsWith(prefix)) { | |
| 137 | + String value = props.getProperty(key); | |
| 138 | + kvMap.put(key, value); | |
| 139 | + } | |
| 140 | + } | |
| 141 | + } | |
| 142 | + return kvMap; | |
| 143 | + } | |
| 144 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/StreamUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/StreamUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.io.BufferedReader; | |
| 4 | +import java.io.InputStream; | |
| 5 | +import java.io.InputStreamReader; | |
| 6 | +import java.io.OutputStream; | |
| 7 | +import org.slf4j.Logger; | |
| 8 | +import org.slf4j.LoggerFactory; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 流操作工具类 | |
| 12 | + * | |
| 13 | + * @author huangyong | |
| 14 | + * @since 1.0 | |
| 15 | + */ | |
| 16 | +public class StreamUtil { | |
| 17 | + | |
| 18 | + private static final Logger logger = LoggerFactory.getLogger(StreamUtil.class); | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 将输入流复制到输出流 | |
| 22 | + */ | |
| 23 | + public static void copyStream(InputStream inputStream, OutputStream outputStream) { | |
| 24 | + try { | |
| 25 | + int length; | |
| 26 | + byte[] buffer = new byte[4 * 1024]; | |
| 27 | + while ((length = inputStream.read(buffer, 0, buffer.length)) != -1) { | |
| 28 | + outputStream.write(buffer, 0, length); | |
| 29 | + } | |
| 30 | + outputStream.flush(); | |
| 31 | + } catch (Exception e) { | |
| 32 | + logger.error("复制流出错!", e); | |
| 33 | + throw new RuntimeException(e); | |
| 34 | + } finally { | |
| 35 | + try { | |
| 36 | + inputStream.close(); | |
| 37 | + outputStream.close(); | |
| 38 | + } catch (Exception e) { | |
| 39 | + e.printStackTrace(); | |
| 40 | + logger.error("释放资源出错!", e); | |
| 41 | + } | |
| 42 | + } | |
| 43 | + } | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 从输入流中获取字符串 | |
| 47 | + */ | |
| 48 | + public static String getString(InputStream is) { | |
| 49 | + StringBuilder sb = new StringBuilder(); | |
| 50 | + try { | |
| 51 | + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); | |
| 52 | + String line; | |
| 53 | + while ((line = reader.readLine()) != null) { | |
| 54 | + sb.append(line); | |
| 55 | + } | |
| 56 | + } catch (Exception e) { | |
| 57 | + logger.error("Stream 转 String 出错!", e); | |
| 58 | + throw new RuntimeException(e); | |
| 59 | + } | |
| 60 | + return sb.toString(); | |
| 61 | + } | |
| 62 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/StringUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/StringUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.util.regex.Matcher; | |
| 4 | +import java.util.regex.Pattern; | |
| 5 | +import org.apache.commons.lang.StringUtils; | |
| 6 | +import org.apache.commons.lang.math.NumberUtils; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * 字符串操作工具类 | |
| 10 | + * | |
| 11 | + * @author huangyong | |
| 12 | + * @since 1.0 | |
| 13 | + */ | |
| 14 | +public class StringUtil { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 字符串分隔符 | |
| 18 | + */ | |
| 19 | + public static final String SEPARATOR = String.valueOf((char) 29); | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 判断字符串是否非空 | |
| 23 | + */ | |
| 24 | + public static boolean isNotEmpty(String str) { | |
| 25 | + return StringUtils.isNotEmpty(str); | |
| 26 | + } | |
| 27 | + | |
| 28 | + /** | |
| 29 | + * 判断字符串是否为空 | |
| 30 | + */ | |
| 31 | + public static boolean isEmpty(String str) { | |
| 32 | + return StringUtils.isEmpty(str); | |
| 33 | + } | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * 若字符串为空,则取默认值 | |
| 37 | + */ | |
| 38 | + public static String defaultIfEmpty(String str, String defaultValue) { | |
| 39 | + return StringUtils.defaultIfEmpty(str, defaultValue); | |
| 40 | + } | |
| 41 | + | |
| 42 | + /** | |
| 43 | + * 替换固定格式的字符串(支持正则表达式) | |
| 44 | + */ | |
| 45 | + public static String replaceAll(String str, String regex, String replacement) { | |
| 46 | + Pattern p = Pattern.compile(regex); | |
| 47 | + Matcher m = p.matcher(str); | |
| 48 | + StringBuffer sb = new StringBuffer(); | |
| 49 | + while (m.find()) { | |
| 50 | + m.appendReplacement(sb, replacement); | |
| 51 | + } | |
| 52 | + m.appendTail(sb); | |
| 53 | + return sb.toString(); | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * 是否为数字(整数或小数) | |
| 58 | + */ | |
| 59 | + public static boolean isNumber(String str) { | |
| 60 | + return NumberUtils.isNumber(str); | |
| 61 | + } | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * 是否为十进制数(整数) | |
| 65 | + */ | |
| 66 | + public static boolean isDigits(String str) { | |
| 67 | + return NumberUtils.isDigits(str); | |
| 68 | + } | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * 将驼峰风格替换为下划线风格 | |
| 72 | + */ | |
| 73 | + public static String camelhumpToUnderline(String str) { | |
| 74 | + Matcher matcher = Pattern.compile("[A-Z]").matcher(str); | |
| 75 | + StringBuilder builder = new StringBuilder(str); | |
| 76 | + for (int i = 0; matcher.find(); i++) { | |
| 77 | + builder.replace(matcher.start() + i, matcher.end() + i, "_" + matcher.group().toLowerCase()); | |
| 78 | + } | |
| 79 | + if (builder.charAt(0) == '_') { | |
| 80 | + builder.deleteCharAt(0); | |
| 81 | + } | |
| 82 | + return builder.toString(); | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * 将下划线风格替换为驼峰风格 | |
| 87 | + */ | |
| 88 | + public static String underlineToCamelhump(String str) { | |
| 89 | + Matcher matcher = Pattern.compile("_[a-z]").matcher(str); | |
| 90 | + StringBuilder builder = new StringBuilder(str); | |
| 91 | + for (int i = 0; matcher.find(); i++) { | |
| 92 | + builder.replace(matcher.start() - i, matcher.end() - i, matcher.group().substring(1).toUpperCase()); | |
| 93 | + } | |
| 94 | + if (Character.isUpperCase(builder.charAt(0))) { | |
| 95 | + builder.replace(0, 1, String.valueOf(Character.toLowerCase(builder.charAt(0)))); | |
| 96 | + } | |
| 97 | + return builder.toString(); | |
| 98 | + } | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * 分割固定格式的字符串 | |
| 102 | + */ | |
| 103 | + public static String[] splitString(String str, String separator) { | |
| 104 | + return StringUtils.splitByWholeSeparator(str, separator); | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * 将字符串首字母大写 | |
| 109 | + */ | |
| 110 | + public static String firstToUpper(String str) { | |
| 111 | + return Character.toUpperCase(str.charAt(0)) + str.substring(1); | |
| 112 | + } | |
| 113 | + | |
| 114 | + /** | |
| 115 | + * 将字符串首字母小写 | |
| 116 | + */ | |
| 117 | + public static String firstToLower(String str) { | |
| 118 | + return Character.toLowerCase(str.charAt(0)) + str.substring(1); | |
| 119 | + } | |
| 120 | + | |
| 121 | + /** | |
| 122 | + * 转为帕斯卡命名方式(如:FooBar) | |
| 123 | + */ | |
| 124 | + public static String toPascalStyle(String str, String seperator) { | |
| 125 | + return StringUtil.firstToUpper(toCamelhumpStyle(str, seperator)); | |
| 126 | + } | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * 转为驼峰命令方式(如:fooBar) | |
| 130 | + */ | |
| 131 | + public static String toCamelhumpStyle(String str, String seperator) { | |
| 132 | + return StringUtil.underlineToCamelhump(toUnderlineStyle(str, seperator)); | |
| 133 | + } | |
| 134 | + | |
| 135 | + /** | |
| 136 | + * 转为下划线命名方式(如:foo_bar) | |
| 137 | + */ | |
| 138 | + public static String toUnderlineStyle(String str, String seperator) { | |
| 139 | + str = str.trim().toLowerCase(); | |
| 140 | + if (str.contains(seperator)) { | |
| 141 | + str = str.replace(seperator, "_"); | |
| 142 | + } | |
| 143 | + return str; | |
| 144 | + } | |
| 145 | + | |
| 146 | + /** | |
| 147 | + * 转为显示命名方式(如:Foo Bar) | |
| 148 | + */ | |
| 149 | + public static String toDisplayStyle(String str, String seperator) { | |
| 150 | + String displayName = ""; | |
| 151 | + str = str.trim().toLowerCase(); | |
| 152 | + if (str.contains(seperator)) { | |
| 153 | + String[] words = StringUtil.splitString(str, seperator); | |
| 154 | + for (String word : words) { | |
| 155 | + displayName += StringUtil.firstToUpper(word) + " "; | |
| 156 | + } | |
| 157 | + displayName = displayName.trim(); | |
| 158 | + } else { | |
| 159 | + displayName = StringUtil.firstToUpper(str); | |
| 160 | + } | |
| 161 | + return displayName; | |
| 162 | + } | |
| 163 | +} | ... | ... |
src/main/java/org/smart4j/framework/util/WebUtil.java
0 → 100644
| 1 | +++ a/src/main/java/org/smart4j/framework/util/WebUtil.java | |
| 1 | +package org.smart4j.framework.util; | |
| 2 | + | |
| 3 | +import java.awt.Color; | |
| 4 | +import java.awt.Font; | |
| 5 | +import java.awt.Graphics2D; | |
| 6 | +import java.awt.image.BufferedImage; | |
| 7 | +import java.io.BufferedInputStream; | |
| 8 | +import java.io.BufferedOutputStream; | |
| 9 | +import java.io.FileInputStream; | |
| 10 | +import java.io.InputStream; | |
| 11 | +import java.io.OutputStream; | |
| 12 | +import java.io.PrintWriter; | |
| 13 | +import java.util.Enumeration; | |
| 14 | +import java.util.LinkedHashMap; | |
| 15 | +import java.util.Map; | |
| 16 | +import java.util.Random; | |
| 17 | + | |
| 18 | +import javax.imageio.ImageIO; | |
| 19 | +import javax.servlet.ServletOutputStream; | |
| 20 | +import javax.servlet.http.Cookie; | |
| 21 | +import javax.servlet.http.HttpServletRequest; | |
| 22 | +import javax.servlet.http.HttpServletResponse; | |
| 23 | + | |
| 24 | +import org.apache.commons.io.FilenameUtils; | |
| 25 | +import org.slf4j.Logger; | |
| 26 | +import org.slf4j.LoggerFactory; | |
| 27 | +import org.smart4j.framework.FrameworkConstant; | |
| 28 | +import org.smart4j.framework.mvc.bean.Redirect; | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * Web 操作工具类 | |
| 32 | + * | |
| 33 | + * @author huangyong | |
| 34 | + * @since 1.0 | |
| 35 | + */ | |
| 36 | +public class WebUtil { | |
| 37 | + | |
| 38 | + private static final Logger logger = LoggerFactory.getLogger(WebUtil.class); | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 将数据以 JSON 格式写入响应中 | |
| 42 | + */ | |
| 43 | + public static void writeJSON(HttpServletResponse response, Object data) { | |
| 44 | + try { | |
| 45 | + // 设置响应头 | |
| 46 | + response.setContentType("application/json"); // 指定内容类型为 JSON 格式 | |
| 47 | + response.setCharacterEncoding(FrameworkConstant.UTF_8); // 防止中文乱码 | |
| 48 | + // 向响应中写入数据 | |
| 49 | + PrintWriter writer = response.getWriter(); | |
| 50 | + writer.write(JsonUtil.toJSON(data)); // 转为 JSON 字符串 | |
| 51 | + writer.flush(); | |
| 52 | + writer.close(); | |
| 53 | + } catch (Exception e) { | |
| 54 | + logger.error("在响应中写数据出错!", e); | |
| 55 | + throw new RuntimeException(e); | |
| 56 | + } | |
| 57 | + } | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * 将数据以 HTML 格式写入响应中(在 JS 中获取的是 JSON 字符串,而不是 JSON 对象) | |
| 61 | + */ | |
| 62 | + public static void writeHTML(HttpServletResponse response, Object data) { | |
| 63 | + try { | |
| 64 | + // 设置响应头 | |
| 65 | + response.setContentType("text/html"); // 指定内容类型为 HTML 格式 | |
| 66 | + response.setCharacterEncoding(FrameworkConstant.UTF_8); // 防止中文乱码 | |
| 67 | + // 向响应中写入数据 | |
| 68 | + PrintWriter writer = response.getWriter(); | |
| 69 | + writer.write(JsonUtil.toJSON(data)); // 转为 JSON 字符串 | |
| 70 | + writer.flush(); | |
| 71 | + writer.close(); | |
| 72 | + } catch (Exception e) { | |
| 73 | + logger.error("在响应中写数据出错!", e); | |
| 74 | + throw new RuntimeException(e); | |
| 75 | + } | |
| 76 | + } | |
| 77 | + | |
| 78 | + public static void redirect(HttpServletResponse response, Redirect api) { | |
| 79 | + try { | |
| 80 | + String redirectUrl=api.getRedirectUrl(); | |
| 81 | + response.setContentType("application/mpegurl"); | |
| 82 | + response.setStatus(301); | |
| 83 | + response.setHeader("Location", redirectUrl); | |
| 84 | + response.setHeader("message", api.getMessage()); | |
| 85 | + response.setHeader("Connection", "close"); | |
| 86 | + } catch (Exception e) { | |
| 87 | + logger.error("在响应中写数据出错!", e); | |
| 88 | + throw new RuntimeException(e); | |
| 89 | + } | |
| 90 | + } | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * 从请求中获取所有参数(当参数名重复时,用后者覆盖前者) | |
| 94 | + */ | |
| 95 | + public static Map<String, Object> getRequestParamMap(HttpServletRequest request) { | |
| 96 | + Map<String, Object> paramMap = new LinkedHashMap<String, Object>(); | |
| 97 | + try { | |
| 98 | + String method = request.getMethod(); | |
| 99 | + if (method.equalsIgnoreCase("put") || method.equalsIgnoreCase("delete")) { | |
| 100 | + String queryString = CodecUtil.decodeURL(StreamUtil.getString(request.getInputStream())); | |
| 101 | + if (StringUtil.isNotEmpty(queryString)) { | |
| 102 | + String[] qsArray = StringUtil.splitString(queryString, "&"); | |
| 103 | + if (ArrayUtil.isNotEmpty(qsArray)) { | |
| 104 | + for (String qs : qsArray) { | |
| 105 | + String[] array = StringUtil.splitString(qs, "="); | |
| 106 | + if (ArrayUtil.isNotEmpty(array) && array.length == 2) { | |
| 107 | + String paramName = array[0]; | |
| 108 | + String paramValue = array[1]; | |
| 109 | + if (checkParamName(paramName)) { | |
| 110 | + if (paramMap.containsKey(paramName)) { | |
| 111 | + paramValue = paramMap.get(paramName) + StringUtil.SEPARATOR + paramValue; | |
| 112 | + } | |
| 113 | + paramMap.put(paramName, paramValue); | |
| 114 | + } | |
| 115 | + } | |
| 116 | + } | |
| 117 | + } | |
| 118 | + } | |
| 119 | + } else { | |
| 120 | + Enumeration<String> paramNames = request.getParameterNames(); | |
| 121 | + while (paramNames.hasMoreElements()) { | |
| 122 | + String paramName = paramNames.nextElement(); | |
| 123 | + if (checkParamName(paramName)) { | |
| 124 | + String[] paramValues = request.getParameterValues(paramName); | |
| 125 | + if (ArrayUtil.isNotEmpty(paramValues)) { | |
| 126 | + if (paramValues.length == 1) { | |
| 127 | + paramMap.put(paramName, paramValues[0]); | |
| 128 | + } else { | |
| 129 | + StringBuilder paramValue = new StringBuilder(""); | |
| 130 | + for (int i = 0; i < paramValues.length; i++) { | |
| 131 | + paramValue.append(paramValues[i]); | |
| 132 | + if (i != paramValues.length - 1) { | |
| 133 | + paramValue.append(StringUtil.SEPARATOR); | |
| 134 | + } | |
| 135 | + } | |
| 136 | + paramMap.put(paramName, paramValue.toString()); | |
| 137 | + } | |
| 138 | + } | |
| 139 | + } | |
| 140 | + } | |
| 141 | + } | |
| 142 | + } catch (Exception e) { | |
| 143 | + logger.error("获取请求参数出错!", e); | |
| 144 | + throw new RuntimeException(e); | |
| 145 | + } | |
| 146 | + return paramMap; | |
| 147 | + } | |
| 148 | + | |
| 149 | + /** | |
| 150 | + * 跳过参数 | |
| 151 | + * @param paramName | |
| 152 | + * @return | |
| 153 | + */ | |
| 154 | + private static boolean checkParamName(String paramName) { | |
| 155 | + // return !paramName.equals("_"); // 忽略 jQuery 缓存参数 | |
| 156 | + boolean flag=true; | |
| 157 | + if (paramName.equals("_")) { | |
| 158 | + flag=false; | |
| 159 | + }if (paramName.equalsIgnoreCase("ticket")) { | |
| 160 | + flag=false; | |
| 161 | + } | |
| 162 | + return flag; | |
| 163 | + | |
| 164 | + | |
| 165 | + } | |
| 166 | + | |
| 167 | + /** | |
| 168 | + * 转发请求 | |
| 169 | + */ | |
| 170 | + public static void forwardRequest(String path, HttpServletRequest request, HttpServletResponse response) { | |
| 171 | + try { | |
| 172 | + request.getRequestDispatcher(path).forward(request, response); | |
| 173 | + } catch (Exception e) { | |
| 174 | + logger.error("转发请求出错!", e); | |
| 175 | + throw new RuntimeException(e); | |
| 176 | + } | |
| 177 | + } | |
| 178 | + | |
| 179 | + /** | |
| 180 | + * 重定向请求 | |
| 181 | + */ | |
| 182 | + public static void redirectRequest(String path, HttpServletRequest request, HttpServletResponse response) { | |
| 183 | + try { | |
| 184 | + response.sendRedirect(request.getContextPath() + path); | |
| 185 | + } catch (Exception e) { | |
| 186 | + logger.error("重定向请求出错!", e); | |
| 187 | + throw new RuntimeException(e); | |
| 188 | + } | |
| 189 | + } | |
| 190 | + | |
| 191 | + /** | |
| 192 | + * 发送错误代码 | |
| 193 | + */ | |
| 194 | + public static void sendError(int code, String message, HttpServletResponse response) { | |
| 195 | + try { | |
| 196 | + response.sendError(code, message); | |
| 197 | + } catch (Exception e) { | |
| 198 | + logger.error("发送错误代码出错!", e); | |
| 199 | + throw new RuntimeException(e); | |
| 200 | + } | |
| 201 | + } | |
| 202 | + | |
| 203 | + /** | |
| 204 | + * 判断是否为 AJAX 请求 | |
| 205 | + */ | |
| 206 | + public static boolean isAJAX(HttpServletRequest request) { | |
| 207 | + return request.getHeader("X-Requested-With") != null; | |
| 208 | + } | |
| 209 | + | |
| 210 | + /** | |
| 211 | + * 获取请求路径 | |
| 212 | + */ | |
| 213 | + public static String getRequestPath(HttpServletRequest request) { | |
| 214 | + String servletPath = request.getServletPath(); | |
| 215 | + String pathInfo = StringUtil.defaultIfEmpty(request.getPathInfo(), ""); | |
| 216 | + return servletPath + pathInfo; | |
| 217 | + } | |
| 218 | + | |
| 219 | + /** | |
| 220 | + * 从 Cookie 中获取数据 | |
| 221 | + */ | |
| 222 | + public static String getCookie(HttpServletRequest request, String name) { | |
| 223 | + String value = ""; | |
| 224 | + try { | |
| 225 | + Cookie[] cookieArray = request.getCookies(); | |
| 226 | + if (cookieArray != null) { | |
| 227 | + for (Cookie cookie : cookieArray) { | |
| 228 | + if (StringUtil.isNotEmpty(name) && name.equals(cookie.getName())) { | |
| 229 | + value = CodecUtil.decodeURL(cookie.getValue()); | |
| 230 | + break; | |
| 231 | + } | |
| 232 | + } | |
| 233 | + } | |
| 234 | + } catch (Exception e) { | |
| 235 | + logger.error("获取 Cookie 出错!", e); | |
| 236 | + throw new RuntimeException(e); | |
| 237 | + } | |
| 238 | + return value; | |
| 239 | + } | |
| 240 | + | |
| 241 | + /** | |
| 242 | + * 下载文件 | |
| 243 | + */ | |
| 244 | + public static void downloadFile(HttpServletResponse response, String filePath) { | |
| 245 | + try { | |
| 246 | + String originalFileName = FilenameUtils.getName(filePath); | |
| 247 | + String downloadedFileName = new String(originalFileName.getBytes("GBK"), "ISO8859_1"); // 防止中文乱码 | |
| 248 | + | |
| 249 | + response.setContentType("application/octet-stream"); | |
| 250 | + response.addHeader("Content-Disposition", "attachment;filename=\"" + downloadedFileName + "\""); | |
| 251 | + | |
| 252 | + InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath)); | |
| 253 | + OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); | |
| 254 | + StreamUtil.copyStream(inputStream, outputStream); | |
| 255 | + } catch (Exception e) { | |
| 256 | + logger.error("下载文件出错!", e); | |
| 257 | + throw new RuntimeException(e); | |
| 258 | + } | |
| 259 | + } | |
| 260 | + | |
| 261 | + /** | |
| 262 | + * 设置 Redirect URL 到 Session 中 | |
| 263 | + */ | |
| 264 | + public static void setRedirectUrl(HttpServletRequest request, String sessionKey) { | |
| 265 | + if (!isAJAX(request)) { | |
| 266 | + String requestPath = getRequestPath(request); | |
| 267 | + request.getSession().setAttribute(sessionKey, requestPath); | |
| 268 | + } | |
| 269 | + } | |
| 270 | + | |
| 271 | + /** | |
| 272 | + * 创建验证码 | |
| 273 | + */ | |
| 274 | + public static String createCaptcha(HttpServletResponse response) { | |
| 275 | + StringBuilder captcha = new StringBuilder(); | |
| 276 | + try { | |
| 277 | + // 参数初始化 | |
| 278 | + int width = 60; // 验证码图片的宽度 | |
| 279 | + int height = 25; // 验证码图片的高度 | |
| 280 | + int codeCount = 4; // 验证码字符个数 | |
| 281 | + int codeX = width / (codeCount + 1); // 字符横向间距 | |
| 282 | + int codeY = height - 4; // 字符纵向间距 | |
| 283 | + int fontHeight = height - 2; // 字体高度 | |
| 284 | + int randomSeed = 10; // 随机数种子 | |
| 285 | + char[] codeSequence = { // 验证码中可出现的字符 | |
| 286 | + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' | |
| 287 | + }; | |
| 288 | + // 创建图像 | |
| 289 | + BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); | |
| 290 | + Graphics2D g = bi.createGraphics(); | |
| 291 | + // 将图像填充为白色 | |
| 292 | + g.setColor(Color.WHITE); | |
| 293 | + g.fillRect(0, 0, width, height); | |
| 294 | + // 设置字体 | |
| 295 | + g.setFont(new Font("Courier New", Font.BOLD, fontHeight)); | |
| 296 | + // 绘制边框 | |
| 297 | + g.setColor(Color.BLACK); | |
| 298 | + g.drawRect(0, 0, width - 1, height - 1); | |
| 299 | + // 产生随机干扰线(160条) | |
| 300 | + g.setColor(Color.WHITE); | |
| 301 | + // 创建随机数生成器 | |
| 302 | + Random random = new Random(); | |
| 303 | + for (int i = 0; i < 160; i++) { | |
| 304 | + int x = random.nextInt(width); | |
| 305 | + int y = random.nextInt(height); | |
| 306 | + int xl = random.nextInt(12); | |
| 307 | + int yl = random.nextInt(12); | |
| 308 | + g.drawLine(x, y, x + xl, y + yl); | |
| 309 | + } | |
| 310 | + // 生成随机验证码 | |
| 311 | + int red, green, blue; | |
| 312 | + for (int i = 0; i < codeCount; i++) { | |
| 313 | + // 获取随机验证码 | |
| 314 | + String validateCode = String.valueOf(codeSequence[random.nextInt(randomSeed)]); | |
| 315 | + // 随机构造颜色值 | |
| 316 | + red = random.nextInt(255); | |
| 317 | + green = random.nextInt(255); | |
| 318 | + blue = random.nextInt(255); | |
| 319 | + // 将带有颜色的验证码绘制到图像中 | |
| 320 | + g.setColor(new Color(red, green, blue)); | |
| 321 | + g.drawString(validateCode, (i + 1) * codeX - 6, codeY); | |
| 322 | + // 将产生的随机数拼接起来 | |
| 323 | + captcha.append(validateCode); | |
| 324 | + } | |
| 325 | + // 禁止图像缓存 | |
| 326 | + response.setHeader("Cache-Control", "no-store"); | |
| 327 | + response.setHeader("Pragma", "no-cache"); | |
| 328 | + response.setDateHeader("Expires", 0); | |
| 329 | + // 设置响应类型为 JPEG 图片 | |
| 330 | + response.setContentType("image/jpeg"); | |
| 331 | + // 将缓冲图像写到 Servlet 输出流中 | |
| 332 | + ServletOutputStream sos = response.getOutputStream(); | |
| 333 | + ImageIO.write(bi, "jpeg", sos); | |
| 334 | + sos.close(); | |
| 335 | + } catch (Exception e) { | |
| 336 | + logger.error("创建验证码出错!", e); | |
| 337 | + throw new RuntimeException(e); | |
| 338 | + } | |
| 339 | + return captcha.toString(); | |
| 340 | + } | |
| 341 | + | |
| 342 | + /** | |
| 343 | + * 是否为 IE 浏览器 | |
| 344 | + */ | |
| 345 | + public boolean isIE(HttpServletRequest request) { | |
| 346 | + String agent = request.getHeader("User-Agent"); | |
| 347 | + return agent != null && agent.contains("MSIE"); | |
| 348 | + } | |
| 349 | +} | ... | ... |