hermit пре 7 година
родитељ
комит
a946e04876
100 измењених фајлова са 7881 додато и 3391 уклоњено
  1. 1 0
      .gitignore
  2. 674 0
      LICENSE
  3. 4 5
      README.md
  4. 172 118
      doc/wxmp.sql
  5. 27 6
      doc/目录结构.txt
  6. 4177 0
      package-lock.json
  7. 26 0
      package.json
  8. 28 9
      pom.xml
  9. 0 24
      src/main/java/com/wxmp/backstage/common/ATTContents.java
  10. 0 133
      src/main/java/com/wxmp/backstage/common/Configuration.java
  11. 0 40
      src/main/java/com/wxmp/backstage/common/DataModel.java
  12. 0 40
      src/main/java/com/wxmp/backstage/common/I18n.java
  13. 0 78
      src/main/java/com/wxmp/backstage/common/Identities.java
  14. 0 75
      src/main/java/com/wxmp/backstage/common/TableModel.java
  15. 0 45
      src/main/java/com/wxmp/backstage/common/XMLDocException.java
  16. 0 87
      src/main/java/com/wxmp/backstage/exception/BusinessException.java
  17. 0 90
      src/main/java/com/wxmp/backstage/exception/UnexpectedException.java
  18. 0 129
      src/main/java/com/wxmp/backstage/ueditor/ActionEnter.java
  19. 0 223
      src/main/java/com/wxmp/backstage/ueditor/ConfigManager.java
  20. 0 24
      src/main/java/com/wxmp/backstage/ueditor/Encoder.java
  21. 0 157
      src/main/java/com/wxmp/backstage/ueditor/PathFormat.java
  22. 0 42
      src/main/java/com/wxmp/backstage/ueditor/define/ActionMap.java
  23. 0 5
      src/main/java/com/wxmp/backstage/ueditor/define/ActionState.java
  24. 0 77
      src/main/java/com/wxmp/backstage/ueditor/define/AppInfo.java
  25. 0 90
      src/main/java/com/wxmp/backstage/ueditor/define/BaseState.java
  26. 0 31
      src/main/java/com/wxmp/backstage/ueditor/define/FileType.java
  27. 0 20
      src/main/java/com/wxmp/backstage/ueditor/define/MIMEType.java
  28. 0 112
      src/main/java/com/wxmp/backstage/ueditor/define/MultiState.java
  29. 0 18
      src/main/java/com/wxmp/backstage/ueditor/define/State.java
  30. 0 112
      src/main/java/com/wxmp/backstage/ueditor/hunter/FileManager.java
  31. 0 144
      src/main/java/com/wxmp/backstage/ueditor/hunter/ImageHunter.java
  32. 0 32
      src/main/java/com/wxmp/backstage/ueditor/test/Test.java
  33. 0 54
      src/main/java/com/wxmp/backstage/ueditor/test/Test2.java
  34. 0 52
      src/main/java/com/wxmp/backstage/ueditor/upload/Base64Uploader.java
  35. 0 98
      src/main/java/com/wxmp/backstage/ueditor/upload/BinaryUploader.java
  36. 0 155
      src/main/java/com/wxmp/backstage/ueditor/upload/StorageManager.java
  37. 0 29
      src/main/java/com/wxmp/backstage/ueditor/upload/Uploader.java
  38. 29 0
      src/main/java/com/wxmp/core/common/AppDefineInitService.java
  39. 74 0
      src/main/java/com/wxmp/core/common/BaseCtrl.java
  40. 133 0
      src/main/java/com/wxmp/core/common/Configuration.java
  41. 104 0
      src/main/java/com/wxmp/core/common/Constants.java
  42. 40 0
      src/main/java/com/wxmp/core/common/DataModel.java
  43. 40 0
      src/main/java/com/wxmp/core/common/I18n.java
  44. 95 0
      src/main/java/com/wxmp/core/common/IBase.java
  45. 77 0
      src/main/java/com/wxmp/core/common/Identities.java
  46. 75 0
      src/main/java/com/wxmp/core/common/TableModel.java
  47. 45 0
      src/main/java/com/wxmp/core/common/XMLDocException.java
  48. 0 25
      src/main/java/com/wxmp/core/domain/BaseEntity.java
  49. 93 0
      src/main/java/com/wxmp/core/exception/BusinessException.java
  50. 96 0
      src/main/java/com/wxmp/core/exception/UnexpectedException.java
  51. 0 59
      src/main/java/com/wxmp/core/interceptor/DisableUrlSessionFilter.java
  52. 53 0
      src/main/java/com/wxmp/core/listener/InitListener.java
  53. 0 103
      src/main/java/com/wxmp/core/page/AbstractPage.java
  54. 25 50
      src/main/java/com/wxmp/core/page/Page.java
  55. 354 0
      src/main/java/com/wxmp/core/page/PageInterceptor.java
  56. 31 0
      src/main/java/com/wxmp/core/page/PageResult.java
  57. 111 0
      src/main/java/com/wxmp/core/page/PageUtil.java
  58. 0 47
      src/main/java/com/wxmp/core/page/Pagination.java
  59. 50 0
      src/main/java/com/wxmp/core/spring/ExceptionHolder.java
  60. 90 0
      src/main/java/com/wxmp/core/spring/SpringContextHolder.java
  61. 225 0
      src/main/java/com/wxmp/core/util/AjaxResult.java
  62. 13 42
      src/main/java/com/wxmp/core/util/CacheUtils.java
  63. 1 1
      src/main/java/com/wxmp/core/util/ConvertUtil.java
  64. 21 21
      src/main/java/com/wxmp/core/util/DateUtil.java
  65. 37 52
      src/main/java/com/wxmp/core/util/FileUtil.java
  66. 1 1
      src/main/java/com/wxmp/core/util/HashUtil.java
  67. 39 0
      src/main/java/com/wxmp/core/util/J2CacheUtil.java
  68. 0 65
      src/main/java/com/wxmp/core/util/SessionUser.java
  69. 0 101
      src/main/java/com/wxmp/core/util/SpringContextHolder.java
  70. 3 2
      src/main/java/com/wxmp/core/util/StringUtil.java
  71. 1 1
      src/main/java/com/wxmp/core/util/WebUtil.java
  72. 1 1
      src/main/java/com/wxmp/core/util/XmlUtil.java
  73. 84 0
      src/main/java/com/wxmp/core/util/qiniu/QiniuResult.java
  74. 121 0
      src/main/java/com/wxmp/core/util/qiniu/QiniuUtil.java
  75. 1 1
      src/main/java/com/wxmp/core/util/security/RSAKeys.java
  76. 1 1
      src/main/java/com/wxmp/core/util/security/RSASignatureTools.java
  77. 154 0
      src/main/java/com/wxmp/core/util/wx/WxUtil.java
  78. 119 165
      src/main/java/com/wxmp/wxapi/ctrl/WxApiCtrl.java
  79. 6 0
      src/main/java/com/wxmp/wxapi/interceptor/OAuth2RequestParamHelper.java
  80. 8 2
      src/main/java/com/wxmp/wxapi/interceptor/WxOAuth2Interceptor.java
  81. 6 0
      src/main/java/com/wxmp/wxapi/process/AccessToken.java
  82. 6 0
      src/main/java/com/wxmp/wxapi/process/ErrCode.java
  83. 6 0
      src/main/java/com/wxmp/wxapi/process/HttpMethod.java
  84. 6 0
      src/main/java/com/wxmp/wxapi/process/JSTicket.java
  85. 6 0
      src/main/java/com/wxmp/wxapi/process/MediaType.java
  86. 11 37
      src/main/java/com/wxmp/wxapi/process/MpAccount.java
  87. 6 0
      src/main/java/com/wxmp/wxapi/process/MsgType.java
  88. 6 0
      src/main/java/com/wxmp/wxapi/process/MsgXmlUtil.java
  89. 6 0
      src/main/java/com/wxmp/wxapi/process/OAuthAccessToken.java
  90. 6 0
      src/main/java/com/wxmp/wxapi/process/OAuthScope.java
  91. 7 1
      src/main/java/com/wxmp/wxapi/process/WxApi.java
  92. 59 28
      src/main/java/com/wxmp/wxapi/process/WxApiClient.java
  93. 114 90
      src/main/java/com/wxmp/wxapi/process/WxMemoryCacheClient.java
  94. 29 11
      src/main/java/com/wxmp/wxapi/process/WxMessageBuilder.java
  95. 7 1
      src/main/java/com/wxmp/wxapi/process/WxSign.java
  96. 7 1
      src/main/java/com/wxmp/wxapi/service/MyService.java
  97. 26 93
      src/main/java/com/wxmp/wxapi/service/impl/MyServiceImpl.java
  98. 4 27
      src/main/java/com/wxmp/wxapi/vo/Article.java
  99. 3 8
      src/main/java/com/wxmp/wxapi/vo/Image.java
  100. 0 0
      src/main/java/com/wxmp/wxapi/vo/Matchrule.java

+ 1 - 0
.gitignore

@@ -8,5 +8,6 @@
 ##############################
 target
 .idea
+node_modules
 *.iml
 jdbc.properties

+ 674 - 0
LICENSE

@@ -0,0 +1,674 @@
+GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/]
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    {one line to give the program's name and a brief idea of what it does.}
+    Copyright (C) {year}  {fullname}
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see [http://www.gnu.org/licenses/].
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    Test  Copyright (C) 2018  hermit
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+[http://www.gnu.org/licenses/].
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+[http://www.gnu.org/philosophy/why-not-lgpl.html].

+ 4 - 5
README.md

@@ -1,5 +1,5 @@
 ## 本项目是一个完整的微信公众号web操作版,直接编译即可运行。让用户不再用关心微信的底层接口,直接使用页面进行操作,简单方便。
-### 包括多公众号管理、文本管理、图文管理、菜单管理、粉丝管理、群发消息、运行数据
+### 包括服务器绑定、文本管理、图文管理、菜单管理、粉丝管理、群发消息等
 ---------------------------------
 [![QQ](https://img.shields.io/badge/chat-on%20QQ-ff69b4.svg?style=flat-square)](https://jq.qq.com/?_wv=1027&k=5bGtRX8)
 [![Apache-2.0](https://img.shields.io/hexpm/l/plug.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
@@ -8,13 +8,12 @@
 ---------------------------------
 ### 重要信息
 
-## 2018-04-16:项目2.0版本已基本完善,演示地址如下:**[【http://smartwx.webcsn.com】](http://smartwx.webcsn.com)**!大家多提宝贵意见,完善之后,再发版。此次更新内容如下:
+1. **为保证以后项目扩展,项目正式更名为SmartWx**
 
-1. **多公众号支持,缓存支持ehcache+redis二级缓存**
+1. **项目2.0版本已发版,演示地址如下:[【http://smartwx.webcsn.com】](http://smartwx.webcsn.com)**
 
-1. **全新的页面,逻辑更加清晰的后台代码。本次采用前后台分离,页面基本采用layui框架,后台采用springmvc等主流框架** 
+1. **本次2.0版本,个人学习免费。商业请先授权,具体请参考项目中的授权协议。另,1.0版本完全免费,欢迎大牛 拉取分支**
 
-1. **丰富微信api接口,优化pom文件依赖引入** 
 
 --------------------------------
 ### 其他说明

+ 172 - 118
doc/wxmp.sql

@@ -1,10 +1,10 @@
+
 /*
-SQLyog Ultimate v11.24 (32 bit)
-MySQL - 5.7.18 : Database - wxmp
+SQLyog Ultimate v12.3.2 (64 bit)
+MySQL - 5.7.18 : Database - wxmp2
 *********************************************************************
 */
 
-
 /*!40101 SET NAMES utf8 */;
 
 /*!40101 SET SQL_MODE=''*/;
@@ -17,11 +17,52 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/`wxmp` /*!40100 DEFAULT CHARACTER SET ut
 
 USE `wxmp`;
 
-/*Table structure for table `t_wxcms_account` */
+/*Table structure for table `sys_config` */
+
+DROP TABLE IF EXISTS `sys_config`;
+
+CREATE TABLE `sys_config` (
+  `jkey` varchar(100) NOT NULL DEFAULT '',
+  `jvalue` varchar(500) DEFAULT '',
+  `description` varchar(255) DEFAULT '',
+  PRIMARY KEY (`jkey`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+/*Data for the table `sys_config` */
+
+insert  into `sys_config`(`jkey`,`jvalue`,`description`) values
+('system_update_time','2018-04-19','系统当前版本发布时间'),
+('system_version','2.0.0','系统当前版本');
+
+/*Table structure for table `sys_user` */
+
+DROP TABLE IF EXISTS `sys_user`;
+
+CREATE TABLE `sys_user` (
+  `id` varchar(64) NOT NULL DEFAULT '' COMMENT '主键id',
+  `account` varchar(50) DEFAULT NULL COMMENT '账号',
+  `pwd` varchar(50) DEFAULT NULL COMMENT '登录密码',
+  `true_name` varchar(50) DEFAULT NULL COMMENT '姓名',
+  `sex` varchar(1) DEFAULT '0' COMMENT '性别:0是男 1是女',
+  `phone` varchar(11) DEFAULT '' COMMENT '手机号码',
+  `email` varchar(50) DEFAULT '' COMMENT '邮箱',
+  `avatar` varchar(255) DEFAULT NULL COMMENT '头像',
+  `flag` int(1) DEFAULT NULL COMMENT '状态',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+/*Data for the table `sys_user` */
+
+insert  into `sys_user`(`id`,`account`,`pwd`,`true_name`,`sex`,`phone`,`email`,`avatar`,`flag`,`create_time`,`update_time`) values
+('1','smartwx','fe5c291e5b5a8d8843ee455d163e1447','smartwx','0','','',NULL,NULL,NULL,NULL);
+
+/*Table structure for table `wxcms_account` */
 
-DROP TABLE IF EXISTS `t_wxcms_account`;
+DROP TABLE IF EXISTS `wxcms_account`;
 
-CREATE TABLE `t_wxcms_account` (
+CREATE TABLE `wxcms_account` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `name` varchar(100) DEFAULT NULL,
   `account` varchar(100) NOT NULL,
@@ -29,223 +70,236 @@ CREATE TABLE `t_wxcms_account` (
   `appsecret` varchar(100) DEFAULT NULL,
   `url` varchar(255) NOT NULL,
   `token` varchar(255) NOT NULL,
-  `msgCount` int(11) DEFAULT '1',
-  `createTime` datetime DEFAULT NULL,
+  `msg_count` int(11) DEFAULT '1',
+  `create_time` datetime DEFAULT NULL,
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_account` */
+/*Data for the table `wxcms_account` */
 
-/*Table structure for table `t_wxcms_account_fans` */
+/*Table structure for table `wxcms_account_fans` */
 
-DROP TABLE IF EXISTS `t_wxcms_account_fans`;
+DROP TABLE IF EXISTS `wxcms_account_fans`;
 
-CREATE TABLE `t_wxcms_account_fans` (
+CREATE TABLE `wxcms_account_fans` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
-  `openid` varchar(100) DEFAULT NULL,
-  `subscribeStatus` int(1) DEFAULT '1',
-  `subscribeTime` varchar(50) DEFAULT NULL,
-  `nickname` varbinary(50) DEFAULT NULL,
+  `open_id` varchar(100) DEFAULT NULL,
+  `subscribe_status` int(1) DEFAULT '1',
+  `subscribe_time` varchar(50) DEFAULT NULL,
+  `nick_name` varbinary(50) DEFAULT NULL,
   `gender` tinyint(4) DEFAULT '1',
   `language` varchar(50) DEFAULT NULL,
   `country` varchar(30) DEFAULT NULL,
   `province` varchar(30) DEFAULT NULL,
   `city` varchar(30) DEFAULT NULL,
-  `headimgurl` varchar(255) DEFAULT NULL,
-  `createTime` datetime DEFAULT NULL,
+  `head_img_url` varchar(255) DEFAULT NULL,
   `status` tinyint(4) DEFAULT '1',
   `remark` varchar(50) DEFAULT NULL,
-  `wxid` varchar(50) DEFAULT NULL,
+  `wx_id` varchar(50) DEFAULT NULL,
+  `account` varchar(100) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=252 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=274 DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_account_fans` */
+/*Data for the table `wxcms_account_fans` */
 
-/*Table structure for table `t_wxcms_account_menu` */
+/*Table structure for table `wxcms_account_menu` */
 
-DROP TABLE IF EXISTS `t_wxcms_account_menu`;
+DROP TABLE IF EXISTS `wxcms_account_menu`;
 
-CREATE TABLE `t_wxcms_account_menu` (
+CREATE TABLE `wxcms_account_menu` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `mtype` varchar(50) DEFAULT NULL,
-  `eventType` varchar(50) DEFAULT NULL,
+  `event_type` varchar(50) DEFAULT NULL,
   `name` varchar(100) DEFAULT NULL,
-  `inputCode` varchar(255) NOT NULL,
+  `input_code` varchar(255) DEFAULT NULL,
   `url` varchar(255) DEFAULT NULL,
   `sort` int(11) DEFAULT NULL,
-  `parentId` int(11) DEFAULT NULL,
-  `msgId` varchar(100) DEFAULT NULL,
-  `createTime` datetime DEFAULT NULL,
+  `parent_id` int(11) DEFAULT NULL,
+  `msg_type` varchar(64) DEFAULT NULL,
+  `msg_id` varchar(100) DEFAULT NULL,
   `gid` int(11) DEFAULT NULL,
+  `account` varchar(100) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=163 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=81 DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_account_menu` */
+/*Data for the table `wxcms_account_menu` */
 
-/*Table structure for table `t_wxcms_account_menu_group` */
+/*Table structure for table `wxcms_account_menu_group` */
 
-DROP TABLE IF EXISTS `t_wxcms_account_menu_group`;
+DROP TABLE IF EXISTS `wxcms_account_menu_group`;
 
-CREATE TABLE `t_wxcms_account_menu_group` (
+CREATE TABLE `wxcms_account_menu_group` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `name` varchar(100) DEFAULT NULL,
   `enable` int(11) DEFAULT NULL,
-  `createtime` datetime DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL,
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_account_menu_group` */
+/*Data for the table `wxcms_account_menu_group` */
 
-/*Table structure for table `t_wxcms_article` */
+/*Table structure for table `wxcms_article` */
 
-DROP TABLE IF EXISTS `t_wxcms_article`;
+DROP TABLE IF EXISTS `wxcms_article`;
 
-CREATE TABLE `t_wxcms_article` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
+CREATE TABLE `wxcms_article` (
+  `ar_id` int(11) NOT NULL AUTO_INCREMENT,
   `title` varchar(30) DEFAULT NULL,
   `author` varchar(50) DEFAULT NULL,
   `content` varchar(200) DEFAULT NULL,
   `digest` varchar(100) DEFAULT NULL,
-  `show_cover_pic` int(1) DEFAULT NULL,
+  `show_cover_pic` int(1) DEFAULT '0',
   `url` varchar(200) DEFAULT NULL,
   `thumb_media_id` varchar(150) DEFAULT NULL,
   `content_source_url` varchar(200) DEFAULT NULL,
   `media_id` varchar(150) DEFAULT NULL,
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+  `news_id` int(11) DEFAULT NULL,
+  `news_index` int(11) DEFAULT NULL,
+  `pic_url` varchar(200) DEFAULT NULL,
+  PRIMARY KEY (`ar_id`),
+  KEY `news_id` (`news_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_article` */
+/*Data for the table `wxcms_article` */
 
-/*Table structure for table `t_wxcms_img_resource` */
+/*Table structure for table `wxcms_img_resource` */
 
-DROP TABLE IF EXISTS `t_wxcms_img_resource`;
+DROP TABLE IF EXISTS `wxcms_img_resource`;
 
-CREATE TABLE `t_wxcms_img_resource` (
+CREATE TABLE `wxcms_img_resource` (
   `id` varchar(32) NOT NULL,
-  `mediaId` varchar(100) DEFAULT NULL,
-  `trueName` varchar(100) NOT NULL,
+  `media_id` varchar(100) DEFAULT NULL,
+  `true_name` varchar(100) NOT NULL,
   `type` varchar(10) NOT NULL,
   `name` varchar(100) NOT NULL,
   `url` varchar(200) NOT NULL,
-  `httpUrl` varchar(200) DEFAULT NULL,
+  `http_url` varchar(200) DEFAULT NULL,
   `size` int(9) NOT NULL,
-  `createTime` datetime NOT NULL,
-  `updateTime` datetime NOT NULL,
+  `create_time` datetime NOT NULL,
+  `update_time` datetime NOT NULL,
   `flag` int(1) NOT NULL,
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_img_resource` */
+/*Data for the table `wxcms_img_resource` */
+
+/*Table structure for table `wxcms_login_info` */
+
+DROP TABLE IF EXISTS `wxcms_login_info`;
+
+CREATE TABLE `wxcms_login_info` (
+  `id` varchar(40) NOT NULL COMMENT '主键',
+  `user_id` varchar(40) DEFAULT NULL COMMENT '用户id',
+  `account` varchar(50) DEFAULT NULL COMMENT '用户名',
+  `phone` varchar(20) DEFAULT NULL COMMENT '用户手机号',
+  `login_count` int(11) DEFAULT '0' COMMENT '登录次数',
+  `curr_login_time` datetime DEFAULT NULL COMMENT '本次登录时间',
+  `curr_login_ip` varchar(15) DEFAULT NULL COMMENT '本次登录IP',
+  `last_login_time` datetime DEFAULT NULL COMMENT '上次登录时间',
+  `last_login_ip` varchar(15) DEFAULT NULL COMMENT '上次登录IP',
+  `login_out_time` datetime DEFAULT NULL COMMENT '退出时间',
+  `login_online` bigint(20) DEFAULT '20' COMMENT '在线时间',
+  `login_online_show` varchar(20) DEFAULT NULL COMMENT '在线时间:时分秒',
+  `session_id` varchar(100) DEFAULT NULL COMMENT 'session id',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='登录信息表';
+
+/*Data for the table `wxcms_login_info` */
 
-/*Table structure for table `t_wxcms_media_files` */
+/*Table structure for table `wxcms_media_files` */
 
-DROP TABLE IF EXISTS `t_wxcms_media_files`;
+DROP TABLE IF EXISTS `wxcms_media_files`;
 
-CREATE TABLE `t_wxcms_media_files` (
+CREATE TABLE `wxcms_media_files` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
-  `mediaType` varchar(20) DEFAULT NULL COMMENT '媒体类型',
+  `media_type` varchar(20) DEFAULT NULL COMMENT '媒体类型',
   `title` varchar(20) DEFAULT NULL COMMENT '标题',
   `introduction` varchar(500) DEFAULT NULL COMMENT '简介说明',
-  `logicClass` varchar(50) DEFAULT NULL COMMENT '标签_逻辑分类',
+  `logic_class` varchar(50) DEFAULT NULL COMMENT '标签_逻辑分类',
   `media_id` varchar(100) DEFAULT NULL COMMENT '返回的media_id',
-  `uploadUrl` varchar(200) DEFAULT NULL COMMENT '返回的wx服务器url',
+  `upload_url` varchar(200) DEFAULT NULL COMMENT '返回的wx服务器url',
   `rmk` varchar(500) DEFAULT NULL COMMENT '备注_预留',
-  `createTime` datetime DEFAULT NULL COMMENT '创建时间',
-  `updateTime` datetime DEFAULT NULL COMMENT '更新时间',
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=121 DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_media_files` */
+/*Data for the table `wxcms_media_files` */
 
-/*Table structure for table `t_wxcms_msg_base` */
+/*Table structure for table `wxcms_msg_base` */
 
-DROP TABLE IF EXISTS `t_wxcms_msg_base`;
+DROP TABLE IF EXISTS `wxcms_msg_base`;
 
-CREATE TABLE `t_wxcms_msg_base` (
+CREATE TABLE `wxcms_msg_base` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
-  `msgType` varchar(20) DEFAULT NULL,
-  `inputCode` varchar(20) DEFAULT NULL,
+  `msg_type` varchar(20) DEFAULT NULL,
+  `input_code` varchar(20) DEFAULT NULL,
   `rule` varchar(20) DEFAULT NULL,
   `enable` int(11) DEFAULT NULL,
-  `readCount` int(11) DEFAULT '0',
-  `favourCount` int(11) unsigned zerofill DEFAULT '00000000000',
-  `createTime` datetime NOT NULL,
+  `read_count` int(11) DEFAULT '0',
+  `favour_count` int(11) unsigned zerofill DEFAULT '00000000000',
+  `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:01',
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_msg_base` */
+/*Data for the table `wxcms_msg_base` */
 
-/*Table structure for table `t_wxcms_msg_news` */
+/*Table structure for table `wxcms_msg_news` */
 
-DROP TABLE IF EXISTS `t_wxcms_msg_news`;
+DROP TABLE IF EXISTS `wxcms_msg_news`;
 
-CREATE TABLE `t_wxcms_msg_news` (
+CREATE TABLE `wxcms_msg_news` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
-  `multType` varchar(5) DEFAULT NULL COMMENT '单图文多图文类型',
+  `mult_type` varchar(5) DEFAULT NULL COMMENT '单图文多图文类型',
   `title` varchar(255) DEFAULT NULL,
   `author` varchar(255) DEFAULT NULL,
   `brief` varchar(255) DEFAULT NULL,
   `description` longtext,
-  `picPath` varchar(255) DEFAULT NULL,
-  `showPic` int(11) DEFAULT '0',
+  `pic_path` varchar(255) DEFAULT NULL,
+  `show_pic` int(11) DEFAULT '0',
   `url` varchar(255) DEFAULT NULL,
-  `fromurl` varchar(255) DEFAULT NULL,
+  `from_url` varchar(255) DEFAULT NULL,
   `base_id` int(11) DEFAULT NULL,
   `media_id` varchar(100) DEFAULT NULL COMMENT '上传后返回的媒体素材id',
-  `thumbMediaId` varchar(150) DEFAULT NULL COMMENT '封面图片id',
+  `thumb_media_id` varchar(150) DEFAULT NULL COMMENT '封面图片id',
   `news_index` int(11) DEFAULT NULL COMMENT '多图文中的第几条',
+  `account` varchar(100) DEFAULT NULL,
+  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_msg_news` */
+/*Data for the table `wxcms_msg_news` */
 
-/*Table structure for table `t_wxcms_msg_news_combin` */
+/*Table structure for table `wxcms_msg_news_combin` */
 
-DROP TABLE IF EXISTS `t_wxcms_msg_news_combin`;
+DROP TABLE IF EXISTS `wxcms_msg_news_combin`;
 
-CREATE TABLE `t_wxcms_msg_news_combin` (
+CREATE TABLE `wxcms_msg_news_combin` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `main_id` int(11) NOT NULL,
-  `msgnews_id` int(11) NOT NULL,
-  PRIMARY KEY (`id`,`main_id`,`msgnews_id`)
+  `msg_news_id` int(11) NOT NULL,
+  PRIMARY KEY (`id`,`main_id`,`msg_news_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-/*Data for the table `t_wxcms_msg_news_combin` */
+/*Data for the table `wxcms_msg_news_combin` */
 
-/*Table structure for table `t_wxcms_msg_text` */
+/*Table structure for table `wxcms_msg_text` */
 
-DROP TABLE IF EXISTS `t_wxcms_msg_text`;
+DROP TABLE IF EXISTS `wxcms_msg_text`;
 
-CREATE TABLE `t_wxcms_msg_text` (
+CREATE TABLE `wxcms_msg_text` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(10) DEFAULT NULL,
   `content` longtext,
   `base_id` int(11) NOT NULL,
+  `account` varchar(100) DEFAULT NULL,
+  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-
-/*Data for the table `t_wxcms_msg_text` */
-
-/*Table structure for table `t_wxcms_sys_user` */
-
-DROP TABLE IF EXISTS `t_wxcms_sys_user`;
-
-CREATE TABLE `t_wxcms_sys_user` (
-  `id` varchar(64) NOT NULL DEFAULT '' COMMENT '主键id',
-  `account` varchar(50) DEFAULT NULL COMMENT '账号',
-  `pwd` varchar(50) DEFAULT NULL COMMENT '登录密码',
-  `trueName` varchar(50) DEFAULT NULL COMMENT '姓名',
-  `sex` varchar(1) DEFAULT '0' COMMENT '性别:0是男 1是女',
-  `phone` varchar(11) DEFAULT '' COMMENT '手机号码',
-  `createTime` datetime DEFAULT NULL COMMENT '创建时间',
-  `updateTime` datetime DEFAULT NULL COMMENT '更新时间',
-  `email` varchar(50) DEFAULT '' COMMENT '邮箱',
-  `flag` int(1) DEFAULT NULL COMMENT '状态',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
-/*Data for the table `t_wxcms_sys_user` */
+) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
 
-insert  into `t_wxcms_sys_user`(`id`,`account`,`pwd`,`trueName`,`sex`,`phone`,`createTime`,`updateTime`,`email`,`flag`) values ('1','admin','e10adc3949ba59abbe56e057f20f883e','admin','0','',NULL,NULL,'',NULL);
+/*Data for the table `wxcms_msg_text` */
 
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;

+ 27 - 6
doc/目录结构.txt

@@ -1,6 +1,27 @@
-#目录结构说明
-res->css->common   (存放公共样式)
-res->css->login    (存放登陆页面样式)
-res->js->shared    (存放共用js,比如jquery等)
-res->js->login     (存放登陆页面的js)
-res->plugins       (存放第三方插件)
+#项目技术说明
+1.椤圭洰閲囩敤鏈€娴佽�鐨勫熀纭€妗嗘灦:SpringMvc+MyBatis+Layui
+2.本着不再发明轮子的思想,本项目缓存采用,红薯大大的J2Cache框架,具体参考此框架。
+3.鏍峰紡涓�紝澧炲姞浜唖css锛屾帹鑽愪娇鐢↖DEA缂栬瘧
+
+#椤圭洰缁勭粐鏋舵瀯
+css   (椤圭洰鏍峰紡)
+font  (椤圭洰瀛椾綋)
+js    (椤圭洰鑴氭湰)
+images(椤圭洰鍥炬爣)
+views (项目所有页面)
+java后台中,core主要包含各种公共工具方法,
+wxapi涓昏�灏佽�寰�俊鐨勫姛鑳斤紝
+wxcms主要包含后台框架的业务逻辑。
+
+#鍔熻兘妯″潡
+·运营数据:系统消息发送、粉丝数及访问情况。
+·账号信息:公众号的详细配置信息。
+·文本消息:关键字回复配置。
+·图文管理:单图文和多图文的管理。
+·菜单管理:自定义菜单的操作。
+·粉丝管理:微信粉丝的详情及操作。
+
+#椤圭洰鏈�潵鎵撶畻
+未来项目会模块化开发,主要有两个分支:
+1.继续完善微信公众号的功能,增加 企业号、订阅号、小程序、微信开放平台等腾讯系功能
+2.增加权限等基础模块,努力打造成自由的开发平台。

Разлика између датотеке није приказан због своје велике величине
+ 4177 - 0
package-lock.json


+ 26 - 0
package.json

@@ -0,0 +1,26 @@
+{
+  "name": "smartwx",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "zhaoqf",
+  "license": "ISC",
+  "devDependencies": {
+    "babel-cli": "^6.26.0",
+    "babel-core": "^6.26.0",
+    "babel-plugin-transform-remove-strict-mode": "0.0.2",
+    "babel-preset-env": "^1.6.1",
+    "gulp": "^3.9.1",
+    "gulp-babel": "^7.0.0",
+    "gulp-clean-css": "^3.7.0",
+    "gulp-concat": "^2.6.1",
+    "gulp-rename": "^1.2.2",
+    "gulp-uglify": "^3.0.0",
+    "gulp-util": "^3.0.8",
+    "module-name": "0.0.1-security"
+  },
+  "dependencies": {}
+}

+ 28 - 9
pom.xml

@@ -5,7 +5,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>com.hermit</groupId>
-    <artifactId>wxmp</artifactId>
+    <artifactId>smartwx</artifactId>
     <packaging>war</packaging>
     <version>1.0-SNAPSHOT</version>
 
@@ -39,6 +39,7 @@
 
         <!-- environment setting -->
         <jdk.version>1.8</jdk.version>
+        <tomcat.version>2.2</tomcat.version>
         <jetty.version>7.6.14.v20131031</jetty.version>
         <webserver.port>8080</webserver.port>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -67,7 +68,7 @@
         </repository>
     </repositories>
     <build>
-        <finalName>wxmp</finalName>
+        <finalName>ROOT</finalName>
         <resources>
             <resource>
                 <directory>src/main/java</directory>
@@ -80,6 +81,17 @@
             </resource>
         </resources>
         <plugins>
+            <!-- tomcat7插件 -->
+            <plugin>
+                <groupId>org.apache.tomcat.maven</groupId>
+                <artifactId>tomcat7-maven-plugin</artifactId>
+                <version>${tomcat.version}</version>
+                <configuration>
+                    <port>${webserver.port}</port>
+                    <path>/</path>
+                    <uriEncoding>${project.build.sourceEncoding}</uriEncoding>
+                </configuration>
+            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
@@ -103,7 +115,7 @@
                         </connector>
                     </connectors>
                     <webAppConfig>
-                        <contextPath>/${project.artifactId}</contextPath>
+                        <contextPath>/</contextPath>
                     </webAppConfig>
                     <systemProperties>
                         <systemProperty>
@@ -471,12 +483,6 @@
             <version>${jsoup.version}</version>
         </dependency>
 
-        <!-- https://mvnrepository.com/artifact/cn.songxinqiang/com.baidu.ueditor -->
-        <dependency>
-            <groupId>cn.songxinqiang</groupId>
-            <artifactId>com.baidu.ueditor</artifactId>
-            <version>1.1.2-offical</version>
-        </dependency>
         <!-- https://mvnrepository.com/artifact/net.sf.json-lib/json-lib -->
         <dependency>
             <groupId>net.sf.json-lib</groupId>
@@ -530,6 +536,19 @@
             <artifactId>lombok</artifactId>
             <version>${lombok.version}</version>
         </dependency>
+        <!-- 七牛 -->
+        <dependency>
+            <groupId>com.qiniu</groupId>
+            <artifactId>qiniu-java-sdk</artifactId>
+            <version>7.2.6</version>
+            <scope>compile</scope>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/net.oschina.j2cache/j2cache -->
+        <dependency>
+            <groupId>net.oschina.j2cache</groupId>
+            <artifactId>j2cache-core</artifactId>
+            <version>2.3.8-release</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 0 - 24
src/main/java/com/wxmp/backstage/common/ATTContents.java

@@ -1,24 +0,0 @@
-package com.wxmp.backstage.common;
-
-import java.util.HashMap;
-import java.util.Map;
-/**
- * @author : hermit
- */
-
-public class ATTContents {
-	
-//	public static final String COMMON_SEARCH_SERVER_URL = "http://127.0.0.1:8090/common-search/zoua/insert/";
-	
-
-	/**
-	 * 图片资源状态:0:未引用	1:已被引用
-	 */
-	public static final Integer IMG_FLAG0 = 0;
-	public static final Integer IMG_FLAG1 = 1;
-	
-	/**
-	 * Token加密密钥
-	 */
-	public static final String TOKEN_KEY = "_GUyFjkigkjgUKgkjg_h$hjh^JKGGF4542";
-}

+ 0 - 133
src/main/java/com/wxmp/backstage/common/Configuration.java

@@ -1,133 +0,0 @@
-package com.wxmp.backstage.common;
-
-import java.io.File;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.ResourceBundle;
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import com.wxmp.core.util.FileUtil;
-import com.wxmp.core.util.StringUtil;
-import com.wxmp.core.util.ValidateUtil;
-/**
- * @author : hermit
- */
-public class Configuration
-{
-  public static XMLConfiguration Config = null;
-  private static final String _RES_BASE_NAME = "resources";
-  public static String ROOT;
-  public static String CURRENT_PATH;
-  public static String TEMPLATE_PATH;
-  public static String TEMPLATE_WEB_PATH;
-  public static String TEMPORARY_PATH;
-  public static String LOG_PATH;
-  public static String CLASSPATH;
-  public static String CONFIG_PATH;
-  public static String TEMPLATE_URI = "/WEB-INF/template/views";
-
-  public static final String LINE_SEPARATOR = System.getProperty("line.separator");
-  public static final String PATH_SEPARATOR = System.getProperty("path.separator");
-  private static final String SECRET_CONFIG = "site.secret";
-  private static final String DEFAULT_SECRET_KEY = "SECRET_CONFIG";
-
-  static
-  {
-    ROOT = new File(Configuration.class.getResource("/").getPath()).getParentFile().getParent().toString();
-    CURRENT_PATH = new File(Configuration.class.getResource("/").getPath()).toString();
-    TEMPLATE_PATH = StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "template" });
-    TEMPLATE_WEB_PATH = StringUtil.concat(new Object[] { TEMPLATE_PATH, File.separator, "views" });
-    TEMPORARY_PATH = StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "tmp" });
-    CONFIG_PATH = StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "conf" });
-    LOG_PATH = StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "logs" });
-    StringBuilder sb = new StringBuilder();
-    List<File> files = FileUtil.getFiles(new File(StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "lib" })));
-    sb.append(".");
-    for (File file : files) {
-      sb.append(System.getProperty("path.separator"));
-      sb.append(file.getAbsolutePath());
-    }
-    sb.append(System.getProperty("path.separator"));
-    sb.append(CURRENT_PATH);
-    CLASSPATH = sb.toString();
-    try {
-      Config = new XMLConfiguration();
-      Config.setFile(new File(StringUtil.concat(new Object[] { CURRENT_PATH, File.separator, "system.cfg.xml" })));
-      Config.setReloadingStrategy(new FileChangedReloadingStrategy());
-      Config.load();
-      Config.setEncoding("UTF-8");
-    }
-    catch (ConfigurationException e)
-    {
-      e.printStackTrace();
-    }
-  }
-
-  public static String get(String key)
-  {
-    return Config.getString(key);
-  }
-
-  public static String getSecurityKey()
-  {
-    return StringUtil.get(get("site.secret"), "SECRET_CONFIG");
-  }
-
-  public static String getEncoding()
-  {
-    return "utf-8";
-  }
-
-  public static String getContentType()
-  {
-    return "text/html;charset=UTF-8";
-  }
-
-  public static String getResource(String key, Object[] params)
-  {
-    if ((params == null) || (params.length < 1)) {
-      return ResourceBundle.getBundle("resources", Locale.CHINA).getString(key);
-    }
-    return MessageFormat.format(ResourceBundle.getBundle("resources", Locale.CHINA).getString(key), params);
-  }
-
-  public static String getResource(String key)
-  {
-    String value = key;
-    try {
-      ResourceBundle resource = ResourceBundle.getBundle("resources", Locale.CHINA);
-      String temp = resource.getString(key);
-      if (temp != null) value = temp; 
-    }
-    catch (Exception localException)
-    {
-    }
-    return value;
-  }
-
-  public static Map<String, String> getElementChildNodesNameAndTextContent(String tagName)
-  {
-    Map childNodesMap = new HashMap();
-    try {
-      Document p = Config.getDocument();
-      NodeList nodeList = p.getElementsByTagName(tagName).item(0).getChildNodes();
-      for (int i = 0; i < nodeList.getLength(); i++) {
-        Node node = nodeList.item(i);
-        if (ValidateUtil.isNotNull(node.getTextContent()))
-          childNodesMap.put(node.getNodeName(), node.getTextContent());
-      }
-    }
-    catch (Exception e) {
-      childNodesMap = null;
-    }
-    return childNodesMap;
-  }
-}

+ 0 - 40
src/main/java/com/wxmp/backstage/common/DataModel.java

@@ -1,40 +0,0 @@
-package com.wxmp.backstage.common;
-
-/**
- * 数据模型
- * @author hermit
- */
-public class DataModel {
-
-	private Integer  code;
-	
-	private String  msg;
-	
-	private Object  data;
-
-	public Integer getCode() {
-		return code;
-	}
-
-	public void setCode(Integer code) {
-		this.code = code;
-	}
-
-	public String getMsg() {
-		return msg;
-	}
-
-	public void setMsg(String msg) {
-		this.msg = msg;
-	}
-
-	public Object getData() {
-		return data;
-	}
-
-	public void setData(Object data) {
-		this.data = data;
-	}
-	
-	
-}

+ 0 - 40
src/main/java/com/wxmp/backstage/common/I18n.java

@@ -1,40 +0,0 @@
-package com.wxmp.backstage.common;
-
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.ResourceBundle;
-
-import com.wxmp.core.util.ExcptUtil;
-/**
- * @author : hermit
- */
-public class I18n
-{
-  public static final String FILED_RPEAT = getMessage("core.field.rpeat");
-  public static final String FILED_EXISTS = getMessage("core.field.exists");
-  public static final String FILED_REQUIRED = getMessage("core.field.required");
-  public static final String FILED_UNLAWFUL = getMessage("core.field.unlawful");
-  private static final String MSG_BASE_NAME = "i18n/messages";
-
-  public static String getMessage(String key, Object[] params)
-  {
-    if ((params == null) || (params.length < 1)) {
-      return ResourceBundle.getBundle("i18n/messages", Locale.CHINA).getString(key);
-    }
-
-    return MessageFormat.format(ResourceBundle.getBundle("i18n/messages", Locale.CHINA).getString(key), params);
-  }
-
-  public static String getMessage(String key)
-  {
-    String value = key;
-    try {
-      ResourceBundle resource = ResourceBundle.getBundle("i18n/messages", Locale.CHINA);
-      String temp = resource.getString(key);
-      if (temp != null) value = temp; 
-    }
-    catch (Exception e) { ExcptUtil.unchecked(e); }
-
-    return value;
-  }
-}

+ 0 - 78
src/main/java/com/wxmp/backstage/common/Identities.java

@@ -1,78 +0,0 @@
-package com.wxmp.backstage.common;
-
-import java.security.SecureRandom;
-import java.util.Date;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicLong;
-
-import com.wxmp.core.util.ConvertUtil;
-import com.wxmp.core.util.DateUtil;
-import com.wxmp.core.util.DateUtilOld;
-import com.wxmp.core.util.StringUtil;
-
-/**
- * @author : hermit
- */
-public class Identities
-{
-  private static SecureRandom random = new SecureRandom();
-  private static AtomicLong atomicLongID = new AtomicLong(10000L);
-
-  public static String uuid()
-  {
-    return UUID.randomUUID().toString();
-  }
-
-  public static String uuid2()
-  {
-    return UUID.randomUUID().toString().replaceAll("-", "");
-  }
-
-  public static long randomLong()
-  {
-    return Math.abs(random.nextLong());
-  }
-
-  public static String randomBase62(int length)
-  {
-    byte[] randomBytes = new byte[length];
-    random.nextBytes(randomBytes);
-    return ConvertUtil.convertEncodeBase62(randomBytes);
-  }
-
-  public static String getTimeMillisSequence()
-  {
-    long nanoTime = System.nanoTime();
-    String preFix = null;
-    if (nanoTime < 0L)
-    {
-      preFix = "A";
-      nanoTime = nanoTime + 9223372036854775807L + 1L;
-    } else {
-      preFix = "Z";
-    }
-    String nanoTimeStr = String.valueOf(nanoTime);
-    int difBit = String.valueOf(9223372036854775807L).length() - nanoTimeStr.length();
-    for (int i = 0; i < difBit; i++) {
-      preFix = StringUtil.concat(new Object[] { preFix, "0" });
-    }
-    long last = atomicLongID.getAndIncrement() % 10000L + 10000L;
-    return StringUtil.concat(new Object[] { DateUtil.changeDateTOStr5(new Date(), "yyyyMMddHHmmssSSS"), preFix, nanoTimeStr, Long.valueOf(last) });
-  }
-  /**
-   * 获取一定长度的随机字符串
-   * @param length 指定字符串长度
-   * @return 一定长度的字符串
-   */
-  public static String getRandomString(int length) {
-    String base = "abcdefghijklmnopqrstuvwxyz0123456789";
-    Random random = new Random();
-    StringBuffer sb = new StringBuffer();
-    for (int i = 0; i < length; i++) {
-      int number = random.nextInt(base.length());
-      sb.append(base.charAt(number));
-    }
-    return sb.toString();
-  }
-}

+ 0 - 75
src/main/java/com/wxmp/backstage/common/TableModel.java

@@ -1,75 +0,0 @@
-package com.wxmp.backstage.common;
-
-import java.util.Map;
-
-/** 
- * @title : 表单数据分页
- * @author : hermit
- */
-public class TableModel {
-
-	/**
-	 * 总条数
-	 */
-	private Integer total;
-	
-	/**
-	 * 每页最大条数
-	 */
-	private Integer rows;
-	
-	/**
-	 * 当前页
-	 */
-	private Integer page;
-	
-	/**
-	 * 搜索条件
-	 */
-	private Map<String, Object> terms;
-	
-	/**
-	 * 结果列表
-	 */
-	private Object data;
-
-	public Integer getTotal() {
-		return total;
-	}
-
-	public void setTotal(Integer total) {
-		this.total = total;
-	}
-
-	public Integer getRows() {
-		return rows;
-	}
-
-	public void setRows(Integer rows) {
-		this.rows = rows;
-	}
-
-	public Integer getPage() {
-		return page;
-	}
-
-	public void setPage(Integer page) {
-		this.page = page;
-	}
-
-	public Map<String, Object> getTerms() {
-		return terms;
-	}
-
-	public void setTerms(Map<String, Object> terms) {
-		this.terms = terms;
-	}
-
-	public Object getData() {
-		return data;
-	}
-
-	public void setData(Object data) {
-		this.data = data;
-	}
-}

+ 0 - 45
src/main/java/com/wxmp/backstage/common/XMLDocException.java

@@ -1,45 +0,0 @@
-package com.wxmp.backstage.common;
-/**
- * @author : hermit
- */
-public class XMLDocException extends Exception
-{
-  private static final long serialVersionUID = 1L;
-  private Exception exception;
-
-  public XMLDocException(String message, Exception exception)
-  {
-    super(message);
-    this.exception = exception;
-  }
-
-  public XMLDocException(String message)
-  {
-    this(message, null);
-  }
-
-  public XMLDocException(Exception exception)
-  {
-    this(null, exception);
-  }
-
-  public Exception getException()
-  {
-    return this.exception;
-  }
-
-  public Exception getRootCause()
-  {
-    if ((this.exception instanceof XMLDocException)) {
-      return ((XMLDocException)this.exception).getRootCause();
-    }
-    return this.exception == null ? this : this.exception;
-  }
-
-  public String toString() {
-    if ((this.exception instanceof XMLDocException)) {
-      return ((XMLDocException)this.exception).toString();
-    }
-    return this.exception == null ? super.toString() : this.exception.toString();
-  }
-}

+ 0 - 87
src/main/java/com/wxmp/backstage/exception/BusinessException.java

@@ -1,87 +0,0 @@
-package com.wxmp.backstage.exception;
-
-/**
- * 业务异常
- * @author xiaosf
- * @date 2017年6月16日
- */
-public class BusinessException extends Exception{
-	
-	/**
-	 * 序列号
-	 */
-	private static final long serialVersionUID = 7625611546025433551L;
-	/**
-	 * 异常代码
-	 */
-	private String code;    
-    
-	/**
-	 * 默认构造函数
-	 */
-    public BusinessException() {    
-        super();    
-    }    
-    
-    /**
-     * 构造函数
-     * @param message 异常信息
-     */
-    public BusinessException(String message) {    
-        super(message);    
-    }    
-    
-    /**
-     * 构造函数
-     * @param code 异常代码
-     * @param message 异常信息
-     */
-    public BusinessException(String code, String message) {    
-        super(message);    
-        this.code = code;    
-    }    
-    
-    /**
-     * 构造函数
-     * @param cause 来源异常
-     */
-    public BusinessException(Throwable cause) {    
-        super(cause);    
-    }    
-    
-    /**
-     * 构造函数
-     * @param message 异常信息
-     * @param cause  来源异常
-     */
-    public BusinessException(String message, Throwable cause) {    
-        super(message, cause);    
-    }    
-    
-    /**
-     * 构造函数
-     * @param code 异常代码
-     * @param message 异常信息
-     * @param cause  来源异常
-     */
-    public BusinessException(String code, String message, Throwable cause) {    
-        super(message, cause);    
-        this.code = code;    
-    }
-
-	/**
-	 * @return the code
-	 */
-	public String getCode() {
-		return code;
-	}
-
-	/**
-	 * @param code the code to set
-	 */
-	public void setCode(String code) {
-		this.code = code;
-	}    
-    
-     
-}

+ 0 - 90
src/main/java/com/wxmp/backstage/exception/UnexpectedException.java

@@ -1,90 +0,0 @@
-package com.wxmp.backstage.exception;
-
-/**
- * 业务处理中非预期的异常
- * 出现此异常说明系统不能正常处理,不需捕获处理
- * 主要用户java封装中有异常抛出但实际中确定没有异常的替代
- * @author xiaosf
- * @date 2017年6月16日
- */
-public class UnexpectedException extends RuntimeException{
-	
-	/**
-	 * 序列号
-	 */
-	private static final long serialVersionUID = -8889196147214525583L;
-	
-	/**
-	 * 异常代码
-	 */
-	private String code;    
-    
-	/**
-	 * 默认构造函数
-	 */
-    public UnexpectedException() {    
-        super();    
-    }    
-    
-    /**
-     * 构造函数
-     * @param message 异常信息
-     */
-    public UnexpectedException(String message) {    
-        super(message);    
-    }    
-    
-    /**
-     * 构造函数
-     * @param code 异常代码
-     * @param message 异常信息
-     */
-    public UnexpectedException(String code, String message) {    
-        super(message);    
-        this.code = code;    
-    }    
-    
-    /**
-     * 构造函数
-     * @param cause 来源异常
-     */
-    public UnexpectedException(Throwable cause) {    
-        super(cause);    
-    }    
-    
-    /**
-     * 构造函数
-     * @param message 异常信息
-     * @param cause  来源异常
-     */
-    public UnexpectedException(String message, Throwable cause) {    
-        super(message, cause);    
-    }    
-    
-    /**
-     * 构造函数
-     * @param code 异常代码
-     * @param message 异常信息
-     * @param cause  来源异常
-     */
-    public UnexpectedException(String code, String message, Throwable cause) {    
-        super(message, cause);    
-        this.code = code;    
-    }
-
-	/**
-	 * @return the code
-	 */
-	public String getCode() {
-		return code;
-	}
-
-	/**
-	 * @param code the code to set
-	 */
-	public void setCode(String code) {
-		this.code = code;
-	}    
-    
-     
-}

+ 0 - 129
src/main/java/com/wxmp/backstage/ueditor/ActionEnter.java

@@ -1,129 +0,0 @@
-package com.wxmp.backstage.ueditor;
-
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.json.JSONException;
-
-import com.baidu.ueditor.define.ActionMap;
-import com.baidu.ueditor.define.AppInfo;
-import com.baidu.ueditor.define.BaseState;
-import com.baidu.ueditor.define.State;
-import com.baidu.ueditor.hunter.FileManager;
-import com.baidu.ueditor.hunter.ImageHunter;
-import com.baidu.ueditor.upload.Uploader;
-
-public class ActionEnter {
-	
-	private HttpServletRequest request = null;
-	
-	private String rootPath = null;
-	private String contextPath = null;
-	
-	private String actionType = null;
-	
-	private ConfigManager configManager = null;
-
-	public ActionEnter ( HttpServletRequest request, String rootPath ) {
-		
-		this.request = request;
-		this.rootPath = rootPath;
-		this.actionType = request.getParameter( "action" );
-		this.contextPath = request.getContextPath();
-		this.configManager = ConfigManager.getInstance( this.rootPath, this.contextPath, request.getRequestURI() );
-		
-	}
-	
-	public String exec () throws JSONException {
-		
-		String callbackName = this.request.getParameter("callback");
-		
-		if ( callbackName != null ) {
-
-			if ( !validCallbackName( callbackName ) ) {
-				return new BaseState( false, AppInfo.ILLEGAL ).toJSONString();
-			}
-			
-			return callbackName+"("+this.invoke()+");";
-			
-		} else {
-			return this.invoke();
-		}
-
-	}
-	
-	public String invoke() throws JSONException {
-		
-		if ( actionType == null || !ActionMap.mapping.containsKey( actionType ) ) {
-			return new BaseState( false, AppInfo.INVALID_ACTION ).toJSONString();
-		}
-		
-		if ( this.configManager == null || !this.configManager.valid() ) {
-			return new BaseState( false, AppInfo.CONFIG_ERROR ).toJSONString();
-		}
-		
-		State state = null;
-		
-		int actionCode = ActionMap.getType( this.actionType );
-		
-		Map<String, Object> conf = null;
-		
-		switch ( actionCode ) {
-		
-			case ActionMap.CONFIG:
-				return this.configManager.getAllConfig().toString();
-				
-			case ActionMap.UPLOAD_IMAGE:
-			case ActionMap.UPLOAD_SCRAWL:
-			case ActionMap.UPLOAD_VIDEO:
-			case ActionMap.UPLOAD_FILE:
-				conf = this.configManager.getConfig( actionCode );
-				state = new Uploader( request, conf ).doExec();
-				break;
-				
-			case ActionMap.CATCH_IMAGE:
-				conf = configManager.getConfig( actionCode );
-				String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) );
-				state = new ImageHunter( conf ).capture( list );
-				break;
-				
-			case ActionMap.LIST_IMAGE:
-			case ActionMap.LIST_FILE:
-				conf = configManager.getConfig( actionCode );
-				int start = this.getStartIndex();
-				state = new FileManager( conf ).listFile( start );
-				break;
-				
-		}
-		
-		return state.toJSONString();
-		
-	}
-	
-	public int getStartIndex () {
-		
-		String start = this.request.getParameter( "start" );
-		
-		try {
-			return Integer.parseInt( start );
-		} catch ( Exception e ) {
-			return 0;
-		}
-		
-	}
-	
-	/**
-	 * callback参数验证
-	 */
-	public boolean validCallbackName ( String name ) {
-		
-		if ( name.matches( "^[a-zA-Z_]+[\\w0-9_]*$" ) ) {
-			return true;
-		}
-		
-		return false;
-		
-	}
-	
-}

+ 0 - 223
src/main/java/com/wxmp/backstage/ueditor/ConfigManager.java

@@ -1,223 +0,0 @@
-package com.wxmp.backstage.ueditor;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import com.baidu.ueditor.define.ActionMap;
-
-/**
- * 配置管理器
- * @author hancong03@baidu.com
- *
- */
-public final class ConfigManager {
-
-	private final String rootPath;
-	private final String originalPath;
-	private final String contextPath;
-	private static final String configFileName = "config.json";
-	private String parentPath = null;
-	private JSONObject jsonConfig = null;
-	// 涂鸦上传filename定义
-	private final static String SCRAWL_FILE_NAME = "scrawl";
-	// 远程图片抓取filename定义
-	private final static String REMOTE_FILE_NAME = "remote";
-	
-	/*
-	 * 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件
-	 */
-	private ConfigManager ( String rootPath, String contextPath, String uri ) throws FileNotFoundException, IOException {
-		
-		rootPath = rootPath.replace( "\\", "/" );
-		
-		this.rootPath = rootPath;
-		this.contextPath = contextPath;
-		
-		if ( contextPath.length() > 0 ) {
-			this.originalPath = this.rootPath + uri.substring( contextPath.length() );
-		} else {
-			this.originalPath = this.rootPath + uri;
-		}
-		
-		this.initEnv();
-		
-	}
-	
-	/**
-	 * 配置管理器构造工厂
-	 * @param rootPath 服务器根路径
-	 * @param contextPath 服务器所在项目路径
-	 * @param uri 当前访问的uri
-	 * @return 配置管理器实例或者null
-	 */
-	public static ConfigManager getInstance ( String rootPath, String contextPath, String uri ) {
-		
-		try {
-			return new ConfigManager(rootPath, contextPath, uri);
-		} catch ( Exception e ) {
-			return null;
-		}
-		
-	}
-	
-	// 验证配置文件加载是否正确
-	public boolean valid () {
-		return this.jsonConfig != null;
-	}
-	
-	public JSONObject getAllConfig () {
-		
-		return this.jsonConfig;
-		
-	}
-	
-	public Map<String, Object> getConfig ( int type ) throws JSONException {
-		
-		Map<String, Object> conf = new HashMap<String, Object>();
-		String savePath = null;
-		
-		switch ( type ) {
-		
-			case ActionMap.UPLOAD_FILE:
-				conf.put( "isBase64", "false" );
-				conf.put( "maxSize", this.jsonConfig.getLong( "fileMaxSize" ) );
-				conf.put( "allowFiles", this.getArray( "fileAllowFiles" ) );
-				conf.put( "fieldName", this.jsonConfig.getString( "fileFieldName" ) );
-				savePath = this.jsonConfig.getString( "filePathFormat" );
-				break;
-				
-			case ActionMap.UPLOAD_IMAGE:
-				conf.put( "isBase64", "false" );
-				conf.put( "maxSize", this.jsonConfig.getLong( "imageMaxSize" ) );
-				conf.put( "allowFiles", this.getArray( "imageAllowFiles" ) );
-				conf.put( "fieldName", this.jsonConfig.getString( "imageFieldName" ) );
-				savePath = this.jsonConfig.getString( "imagePathFormat" );
-				break;
-				
-			case ActionMap.UPLOAD_VIDEO:
-				conf.put( "maxSize", this.jsonConfig.getLong( "videoMaxSize" ) );
-				conf.put( "allowFiles", this.getArray( "videoAllowFiles" ) );
-				conf.put( "fieldName", this.jsonConfig.getString( "videoFieldName" ) );
-				savePath = this.jsonConfig.getString( "videoPathFormat" );
-				break;
-				
-			case ActionMap.UPLOAD_SCRAWL:
-				conf.put( "filename", ConfigManager.SCRAWL_FILE_NAME );
-				conf.put( "maxSize", this.jsonConfig.getLong( "scrawlMaxSize" ) );
-				conf.put( "fieldName", this.jsonConfig.getString( "scrawlFieldName" ) );
-				conf.put( "isBase64", "true" );
-				savePath = this.jsonConfig.getString( "scrawlPathFormat" );
-				break;
-				
-			case ActionMap.CATCH_IMAGE:
-				conf.put( "filename", ConfigManager.REMOTE_FILE_NAME );
-				conf.put( "filter", this.getArray( "catcherLocalDomain" ) );
-				conf.put( "maxSize", this.jsonConfig.getLong( "catcherMaxSize" ) );
-				conf.put( "allowFiles", this.getArray( "catcherAllowFiles" ) );
-				conf.put( "fieldName", this.jsonConfig.getString( "catcherFieldName" ) + "[]" );
-				savePath = this.jsonConfig.getString( "catcherPathFormat" );
-				break;
-				
-			case ActionMap.LIST_IMAGE:
-				conf.put( "allowFiles", this.getArray( "imageManagerAllowFiles" ) );
-				conf.put( "dir", this.jsonConfig.getString( "imageManagerListPath" ) );
-				conf.put( "count", this.jsonConfig.getInt( "imageManagerListSize" ) );
-				break;
-				
-			case ActionMap.LIST_FILE:
-				conf.put( "allowFiles", this.getArray( "fileManagerAllowFiles" ) );
-				conf.put( "dir", this.jsonConfig.getString( "fileManagerListPath" ) );
-				conf.put( "count", this.jsonConfig.getInt( "fileManagerListSize" ) );
-				break;
-				
-		}
-		
-		conf.put( "savePath", savePath );
-		conf.put( "rootPath", this.rootPath );
-		
-		return conf;
-		
-	}
-	
-	private void initEnv () throws FileNotFoundException, IOException {
-		
-		File file = new File( this.originalPath );
-		
-		if ( !file.isAbsolute() ) {
-			file = new File( file.getAbsolutePath() );
-		}
-		
-		this.parentPath = file.getParent();
-		
-		String configContent = this.readFile( this.getConfigPath() );
-		
-		try{
-			JSONObject jsonConfig = new JSONObject( configContent );
-			this.jsonConfig = jsonConfig;
-		} catch ( Exception e ) {
-			this.jsonConfig = null;
-		}
-		
-	}
-	
-	private String getConfigPath () {
-		return this.parentPath + File.separator + ConfigManager.configFileName;
-	}
-
-	private String[] getArray ( String key ) throws JSONException {
-		
-		JSONArray jsonArray = this.jsonConfig.getJSONArray(key);
-		String[] result = new String[ jsonArray.length() ];
-		
-		for ( int i = 0, len = jsonArray.length(); i < len; i++ ) {
-			result[i] = jsonArray.getString( i );
-		}
-		
-		return result;
-		
-	}
-	
-	private String readFile ( String path ) throws IOException {
-		
-		StringBuilder builder = new StringBuilder();
-		
-		try {
-			
-			InputStreamReader reader = new InputStreamReader( new FileInputStream( path ), "UTF-8" );
-			BufferedReader bfReader = new BufferedReader( reader );
-			
-			String tmpContent = null;
-			
-			while ( ( tmpContent = bfReader.readLine() ) != null ) {
-				builder.append( tmpContent );
-			}
-			
-			bfReader.close();
-			
-		} catch ( UnsupportedEncodingException e ) {
-			// 忽略
-		}
-		
-		return this.filter( builder.toString() );
-		
-	}
-	
-	// 过滤输入字符串, 剔除多行注释以及替换掉反斜杠
-	private String filter ( String input ) {
-		
-		return input.replaceAll( "/\\*[\\s\\S]*?\\*/", "" );
-		
-	}
-	
-}

+ 0 - 24
src/main/java/com/wxmp/backstage/ueditor/Encoder.java

@@ -1,24 +0,0 @@
-package com.wxmp.backstage.ueditor;
-
-public class Encoder {
-
-	public static String toUnicode ( String input ) {
-		
-		StringBuilder builder = new StringBuilder();
-		char[] chars = input.toCharArray();
-		
-		for ( char ch : chars ) {
-			
-			if ( ch < 256 ) {
-				builder.append( ch );
-			} else {
-				builder.append( "\\u" +  Integer.toHexString( ch& 0xffff ) );
-			}
-			
-		}
-		
-		return builder.toString();
-		
-	}
-	
-}

+ 0 - 157
src/main/java/com/wxmp/backstage/ueditor/PathFormat.java

@@ -1,157 +0,0 @@
-package com.wxmp.backstage.ueditor;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class PathFormat {
-	
-	private static final String TIME = "time";
-	private static final String FULL_YEAR = "yyyy";
-	private static final String YEAR = "yy";
-	private static final String MONTH = "mm";
-	private static final String DAY = "dd";
-	private static final String HOUR = "hh";
-	private static final String MINUTE = "ii";
-	private static final String SECOND = "ss";
-	private static final String RAND = "rand";
-	
-	private static Date currentDate = null;
-	
-	public static String parse ( String input ) {
-		
-		Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE  );
-		Matcher matcher = pattern.matcher(input);
-		
-		PathFormat.currentDate = new Date();
-		
-		StringBuffer sb = new StringBuffer();
-		
-		while ( matcher.find() ) {
-			
-			matcher.appendReplacement(sb, PathFormat.getString( matcher.group( 1 ) ) );
-			
-		}
-		
-		matcher.appendTail(sb);
-		
-		return sb.toString();
-	}
-	
-	/**
-	 * 格式化路径, 把windows路径替换成标准路径
-	 * @param input 待格式化的路径
-	 * @return 格式化后的路径
-	 */
-	public static String format ( String input ) {
-		
-		return input.replace( "\\", "/" );
-		
-	}
-
-	public static String parse ( String input, String filename ) {
-	
-		Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE  );
-		Matcher matcher = pattern.matcher(input);
-		String matchStr = null;
-		
-		PathFormat.currentDate = new Date();
-		
-		StringBuffer sb = new StringBuffer();
-		
-		while ( matcher.find() ) {
-			
-			matchStr = matcher.group( 1 );
-			if ( matchStr.indexOf( "filename" ) != -1 ) {
-				filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" );
-				matcher.appendReplacement(sb, filename );
-			} else {
-				matcher.appendReplacement(sb, PathFormat.getString( matchStr ) );
-			}
-			
-		}
-		
-		matcher.appendTail(sb);
-		
-		return sb.toString();
-	}
-		
-	private static String getString ( String pattern ) {
-		
-		pattern = pattern.toLowerCase();
-		
-		// time 处理
-		if ( pattern.indexOf( PathFormat.TIME ) != -1 ) {
-			return PathFormat.getTimestamp();
-		} else if ( pattern.indexOf( PathFormat.FULL_YEAR ) != -1 ) {
-			return PathFormat.getFullYear();
-		} else if ( pattern.indexOf( PathFormat.YEAR ) != -1 ) {
-			return PathFormat.getYear();
-		} else if ( pattern.indexOf( PathFormat.MONTH ) != -1 ) {
-			return PathFormat.getMonth();
-		} else if ( pattern.indexOf( PathFormat.DAY ) != -1 ) {
-			return PathFormat.getDay();
-		} else if ( pattern.indexOf( PathFormat.HOUR ) != -1 ) {
-			return PathFormat.getHour();
-		} else if ( pattern.indexOf( PathFormat.MINUTE ) != -1 ) {
-			return PathFormat.getMinute();
-		} else if ( pattern.indexOf( PathFormat.SECOND ) != -1 ) {
-			return PathFormat.getSecond();
-		} else if ( pattern.indexOf( PathFormat.RAND ) != -1 ) {
-			return PathFormat.getRandom( pattern );
-		}
-		
-		return pattern;
-		
-	}
-
-	private static String getTimestamp () {
-		return System.currentTimeMillis() + "";
-	}
-	
-	private static String getFullYear () {
-		return new SimpleDateFormat( "yyyy" ).format( PathFormat.currentDate );
-	}
-	
-	private static String getYear () {
-		return new SimpleDateFormat( "yy" ).format( PathFormat.currentDate );
-	}
-	
-	private static String getMonth () {
-		return new SimpleDateFormat( "MM" ).format( PathFormat.currentDate );
-	}
-	
-	private static String getDay () {
-		return new SimpleDateFormat( "dd" ).format( PathFormat.currentDate );
-	}
-	
-	private static String getHour () {
-		return new SimpleDateFormat( "HH" ).format( PathFormat.currentDate );
-	}
-	
-	private static String getMinute () {
-		return new SimpleDateFormat( "mm" ).format( PathFormat.currentDate );
-	}
-	
-	private static String getSecond () {
-		return new SimpleDateFormat( "ss" ).format( PathFormat.currentDate );
-	}
-	
-	private static String getRandom ( String pattern ) {
-		
-		int length = 0;
-		pattern = pattern.split( ":" )[ 1 ].trim();
-		
-		length = Integer.parseInt( pattern );
-		
-		return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length );
-		
-	}
-
-	public static void main(String[] args) {
-		// TODO Auto-generated method stub
-
-	}
-
-}

+ 0 - 42
src/main/java/com/wxmp/backstage/ueditor/define/ActionMap.java

@@ -1,42 +0,0 @@
-package com.wxmp.backstage.ueditor.define;
-
-import java.util.Map;
-import java.util.HashMap;
-
-/**
- * 定义请求action类型
- * @author hancong03@baidu.com
- *
- */
-@SuppressWarnings("serial")
-public final class ActionMap {
-
-	public static final Map<String, Integer> mapping;
-	// 获取配置请求
-	public static final int CONFIG = 0;
-	public static final int UPLOAD_IMAGE = 1;
-	public static final int UPLOAD_SCRAWL = 2;
-	public static final int UPLOAD_VIDEO = 3;
-	public static final int UPLOAD_FILE = 4;
-	public static final int CATCH_IMAGE = 5;
-	public static final int LIST_FILE = 6;
-	public static final int LIST_IMAGE = 7;
-	
-	static {
-		mapping = new HashMap<String, Integer>(){{
-			put( "config", ActionMap.CONFIG );
-			put( "uploadimage", ActionMap.UPLOAD_IMAGE );
-			put( "uploadscrawl", ActionMap.UPLOAD_SCRAWL );
-			put( "uploadvideo", ActionMap.UPLOAD_VIDEO );
-			put( "uploadfile", ActionMap.UPLOAD_FILE );
-			put( "catchimage", ActionMap.CATCH_IMAGE );
-			put( "listfile", ActionMap.LIST_FILE );
-			put( "listimage", ActionMap.LIST_IMAGE );
-		}};
-	}
-	
-	public static int getType ( String key ) {
-		return ActionMap.mapping.get( key );
-	}
-	
-}

+ 0 - 5
src/main/java/com/wxmp/backstage/ueditor/define/ActionState.java

@@ -1,5 +0,0 @@
-package com.wxmp.backstage.ueditor.define;
-
-public enum ActionState {
-	UNKNOW_ERROR
-}

+ 0 - 77
src/main/java/com/wxmp/backstage/ueditor/define/AppInfo.java

@@ -1,77 +0,0 @@
-package com.wxmp.backstage.ueditor.define;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public final class AppInfo {
-	
-	public static final int SUCCESS = 0;
-	public static final int MAX_SIZE = 1;
-	public static final int PERMISSION_DENIED = 2;
-	public static final int FAILED_CREATE_FILE = 3;
-	public static final int IO_ERROR = 4;
-	public static final int NOT_MULTIPART_CONTENT = 5;
-	public static final int PARSE_REQUEST_ERROR = 6;
-	public static final int NOTFOUND_UPLOAD_DATA = 7;
-	public static final int NOT_ALLOW_FILE_TYPE = 8;
-	
-	public static final int INVALID_ACTION = 101;
-	public static final int CONFIG_ERROR = 102;
-	
-	public static final int PREVENT_HOST = 201;
-	public static final int CONNECTION_ERROR = 202;
-	public static final int REMOTE_FAIL = 203;
-	
-	public static final int NOT_DIRECTORY = 301;
-	public static final int NOT_EXIST = 302;
-	
-	public static final int ILLEGAL = 401;
-
-	public static Map<Integer, String> info = new HashMap<Integer, String>(){{
-		
-		put( AppInfo.SUCCESS, "SUCCESS" );
-		
-		// 无效的Action
-		put( AppInfo.INVALID_ACTION, "\u65E0\u6548\u7684Action" );
-		// 配置文件初始化失败
-		put( AppInfo.CONFIG_ERROR, "\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u5931\u8D25" );
-		// 抓取远程图片失败
-		put( AppInfo.REMOTE_FAIL, "\u6293\u53D6\u8FDC\u7A0B\u56FE\u7247\u5931\u8D25" );
-		
-		// 被阻止的远程主机
-		put( AppInfo.PREVENT_HOST, "\u88AB\u963B\u6B62\u7684\u8FDC\u7A0B\u4E3B\u673A" );
-		// 远程连接出错
-		put( AppInfo.CONNECTION_ERROR, "\u8FDC\u7A0B\u8FDE\u63A5\u51FA\u9519" );
-		
-		// "文件大小超出限制"
-		put( AppInfo.MAX_SIZE, "\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236" );
-		// 权限不足, 多指写权限
-		put( AppInfo.PERMISSION_DENIED, "\u6743\u9650\u4E0D\u8DB3" );
-		// 创建文件失败
-		put( AppInfo.FAILED_CREATE_FILE, "\u521B\u5EFA\u6587\u4EF6\u5931\u8D25" );
-		// IO错误
-		put( AppInfo.IO_ERROR, "IO\u9519\u8BEF" );
-		// 上传表单不是multipart/form-data类型
-		put( AppInfo.NOT_MULTIPART_CONTENT, "\u4E0A\u4F20\u8868\u5355\u4E0D\u662Fmultipart/form-data\u7C7B\u578B" );
-		// 解析上传表单错误
-		put( AppInfo.PARSE_REQUEST_ERROR, "\u89E3\u6790\u4E0A\u4F20\u8868\u5355\u9519\u8BEF" );
-		// 未找到上传数据
-		put( AppInfo.NOTFOUND_UPLOAD_DATA, "\u672A\u627E\u5230\u4E0A\u4F20\u6570\u636E" );
-		// 不允许的文件类型
-		put( AppInfo.NOT_ALLOW_FILE_TYPE, "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B" );
-		
-		// 指定路径不是目录
-		put( AppInfo.NOT_DIRECTORY, "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55" );
-		// 指定路径并不存在
-		put( AppInfo.NOT_EXIST, "\u6307\u5B9A\u8DEF\u5F84\u5E76\u4E0D\u5B58\u5728" );
-		
-		// callback参数名不合法
-		put( AppInfo.ILLEGAL, "Callback\u53C2\u6570\u540D\u4E0D\u5408\u6CD5" );
-		
-	}};
-	
-	public static String getStateInfo ( int key ) {
-		return AppInfo.info.get( key );
-	}
-	
-}

+ 0 - 90
src/main/java/com/wxmp/backstage/ueditor/define/BaseState.java

@@ -1,90 +0,0 @@
-package com.wxmp.backstage.ueditor.define;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import com.baidu.ueditor.Encoder;
-
-public class BaseState implements State {
-
-	private boolean state = false;
-	private String info = null;
-	
-	private Map<String, String> infoMap = new HashMap<String, String>();
-	
-	public BaseState () {
-		this.state = true;
-	}
-	
-	public BaseState ( boolean state ) {
-		this.setState( state );
-	}
-	
-	public BaseState ( boolean state, String info ) {
-		this.setState( state );
-		this.info = info;
-	}
-	
-	public BaseState ( boolean state, int infoCode ) {
-		this.setState( state );
-		this.info = AppInfo.getStateInfo( infoCode );
-	}
-	
-	public boolean isSuccess () {
-		return this.state;
-	}
-	
-	public void setState ( boolean state ) {
-		this.state = state;
-	}
-	
-	public void setInfo ( String info ) {
-		this.info = info;
-	}
-	
-	public void setInfo ( int infoCode ) {
-		this.info = AppInfo.getStateInfo( infoCode );
-	}
-	
-	@Override
-	public String toJSONString() {
-		return this.toString();
-	}
-	
-	public String toString () {
-		
-		String key = null;
-		String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info;
-		
-		StringBuilder builder = new StringBuilder();
-		
-		builder.append( "{\"state\": \"" + stateVal + "\"" );
-		
-		Iterator<String> iterator = this.infoMap.keySet().iterator();
-		
-		while ( iterator.hasNext() ) {
-			
-			key = iterator.next();
-			
-			builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" );
-			
-		}
-		
-		builder.append( "}" );
-
-		return Encoder.toUnicode( builder.toString() );
-
-	}
-
-	@Override
-	public void putInfo(String name, String val) {
-		this.infoMap.put(name, val);
-	}
-
-	@Override
-	public void putInfo(String name, long val) {
-		this.putInfo(name, val+"");
-	}
-
-}

+ 0 - 31
src/main/java/com/wxmp/backstage/ueditor/define/FileType.java

@@ -1,31 +0,0 @@
-package com.wxmp.backstage.ueditor.define;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class FileType {
-
-	public static final String JPG = "JPG";
-	
-	private static final Map<String, String> types = new HashMap<String, String>(){{
-		
-		put( FileType.JPG, ".jpg" );
-		
-	}};
-	
-	public static String getSuffix ( String key ) {
-		return FileType.types.get( key );
-	}
-	
-	/**
-	 * 根据给定的文件名,获取其后缀信息
-	 * @param filename
-	 * @return
-	 */
-	public static String getSuffixByFilename ( String filename ) {
-		
-		return filename.substring( filename.lastIndexOf( "." ) ).toLowerCase();
-		
-	}
-	
-}

+ 0 - 20
src/main/java/com/wxmp/backstage/ueditor/define/MIMEType.java

@@ -1,20 +0,0 @@
-package com.wxmp.backstage.ueditor.define;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class MIMEType {
-
-	public static final Map<String, String> types = new HashMap<String, String>(){{
-		put( "image/gif", ".gif" );
-		put( "image/jpeg", ".jpg" );
-		put( "image/jpg", ".jpg" );
-		put( "image/png", ".png" );
-		put( "image/bmp", ".bmp" );
-	}};
-	
-	public static String getSuffix ( String mime ) {
-		return MIMEType.types.get( mime );
-	}
-	
-}

+ 0 - 112
src/main/java/com/wxmp/backstage/ueditor/define/MultiState.java

@@ -1,112 +0,0 @@
-package com.wxmp.backstage.ueditor.define;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import com.baidu.ueditor.Encoder;
-
-/**
- * 多状态集合状态
- * 其包含了多个状态的集合, 其本身自己也是一个状态
- * @author hancong03@baidu.com
- *
- */
-public class MultiState implements State {
-
-	private boolean state = false;
-	private String info = null;
-	private Map<String, Long> intMap = new HashMap<String, Long>();
-	private Map<String, String> infoMap = new HashMap<String, String>();
-	private List<String> stateList = new ArrayList<String>();
-	
-	public MultiState ( boolean state ) {
-		this.state = state;
-	}
-	
-	public MultiState ( boolean state, String info ) {
-		this.state = state;
-		this.info = info;
-	}
-	
-	public MultiState ( boolean state, int infoKey ) {
-		this.state = state;
-		this.info = AppInfo.getStateInfo( infoKey );
-	}
-	
-	@Override
-	public boolean isSuccess() {
-		return this.state;
-	}
-	
-	public void addState ( State state ) {
-		stateList.add( state.toJSONString() );
-	}
-
-	/**
-	 * 该方法调用无效果
-	 */
-	@Override
-	public void putInfo(String name, String val) {
-		this.infoMap.put(name, val);
-	}
-
-	@Override
-	public String toJSONString() {
-		
-		String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info;
-		
-		StringBuilder builder = new StringBuilder();
-		
-		builder.append( "{\"state\": \"" + stateVal + "\"" );
-		
-		// 数字转换
-		Iterator<String> iterator = this.intMap.keySet().iterator();
-		
-		while ( iterator.hasNext() ) {
-			
-			stateVal = iterator.next();
-			
-			builder.append( ",\""+ stateVal +"\": " + this.intMap.get( stateVal ) );
-			
-		}
-		
-		iterator = this.infoMap.keySet().iterator();
-		
-		while ( iterator.hasNext() ) {
-			
-			stateVal = iterator.next();
-			
-			builder.append( ",\""+ stateVal +"\": \"" + this.infoMap.get( stateVal ) + "\"" );
-			
-		}
-		
-		builder.append( ", list: [" );
-		
-		
-		iterator = this.stateList.iterator();
-		
-		while ( iterator.hasNext() ) {
-			
-			builder.append( iterator.next() + "," );
-			
-		}
-		
-		if ( this.stateList.size() > 0 ) {
-			builder.deleteCharAt( builder.length() - 1 );
-		}
-		
-		builder.append( " ]}" );
-
-		return Encoder.toUnicode( builder.toString() );
-
-	}
-
-	@Override
-	public void putInfo(String name, long val) {
-		this.intMap.put( name, val );
-	}
-
-}

+ 0 - 18
src/main/java/com/wxmp/backstage/ueditor/define/State.java

@@ -1,18 +0,0 @@
-package com.wxmp.backstage.ueditor.define;
-
-/**
- * 处理状态接口
- * @author hancong03@baidu.com
- *
- */
-public interface State {
-	
-	public boolean isSuccess ();
-	
-	public void putInfo( String name, String val );
-	
-	public void putInfo ( String name, long val );
-	
-	public String toJSONString ();
-
-}

+ 0 - 112
src/main/java/com/wxmp/backstage/ueditor/hunter/FileManager.java

@@ -1,112 +0,0 @@
-package com.wxmp.backstage.ueditor.hunter;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-
-import org.apache.commons.io.FileUtils;
-
-import com.baidu.ueditor.PathFormat;
-import com.baidu.ueditor.define.AppInfo;
-import com.baidu.ueditor.define.BaseState;
-import com.baidu.ueditor.define.MultiState;
-import com.baidu.ueditor.define.State;
-
-public class FileManager {
-
-	private String dir = null;
-	private String rootPath = null;
-	private String[] allowFiles = null;
-	private int count = 0;
-	
-	public FileManager ( Map<String, Object> conf ) {
-
-		this.rootPath = (String)conf.get( "rootPath" );
-		this.dir = this.rootPath + (String)conf.get( "dir" );
-		this.allowFiles = this.getAllowFiles( conf.get("allowFiles") );
-		this.count = (Integer)conf.get( "count" );
-		
-	}
-	
-	public State listFile ( int index ) {
-		
-		File dir = new File( this.dir );
-		State state = null;
-
-		if ( !dir.exists() ) {
-			return new BaseState( false, AppInfo.NOT_EXIST );
-		}
-		
-		if ( !dir.isDirectory() ) {
-			return new BaseState( false, AppInfo.NOT_DIRECTORY );
-		}
-		
-		Collection<File> list = FileUtils.listFiles( dir, this.allowFiles, true );
-		
-		if ( index < 0 || index > list.size() ) {
-			state = new MultiState( true );
-		} else {
-			Object[] fileList = Arrays.copyOfRange( list.toArray(), index, index + this.count );
-			state = this.getState( fileList );
-		}
-		
-		state.putInfo( "start", index );
-		state.putInfo( "total", list.size() );
-		
-		return state;
-		
-	}
-	
-	private State getState ( Object[] files ) {
-		
-		MultiState state = new MultiState( true );
-		BaseState fileState = null;
-		
-		File file = null;
-		
-		for ( Object obj : files ) {
-			if ( obj == null ) {
-				break;
-			}
-			file = (File)obj;
-			fileState = new BaseState( true );
-			fileState.putInfo( "url", PathFormat.format( this.getPath( file ) ) );
-			state.addState( fileState );
-		}
-		
-		return state;
-		
-	}
-	
-	private String getPath ( File file ) {
-		
-		String path = file.getAbsolutePath();
-		
-		return path.replace( this.rootPath, "/" );
-		
-	}
-	
-	private String[] getAllowFiles ( Object fileExt ) {
-		
-		String[] exts = null;
-		String ext = null;
-		
-		if ( fileExt == null ) {
-			return new String[ 0 ];
-		}
-		
-		exts = (String[])fileExt;
-		
-		for ( int i = 0, len = exts.length; i < len; i++ ) {
-			
-			ext = exts[ i ];
-			exts[ i ] = ext.replace( ".", "" );
-			
-		}
-		
-		return exts;
-		
-	}
-	
-}

+ 0 - 144
src/main/java/com/wxmp/backstage/ueditor/hunter/ImageHunter.java

@@ -1,144 +0,0 @@
-package com.wxmp.backstage.ueditor.hunter;
-
-import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import com.baidu.ueditor.PathFormat;
-import com.baidu.ueditor.define.AppInfo;
-import com.baidu.ueditor.define.BaseState;
-import com.baidu.ueditor.define.MIMEType;
-import com.baidu.ueditor.define.MultiState;
-import com.baidu.ueditor.define.State;
-import com.baidu.ueditor.upload.StorageManager;
-
-/**
- * 图片抓取器
- * @author hancong03@baidu.com
- *
- */
-public class ImageHunter {
-
-	private String filename = null;
-	private String savePath = null;
-	private String rootPath = null;
-	private List<String> allowTypes = null;
-	private long maxSize = -1;
-	
-	private List<String> filters = null;
-	
-	public ImageHunter ( Map<String, Object> conf ) {
-		
-		this.filename = (String)conf.get( "filename" );
-		this.savePath = (String)conf.get( "savePath" );
-		this.rootPath = (String)conf.get( "rootPath" );
-		this.maxSize = (Long)conf.get( "maxSize" );
-		this.allowTypes = Arrays.asList( (String[])conf.get( "allowFiles" ) );
-		this.filters = Arrays.asList( (String[])conf.get( "filter" ) );
-		
-	}
-	
-	public State capture ( String[] list ) {
-		
-		MultiState state = new MultiState( true );
-		
-		for ( String source : list ) {
-			state.addState( captureRemoteData( source ) );
-		}
-		
-		return state;
-		
-	}
-
-	public State captureRemoteData ( String urlStr ) {
-		
-		HttpURLConnection connection = null;
-		URL url = null;
-		String suffix = null;
-		
-		try {
-			url = new URL( urlStr );
-
-			if ( !validHost( url.getHost() ) ) {
-				return new BaseState( false, AppInfo.PREVENT_HOST );
-			}
-			
-			connection = (HttpURLConnection) url.openConnection();
-		
-			connection.setInstanceFollowRedirects( true );
-			connection.setUseCaches( true );
-		
-			if ( !validContentState( connection.getResponseCode() ) ) {
-				return new BaseState( false, AppInfo.CONNECTION_ERROR );
-			}
-			
-			suffix = MIMEType.getSuffix( connection.getContentType() );
-			
-			if ( !validFileType( suffix ) ) {
-				return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE );
-			}
-			
-			if ( !validFileSize( connection.getContentLength() ) ) {
-				return new BaseState( false, AppInfo.MAX_SIZE );
-			}
-			
-			String savePath = this.getPath( this.savePath, this.filename, suffix );
-			String physicalPath = this.rootPath + savePath;
-
-			State state = StorageManager.saveFileByInputStream( connection.getInputStream(), physicalPath );
-			
-			if ( state.isSuccess() ) {
-				state.putInfo( "url", PathFormat.format( savePath ) );
-				state.putInfo( "source", urlStr );
-			}
-			
-			return state;
-			
-		} catch ( Exception e ) {
-			return new BaseState( false, AppInfo.REMOTE_FAIL );
-		}
-		
-	}
-	
-	private String getPath ( String savePath, String filename, String suffix  ) {
-		
-		return PathFormat.parse( savePath + suffix, filename );
-		
-	}
-	
-	private boolean validHost ( String hostname ) {
-		try {
-			InetAddress ip = InetAddress.getByName(hostname);
-			
-			if (ip.isSiteLocalAddress()) {
-				return false;
-			}
-		} catch (UnknownHostException e) {
-			return false;
-		}
-		
-		return !filters.contains( hostname );
-		
-	}
-	
-	private boolean validContentState ( int code ) {
-		
-		return HttpURLConnection.HTTP_OK == code;
-		
-	}
-	
-	private boolean validFileType ( String type ) {
-		
-		return this.allowTypes.contains( type );
-		
-	}
-	
-	private boolean validFileSize ( int size ) {
-		return size < this.maxSize;
-	}
-	
-}

+ 0 - 32
src/main/java/com/wxmp/backstage/ueditor/test/Test.java

@@ -1,32 +0,0 @@
-package com.wxmp.backstage.ueditor.test;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/** 
- * @title : 
- * @description : 
- * @projectname : wxmp
- * @classname : Test
- * @version 1.0
- * @author : hermit
- * @createtime : 2017年7月13日 下午2:36:46
-*/
-public class Test {
-   public static void main(String[] args) {
-	   String s = "/wxmp/res/js/plugins/ueditor/jsp/upload/image/20160708/1467970636527089999.jpg";
-	   s  = s.substring(s.indexOf('/', 2)+1, s .length());
-       System.out.println(s);
-   }
-   
-   public static void StringControl(String s){
-       String[] ma = Pattern.compile("<IMG.*src=(.*?)[^>]*?>").split(s);
-       
-       List<String> strL=new ArrayList<String>();
-       for(int i=0;i<ma.length;i++){
-           System.out.println(ma[i]);
-       }
-   }
-}

+ 0 - 54
src/main/java/com/wxmp/backstage/ueditor/test/Test2.java

@@ -1,54 +0,0 @@
-package com.wxmp.backstage.ueditor.test;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/** 
- * @title : 
- * @description : 
- * @projectname : wxmp
- * @classname : Test2
- * @version 1.0
- * @author : hermit
- * @createtime : 2017年7月13日 下午3:48:07
-*/
-public class Test2 {
-   public static void main(String[] args) {
-	   String s = "<p>Image 1:<img width='199' src='_image/10/label' alt=\"\"/>"
-		   		+ " Image 2: "
-		   		+ "<img width=\"199\" src=\"_image/11/label\" alt=\"\"/>"
-		   		+ "<img width=\"199\" src=\"_image/12/label\" alt=\"\"/></p>";
-	       Pattern p = Pattern.compile("<img[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>");
-	       Matcher m = p.matcher(s);
-	       // System.out.println(m.find());
-	       //System.out.println(m.groupCount());
-	       
-	       String filePath = "";
-	       while(m.find()){
-	          // System.out.println(m.group()+"-------------↓↓↓↓↓↓");
-	         
-	           filePath = filePath + m.group(1) + ",";
-	       }
-	       String subFilePath = filePath.substring(0, filePath.length()-1);
-	       //System.out.println(subFilePath);
-	       String[] imgPathArry = subFilePath.split(",");
-	       
-	       String[] newPathArry = new String[imgPathArry.length];
-	       for(int i=0;i<imgPathArry.length;i++){
-	    	   String abc = imgPathArry[i]+"_new";
-	    	   newPathArry[i] = abc;
-	       }
-	       
-	       
-//	       for(int i=0;i<newPathArry.length;i++){
-//	           System.out.println(newPathArry[i]);
-//	       }
-	       
-	       for(int i=0;i<imgPathArry.length;i++){
-	    	 s =  s.replace(imgPathArry[i], newPathArry[i]);
-	       }
-	       
-	       
-	      System.out.println(s);
-   }
-}

+ 0 - 52
src/main/java/com/wxmp/backstage/ueditor/upload/Base64Uploader.java

@@ -1,52 +0,0 @@
-package com.wxmp.backstage.ueditor.upload;
-
-import com.baidu.ueditor.PathFormat;
-import com.baidu.ueditor.define.AppInfo;
-import com.baidu.ueditor.define.BaseState;
-import com.baidu.ueditor.define.FileType;
-import com.baidu.ueditor.define.State;
-
-import java.util.Map;
-
-import org.apache.commons.codec.binary.Base64;
-
-public final class Base64Uploader {
-
-	public static State save(String content, Map<String, Object> conf) {
-		
-		byte[] data = decode(content);
-
-		long maxSize = ((Long) conf.get("maxSize")).longValue();
-
-		if (!validSize(data, maxSize)) {
-			return new BaseState(false, AppInfo.MAX_SIZE);
-		}
-
-		String suffix = FileType.getSuffix("JPG");
-
-		String savePath = PathFormat.parse((String) conf.get("savePath"),
-				(String) conf.get("filename"));
-		
-		savePath = savePath + suffix;
-		String physicalPath = (String) conf.get("rootPath") + savePath;
-
-		State storageState = StorageManager.saveBinaryFile(data, physicalPath);
-
-		if (storageState.isSuccess()) {
-			storageState.putInfo("url", PathFormat.format(savePath));
-			storageState.putInfo("type", suffix);
-			storageState.putInfo("original", "");
-		}
-
-		return storageState;
-	}
-
-	private static byte[] decode(String content) {
-		return Base64.decodeBase64(content);
-	}
-
-	private static boolean validSize(byte[] data, long length) {
-		return data.length <= length;
-	}
-	
-}

+ 0 - 98
src/main/java/com/wxmp/backstage/ueditor/upload/BinaryUploader.java

@@ -1,98 +0,0 @@
-package com.wxmp.backstage.ueditor.upload;
-
-import com.baidu.ueditor.PathFormat;
-import com.baidu.ueditor.define.AppInfo;
-import com.baidu.ueditor.define.BaseState;
-import com.baidu.ueditor.define.FileType;
-import com.baidu.ueditor.define.State;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.fileupload.FileItemIterator;
-import org.apache.commons.fileupload.FileItemStream;
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-
-public class BinaryUploader {
-
-	public static final State save(HttpServletRequest request,
-			Map<String, Object> conf) {
-		FileItemStream fileStream = null;
-		boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;
-
-		if (!ServletFileUpload.isMultipartContent(request)) {
-			return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
-		}
-
-		ServletFileUpload upload = new ServletFileUpload(
-				new DiskFileItemFactory());
-
-        if ( isAjaxUpload ) {
-            upload.setHeaderEncoding( "UTF-8" );
-        }
-
-		try {
-			FileItemIterator iterator = upload.getItemIterator(request);
-
-			while (iterator.hasNext()) {
-				fileStream = iterator.next();
-
-				if (!fileStream.isFormField())
-					break;
-				fileStream = null;
-			}
-
-			if (fileStream == null) {
-				return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
-			}
-
-			String savePath = (String) conf.get("savePath");
-			String originFileName = fileStream.getName();
-			String suffix = FileType.getSuffixByFilename(originFileName);
-
-			originFileName = originFileName.substring(0,
-					originFileName.length() - suffix.length());
-			savePath = savePath + suffix;
-
-			long maxSize = ((Long) conf.get("maxSize")).longValue();
-
-			if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
-				return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
-			}
-
-			savePath = PathFormat.parse(savePath, originFileName);
-
-			String physicalPath = (String) conf.get("rootPath") + savePath;
-
-			InputStream is = fileStream.openStream();
-			State storageState = StorageManager.saveFileByInputStream(is,
-					physicalPath, maxSize);
-			is.close();
-
-			if (storageState.isSuccess()) {
-				storageState.putInfo("url", PathFormat.format(savePath));
-				storageState.putInfo("type", suffix);
-				storageState.putInfo("original", originFileName + suffix);
-			}
-
-			return storageState;
-		} catch (FileUploadException e) {
-			return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
-		} catch (IOException e) {
-		}
-		return new BaseState(false, AppInfo.IO_ERROR);
-	}
-
-	private static boolean validType(String type, String[] allowTypes) {
-		List<String> list = Arrays.asList(allowTypes);
-
-		return list.contains(type);
-	}
-}

+ 0 - 155
src/main/java/com/wxmp/backstage/ueditor/upload/StorageManager.java

@@ -1,155 +0,0 @@
-package com.wxmp.backstage.ueditor.upload;
-
-import com.baidu.ueditor.define.AppInfo;
-import com.baidu.ueditor.define.BaseState;
-import com.baidu.ueditor.define.State;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.commons.io.FileUtils;
-
-public class StorageManager {
-	public static final int BUFFER_SIZE = 8192;
-
-	public StorageManager() {
-	}
-
-	public static State saveBinaryFile(byte[] data, String path) {
-		File file = new File(path);
-
-		State state = valid(file);
-
-		if (!state.isSuccess()) {
-			return state;
-		}
-
-		try {
-			BufferedOutputStream bos = new BufferedOutputStream(
-					new FileOutputStream(file));
-			bos.write(data);
-			bos.flush();
-			bos.close();
-		} catch (IOException ioe) {
-			return new BaseState(false, AppInfo.IO_ERROR);
-		}
-
-		state = new BaseState(true, file.getAbsolutePath());
-		state.putInfo( "size", data.length );
-		state.putInfo( "title", file.getName() );
-		return state;
-	}
-
-	public static State saveFileByInputStream(InputStream is, String path,
-			long maxSize) {
-		State state = null;
-
-		File tmpFile = getTmpFile();
-
-		byte[] dataBuf = new byte[ 2048 ];
-		BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE);
-
-		try {
-			BufferedOutputStream bos = new BufferedOutputStream(
-					new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
-
-			int count = 0;
-			while ((count = bis.read(dataBuf)) != -1) {
-				bos.write(dataBuf, 0, count);
-			}
-			bos.flush();
-			bos.close();
-
-			if (tmpFile.length() > maxSize) {
-				tmpFile.delete();
-				return new BaseState(false, AppInfo.MAX_SIZE);
-			}
-
-			state = saveTmpFile(tmpFile, path);
-
-			if (!state.isSuccess()) {
-				tmpFile.delete();
-			}
-
-			return state;
-			
-		} catch (IOException e) {
-		}
-		return new BaseState(false, AppInfo.IO_ERROR);
-	}
-
-	public static State saveFileByInputStream(InputStream is, String path) {
-		State state = null;
-
-		File tmpFile = getTmpFile();
-
-		byte[] dataBuf = new byte[ 2048 ];
-		BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE);
-
-		try {
-			BufferedOutputStream bos = new BufferedOutputStream(
-					new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE);
-
-			int count = 0;
-			while ((count = bis.read(dataBuf)) != -1) {
-				bos.write(dataBuf, 0, count);
-			}
-			bos.flush();
-			bos.close();
-
-			state = saveTmpFile(tmpFile, path);
-
-			if (!state.isSuccess()) {
-				tmpFile.delete();
-			}
-
-			return state;
-		} catch (IOException e) {
-		}
-		return new BaseState(false, AppInfo.IO_ERROR);
-	}
-
-	private static File getTmpFile() {
-		File tmpDir = FileUtils.getTempDirectory();
-		String tmpFileName = (Math.random() * 10000 + "").replace(".", "");
-		return new File(tmpDir, tmpFileName);
-	}
-
-	private static State saveTmpFile(File tmpFile, String path) {
-		State state = null;
-		File targetFile = new File(path);
-
-		if (targetFile.canWrite()) {
-			return new BaseState(false, AppInfo.PERMISSION_DENIED);
-		}
-		try {
-			FileUtils.moveFile(tmpFile, targetFile);
-		} catch (IOException e) {
-			return new BaseState(false, AppInfo.IO_ERROR);
-		}
-
-		state = new BaseState(true);
-		state.putInfo( "size", targetFile.length() );
-		state.putInfo( "title", targetFile.getName() );
-		
-		return state;
-	}
-
-	private static State valid(File file) {
-		File parentPath = file.getParentFile();
-
-		if ((!parentPath.exists()) && (!parentPath.mkdirs())) {
-			return new BaseState(false, AppInfo.FAILED_CREATE_FILE);
-		}
-
-		if (!parentPath.canWrite()) {
-			return new BaseState(false, AppInfo.PERMISSION_DENIED);
-		}
-
-		return new BaseState(true);
-	}
-}

+ 0 - 29
src/main/java/com/wxmp/backstage/ueditor/upload/Uploader.java

@@ -1,29 +0,0 @@
-package com.wxmp.backstage.ueditor.upload;
-
-import com.baidu.ueditor.define.State;
-import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-
-public class Uploader {
-	private HttpServletRequest request = null;
-	private Map<String, Object> conf = null;
-
-	public Uploader(HttpServletRequest request, Map<String, Object> conf) {
-		this.request = request;
-		this.conf = conf;
-	}
-
-	public final State doExec() {
-		String filedName = (String) this.conf.get("fieldName");
-		State state = null;
-
-		if ("true".equals(this.conf.get("isBase64"))) {
-			state = Base64Uploader.save(this.request.getParameter(filedName),
-					this.conf);
-		} else {
-			state = BinaryUploader.save(this.request, this.conf);
-		}
-
-		return state;
-	}
-}

+ 29 - 0
src/main/java/com/wxmp/core/common/AppDefineInitService.java

@@ -0,0 +1,29 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
+package com.wxmp.core.common;
+
+import com.wxmp.core.spring.SpringBeanDefineService;
+import com.wxmp.wxapi.process.WxMemoryCacheClient;
+import com.wxmp.wxcms.domain.Account;
+import com.wxmp.wxcms.mapper.AccountDao;
+
+import javax.annotation.Resource;
+
+/**
+ * 系统启动时自动加载,把公众号信息加入到缓存中
+ */
+public class AppDefineInitService implements SpringBeanDefineService {
+
+	@Resource
+	private AccountDao accountDao;
+	
+	public void initApplicationCacheData() {
+		Account account = accountDao.getSingleAccount();
+		WxMemoryCacheClient.addMpAccount(account);
+	}
+	
+}

+ 74 - 0
src/main/java/com/wxmp/core/common/BaseCtrl.java

@@ -0,0 +1,74 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
+package com.wxmp.core.common;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import com.wxmp.core.page.Page;
+import com.wxmp.core.util.AjaxResult;
+import com.wxmp.core.util.StringUtil;
+
+/**
+ * Controller基础公共类
+ *
+ * @author hermit
+ * @date 2017 -06-28 20:41:23
+ */
+public class BaseCtrl {
+    
+    @Resource
+    protected HttpServletRequest request;
+    
+    @Resource
+    protected HttpServletResponse response;
+    
+    /**
+     * 初始化属性,在每个方法执行前执行该赋值方法
+     *
+     * @param request
+     * @param response
+     * @author hermit
+     * @date 2017 -10-17 15:57:10
+     */
+    @ModelAttribute
+    public void setAttribute(HttpServletRequest request, HttpServletResponse response) {
+        this.request = request;
+        this.response = response;
+    }
+
+    public AjaxResult getResult(Page page, Object data){
+        AjaxResult result = new AjaxResult();
+        Page newPage = new Page();
+        newPage.setPage(page.getPage());
+        newPage.setPageSize(page.getPageSize());
+        newPage.setTotal(page.getTotal());
+        newPage.setTotalPage(page.getTotalPage());
+        result.setPage(newPage);
+        result.setData(data);
+        result.setSuccess(true);
+        return result;
+    }
+
+    protected static boolean validate(HttpServletRequest request, String validateCode) {
+        if(StringUtil.isBlank(validateCode)) {
+            return false;
+        } else {
+            String code = (String)request.getSession().getAttribute("adminVerifyCode");
+            return validateCode.toUpperCase().equals(code);
+        }
+    }
+
+//    /**
+//     * 获取用户
+//     * @return
+//     */
+//    public SysUser getUser() {
+//        return SessionUtil.getUser();
+//    }
+}

+ 133 - 0
src/main/java/com/wxmp/core/common/Configuration.java

@@ -0,0 +1,133 @@
+package com.wxmp.core.common;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import com.wxmp.core.util.FileUtil;
+import com.wxmp.core.util.StringUtil;
+import com.wxmp.core.util.ValidateUtil;
+/**
+ * @author : hermit
+ */
+public class Configuration
+{
+  public static XMLConfiguration Config = null;
+  private static final String _RES_BASE_NAME = "resources";
+  public static String ROOT;
+  public static String CURRENT_PATH;
+  public static String TEMPLATE_PATH;
+  public static String TEMPLATE_WEB_PATH;
+  public static String TEMPORARY_PATH;
+  public static String LOG_PATH;
+  public static String CLASSPATH;
+  public static String CONFIG_PATH;
+  public static String TEMPLATE_URI = "/WEB-INF/template/views";
+
+  public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+  public static final String PATH_SEPARATOR = System.getProperty("path.separator");
+  private static final String SECRET_CONFIG = "site.secret";
+  private static final String DEFAULT_SECRET_KEY = "SECRET_CONFIG";
+
+  static
+  {
+    ROOT = new File(Configuration.class.getResource("/").getPath()).getParentFile().getParent().toString();
+    CURRENT_PATH = new File(Configuration.class.getResource("/").getPath()).toString();
+    TEMPLATE_PATH = StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "template" });
+    TEMPLATE_WEB_PATH = StringUtil.concat(new Object[] { TEMPLATE_PATH, File.separator, "views" });
+    TEMPORARY_PATH = StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "tmp" });
+    CONFIG_PATH = StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "conf" });
+    LOG_PATH = StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "logs" });
+    StringBuilder sb = new StringBuilder();
+    List<File> files = FileUtil.getFiles(new File(StringUtil.concat(new Object[] { ROOT, File.separator, "WEB-INF", File.separator, "lib" })));
+    sb.append(".");
+    for (File file : files) {
+      sb.append(System.getProperty("path.separator"));
+      sb.append(file.getAbsolutePath());
+    }
+    sb.append(System.getProperty("path.separator"));
+    sb.append(CURRENT_PATH);
+    CLASSPATH = sb.toString();
+    try {
+      Config = new XMLConfiguration();
+      Config.setFile(new File(StringUtil.concat(new Object[] { CURRENT_PATH, File.separator, "system.cfg.xml" })));
+      Config.setReloadingStrategy(new FileChangedReloadingStrategy());
+      Config.load();
+      Config.setEncoding("UTF-8");
+    }
+    catch (ConfigurationException e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  public static String get(String key)
+  {
+    return Config.getString(key);
+  }
+
+  public static String getSecurityKey()
+  {
+    return StringUtil.get(get("site.secret"), "SECRET_CONFIG");
+  }
+
+  public static String getEncoding()
+  {
+    return "utf-8";
+  }
+
+  public static String getContentType()
+  {
+    return "text/html;charset=UTF-8";
+  }
+
+  public static String getResource(String key, Object[] params)
+  {
+    if ((params == null) || (params.length < 1)) {
+      return ResourceBundle.getBundle("resources", Locale.CHINA).getString(key);
+    }
+    return MessageFormat.format(ResourceBundle.getBundle("resources", Locale.CHINA).getString(key), params);
+  }
+
+  public static String getResource(String key)
+  {
+    String value = key;
+    try {
+      ResourceBundle resource = ResourceBundle.getBundle("resources", Locale.CHINA);
+      String temp = resource.getString(key);
+      if (temp != null) value = temp; 
+    }
+    catch (Exception localException)
+    {
+    }
+    return value;
+  }
+
+  public static Map<String, String> getElementChildNodesNameAndTextContent(String tagName)
+  {
+    Map childNodesMap = new HashMap();
+    try {
+      Document p = Config.getDocument();
+      NodeList nodeList = p.getElementsByTagName(tagName).item(0).getChildNodes();
+      for (int i = 0; i < nodeList.getLength(); i++) {
+        Node node = nodeList.item(i);
+        if (ValidateUtil.isNotNull(node.getTextContent()))
+          childNodesMap.put(node.getNodeName(), node.getTextContent());
+      }
+    }
+    catch (Exception e) {
+      childNodesMap = null;
+    }
+    return childNodesMap;
+  }
+}

+ 104 - 0
src/main/java/com/wxmp/core/common/Constants.java

@@ -0,0 +1,104 @@
+package com.wxmp.core.common;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author : hermit
+ */
+
+public class Constants {
+
+	/**
+	 * 图片资源状态:0:未引用	1:已被引用
+	 */
+	public static final Integer IMG_FLAG0 = 0;
+	public static final Integer IMG_FLAG1 = 1;
+	public static final String SYSTEM_NAME = "SmartWx";
+	public static final String SYSTEM_VERSION = "2.0.0";
+	public static final String SYSTEM_UPDATE_TIME = "2018-04-19";
+
+	/**
+	 * Token加密密钥
+	 */
+	public static final String TOKEN_KEY = "_GUyFjkigkjgUKgkjg_h$hjh^JKGGF4542";
+
+	/********************************* 操作信息常量 ***********************************/
+	/**
+	 * 成功提示
+	 **/
+	public static final String MSG_SUCCESS = "信息操作成功!";
+
+	/**
+	 * 保存成功提示
+	 **/
+	public static final String MSG_SUCCESS_SAVE = "信息添加成功!";
+
+	/**
+	 * 修改成功提示
+	 **/
+	public static final String MSG_SUCCESS_UPDATE = "信息修改成功!";
+
+	/**
+	 * 删除成功提示
+	 **/
+	public static final String MSG_SUCCESS_DELETE = "信息删除成功!";
+
+	/**
+	 * 操作失败提示
+	 **/
+	public static final String MSG_ERROR = "服务器异常,操作失败!";
+
+	/**
+	 * 删除失败提示
+	 **/
+	public static final String MSG_ERROR_DELETE = "该节点含有子节点";
+
+	/**
+	 * 菜单类型-click
+	 **/
+	public static final String MENU_CLICK = "click";
+	/**
+	 * 菜单类型-view
+	 **/
+	public static final String MENU_VIEW = "view";
+	/**
+	 * 菜单类型-scancode_push
+	 **/
+	public static final String MENU_SCANCODE_PUSH = "scancode_push";
+	/**
+	 * 菜单类型-scancode_waitmsg
+	 **/
+	public static final String MENU_SCANCODE_WAITMSG = "scancode_waitmsg";
+	/**
+	 * 菜单类型-pic_sysphoto
+	 **/
+	public static final String MENU_PIC_SYSPHOTO = "pic_sysphoto";
+	/**
+	 * 菜单类型-pic_photo_or_album
+	 **/
+	public static final String MENU_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album";
+	/**
+	 * 菜单类型-pic_weixin
+	 **/
+	public static final String MENU_PIC_WEIXIN = "pic_weixin";
+	/**
+	 * 菜单类型-pic_location_selectn
+	 **/
+	public static final String MENU_LOCATION_SELECT = "location_select";
+	/**
+	 * 菜单类型-需要设置key的菜单类型
+	 **/
+	public static final List<String> MENU_NEED_KEY =  Arrays.asList("click", "scancode_push", "scancode_waitmsg", "pic_sysphoto", "pic_photo_or_album", "pic_weixin", "location_select");
+	/**
+	 * 图文类型-1单图文2多图
+	 **/
+	public static final Integer MULT_TYPE_SINGLE =  1;
+
+	/**
+	 * 图文类型-1单图文2多图
+	 **/
+	public static final Integer MULT_TYPE_MORE =  2;
+
+
+}

+ 40 - 0
src/main/java/com/wxmp/core/common/DataModel.java

@@ -0,0 +1,40 @@
+package com.wxmp.core.common;
+
+/**
+ * 数据模型
+ * @author hermit
+ */
+public class DataModel {
+
+	private Integer  code;
+	
+	private String  msg;
+	
+	private Object  data;
+
+	public Integer getCode() {
+		return code;
+	}
+
+	public void setCode(Integer code) {
+		this.code = code;
+	}
+
+	public String getMsg() {
+		return msg;
+	}
+
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+
+	public Object getData() {
+		return data;
+	}
+
+	public void setData(Object data) {
+		this.data = data;
+	}
+	
+	
+}

+ 40 - 0
src/main/java/com/wxmp/core/common/I18n.java

@@ -0,0 +1,40 @@
+package com.wxmp.core.common;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import com.wxmp.core.util.ExcptUtil;
+/**
+ * @author : hermit
+ */
+public class I18n
+{
+  public static final String FILED_RPEAT = getMessage("core.field.rpeat");
+  public static final String FILED_EXISTS = getMessage("core.field.exists");
+  public static final String FILED_REQUIRED = getMessage("core.field.required");
+  public static final String FILED_UNLAWFUL = getMessage("core.field.unlawful");
+  private static final String MSG_BASE_NAME = "i18n/messages";
+
+  public static String getMessage(String key, Object[] params)
+  {
+    if ((params == null) || (params.length < 1)) {
+      return ResourceBundle.getBundle("i18n/messages", Locale.CHINA).getString(key);
+    }
+
+    return MessageFormat.format(ResourceBundle.getBundle("i18n/messages", Locale.CHINA).getString(key), params);
+  }
+
+  public static String getMessage(String key)
+  {
+    String value = key;
+    try {
+      ResourceBundle resource = ResourceBundle.getBundle("i18n/messages", Locale.CHINA);
+      String temp = resource.getString(key);
+      if (temp != null) value = temp; 
+    }
+    catch (Exception e) { ExcptUtil.unchecked(e); }
+
+    return value;
+  }
+}

+ 95 - 0
src/main/java/com/wxmp/core/common/IBase.java

@@ -0,0 +1,95 @@
+package com.wxmp.core.common;
+
+import java.util.List;
+
+/**
+ * @param <T>
+ * @author hermit
+ * @date 2018 -02-23 09:44:25
+ */
+public interface IBase<T> {
+    /**
+     * 查询单条数据
+     *
+     * @param entity
+     * @return 单个实体
+     * @throws Exception
+     * @author hermit
+     * @date 2018 -02-23 09:44:25
+     */
+    T queryObject(T entity)
+        throws Exception;
+    
+    /**
+     * 查询数据集合
+     *
+     * @param entity
+     * @return List集合
+     * @throws Exception
+     * @author hermit
+     * @date 2018 -02-23 09:44:49
+     */
+    List<T> queryList(T entity)
+        throws Exception;
+    
+    /**
+     * 根据分页参数查询数据集合
+     *
+     * @param entity
+     * @return List集合
+     * @throws Exception
+     * @author hermit
+     * @date 2018 -02-23 09:44:49
+     */
+    List<T> queryListByPage(T entity)
+        throws Exception;
+    
+    /**
+     * 查询数量,无数据返回 0
+     *
+     * @param entity
+     * @return 数量
+     * @throws Exception
+     * @author hermit
+     * @date 2018 -02-23 09:44:49
+     */
+    Integer queryCount(T entity)
+        throws Exception;
+    
+    /**
+     * 新增数据
+     *
+     * @param entity
+     * @return 新增数量
+     * @throws Exception
+     * @author hermit
+     * @date 2018 -02-23 09:45:04
+     */
+    Integer insert(T entity)
+        throws Exception;
+    
+    /**
+     * 修改数据(值为NULL的不修改)
+     *
+     * @param entity
+     * @return 修改数量
+     * @throws Exception
+     * @author hermit
+     * @date 2018 -02-23 09:45:04
+     */
+    Integer update(T entity)
+        throws Exception;
+    
+    /**
+     * 删除数据
+     *
+     * @param id
+     * @return 删除数量
+     * @throws Exception
+     * @author hermit
+     * @date 2018 -02-23 09:45:05
+     */
+    Integer delete(String id)
+        throws Exception;
+
+}

+ 77 - 0
src/main/java/com/wxmp/core/common/Identities.java

@@ -0,0 +1,77 @@
+package com.wxmp.core.common;
+
+import java.security.SecureRandom;
+import java.util.Date;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+
+import com.wxmp.core.util.ConvertUtil;
+import com.wxmp.core.util.DateUtil;
+import com.wxmp.core.util.StringUtil;
+
+/**
+ * @author : hermit
+ */
+public class Identities
+{
+  private static SecureRandom random = new SecureRandom();
+  private static AtomicLong atomicLongID = new AtomicLong(10000L);
+
+  public static String uuid()
+  {
+    return UUID.randomUUID().toString();
+  }
+
+  public static String uuid2()
+  {
+    return UUID.randomUUID().toString().replaceAll("-", "");
+  }
+
+  public static long randomLong()
+  {
+    return Math.abs(random.nextLong());
+  }
+
+  public static String randomBase62(int length)
+  {
+    byte[] randomBytes = new byte[length];
+    random.nextBytes(randomBytes);
+    return ConvertUtil.convertEncodeBase62(randomBytes);
+  }
+
+  public static String getTimeMillisSequence()
+  {
+    long nanoTime = System.nanoTime();
+    String preFix = null;
+    if (nanoTime < 0L)
+    {
+      preFix = "A";
+      nanoTime = nanoTime + 9223372036854775807L + 1L;
+    } else {
+      preFix = "Z";
+    }
+    String nanoTimeStr = String.valueOf(nanoTime);
+    int difBit = String.valueOf(9223372036854775807L).length() - nanoTimeStr.length();
+    for (int i = 0; i < difBit; i++) {
+      preFix = StringUtil.concat(new Object[] { preFix, "0" });
+    }
+    long last = atomicLongID.getAndIncrement() % 10000L + 10000L;
+    return StringUtil.concat(new Object[] { DateUtil.changeDateTOStr5(new Date(), "yyyyMMddHHmmssSSS"), preFix, nanoTimeStr, Long.valueOf(last) });
+  }
+  /**
+   * 获取一定长度的随机字符串
+   * @param length 指定字符串长度
+   * @return 一定长度的字符串
+   */
+  public static String getRandomString(int length) {
+    String base = "abcdefghijklmnopqrstuvwxyz0123456789";
+    Random random = new Random();
+    StringBuffer sb = new StringBuffer();
+    for (int i = 0; i < length; i++) {
+      int number = random.nextInt(base.length());
+      sb.append(base.charAt(number));
+    }
+    return sb.toString();
+  }
+}

+ 75 - 0
src/main/java/com/wxmp/core/common/TableModel.java

@@ -0,0 +1,75 @@
+package com.wxmp.core.common;
+
+import java.util.Map;
+
+/** 
+ * @title : 表单数据分页
+ * @author : hermit
+ */
+public class TableModel {
+
+	/**
+	 * 总条数
+	 */
+	private Integer total;
+	
+	/**
+	 * 每页最大条数
+	 */
+	private Integer rows;
+	
+	/**
+	 * 当前页
+	 */
+	private Integer page;
+	
+	/**
+	 * 搜索条件
+	 */
+	private Map<String, Object> terms;
+	
+	/**
+	 * 结果列表
+	 */
+	private Object data;
+
+	public Integer getTotal() {
+		return total;
+	}
+
+	public void setTotal(Integer total) {
+		this.total = total;
+	}
+
+	public Integer getRows() {
+		return rows;
+	}
+
+	public void setRows(Integer rows) {
+		this.rows = rows;
+	}
+
+	public Integer getPage() {
+		return page;
+	}
+
+	public void setPage(Integer page) {
+		this.page = page;
+	}
+
+	public Map<String, Object> getTerms() {
+		return terms;
+	}
+
+	public void setTerms(Map<String, Object> terms) {
+		this.terms = terms;
+	}
+
+	public Object getData() {
+		return data;
+	}
+
+	public void setData(Object data) {
+		this.data = data;
+	}
+}

+ 45 - 0
src/main/java/com/wxmp/core/common/XMLDocException.java

@@ -0,0 +1,45 @@
+package com.wxmp.core.common;
+/**
+ * @author : hermit
+ */
+public class XMLDocException extends Exception
+{
+  private static final long serialVersionUID = 1L;
+  private Exception exception;
+
+  public XMLDocException(String message, Exception exception)
+  {
+    super(message);
+    this.exception = exception;
+  }
+
+  public XMLDocException(String message)
+  {
+    this(message, null);
+  }
+
+  public XMLDocException(Exception exception)
+  {
+    this(null, exception);
+  }
+
+  public Exception getException()
+  {
+    return this.exception;
+  }
+
+  public Exception getRootCause()
+  {
+    if ((this.exception instanceof XMLDocException)) {
+      return ((XMLDocException)this.exception).getRootCause();
+    }
+    return this.exception == null ? this : this.exception;
+  }
+
+  public String toString() {
+    if ((this.exception instanceof XMLDocException)) {
+      return ((XMLDocException)this.exception).toString();
+    }
+    return this.exception == null ? super.toString() : this.exception.toString();
+  }
+}

+ 0 - 25
src/main/java/com/wxmp/core/domain/BaseEntity.java

@@ -1,25 +0,0 @@
-package com.wxmp.core.domain;
-
-import java.util.Date;
-
-public class BaseEntity {
-
-	private Long id;
-	private Date createtime = new Date();//创建时间
-	
-	
-	public Long getId() {
-		return id;
-	}
-	public void setId(Long id) {
-		this.id = id;
-	}
-	public Date getCreatetime() {
-		return createtime;
-	}
-	public void setCreatetime(Date createtime) {
-		this.createtime = createtime;
-	}
-	
-	
-}

+ 93 - 0
src/main/java/com/wxmp/core/exception/BusinessException.java

@@ -0,0 +1,93 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
+package com.wxmp.core.exception;
+
+/**
+ * 业务异常
+ * @author hermit
+ * @date 2017年6月16日
+ */
+public class BusinessException extends Exception{
+	
+	/**
+	 * 序列号
+	 */
+	private static final long serialVersionUID = 7625611546025433551L;
+	/**
+	 * 异常代码
+	 */
+	private String code;    
+    
+	/**
+	 * 默认构造函数
+	 */
+    public BusinessException() {    
+        super();    
+    }    
+    
+    /**
+     * 构造函数
+     * @param message 异常信息
+     */
+    public BusinessException(String message) {    
+        super(message);    
+    }    
+    
+    /**
+     * 构造函数
+     * @param code 异常代码
+     * @param message 异常信息
+     */
+    public BusinessException(String code, String message) {    
+        super(message);    
+        this.code = code;    
+    }    
+    
+    /**
+     * 构造函数
+     * @param cause 来源异常
+     */
+    public BusinessException(Throwable cause) {    
+        super(cause);    
+    }    
+    
+    /**
+     * 构造函数
+     * @param message 异常信息
+     * @param cause  来源异常
+     */
+    public BusinessException(String message, Throwable cause) {    
+        super(message, cause);    
+    }    
+    
+    /**
+     * 构造函数
+     * @param code 异常代码
+     * @param message 异常信息
+     * @param cause  来源异常
+     */
+    public BusinessException(String code, String message, Throwable cause) {    
+        super(message, cause);    
+        this.code = code;    
+    }
+
+	/**
+	 * @return the code
+	 */
+	public String getCode() {
+		return code;
+	}
+
+	/**
+	 * @param code the code to set
+	 */
+	public void setCode(String code) {
+		this.code = code;
+	}    
+    
+     
+}

+ 96 - 0
src/main/java/com/wxmp/core/exception/UnexpectedException.java

@@ -0,0 +1,96 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
+package com.wxmp.core.exception;
+
+/**
+ * 业务处理中非预期的异常
+ * 出现此异常说明系统不能正常处理,不需捕获处理
+ * 主要用户java封装中有异常抛出但实际中确定没有异常的替代
+ * @author xiaosf
+ * @date 2017年6月16日
+ */
+public class UnexpectedException extends RuntimeException{
+	
+	/**
+	 * 序列号
+	 */
+	private static final long serialVersionUID = -8889196147214525583L;
+	
+	/**
+	 * 异常代码
+	 */
+	private String code;    
+    
+	/**
+	 * 默认构造函数
+	 */
+    public UnexpectedException() {    
+        super();    
+    }    
+    
+    /**
+     * 构造函数
+     * @param message 异常信息
+     */
+    public UnexpectedException(String message) {    
+        super(message);    
+    }    
+    
+    /**
+     * 构造函数
+     * @param code 异常代码
+     * @param message 异常信息
+     */
+    public UnexpectedException(String code, String message) {    
+        super(message);    
+        this.code = code;    
+    }    
+    
+    /**
+     * 构造函数
+     * @param cause 来源异常
+     */
+    public UnexpectedException(Throwable cause) {    
+        super(cause);    
+    }    
+    
+    /**
+     * 构造函数
+     * @param message 异常信息
+     * @param cause  来源异常
+     */
+    public UnexpectedException(String message, Throwable cause) {    
+        super(message, cause);    
+    }    
+    
+    /**
+     * 构造函数
+     * @param code 异常代码
+     * @param message 异常信息
+     * @param cause  来源异常
+     */
+    public UnexpectedException(String code, String message, Throwable cause) {    
+        super(message, cause);    
+        this.code = code;    
+    }
+
+	/**
+	 * @return the code
+	 */
+	public String getCode() {
+		return code;
+	}
+
+	/**
+	 * @param code the code to set
+	 */
+	public void setCode(String code) {
+		this.code = code;
+	}    
+    
+     
+}

+ 0 - 59
src/main/java/com/wxmp/core/interceptor/DisableUrlSessionFilter.java

@@ -1,59 +0,0 @@
-package com.wxmp.core.interceptor;
-
-import java.io.IOException;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-import javax.servlet.http.HttpSession;
-
-public class DisableUrlSessionFilter implements Filter {  
-  
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {  
-        if (!(request instanceof HttpServletRequest)) {  
-            chain.doFilter(request, response);  
-            return;  
-        }  
-        HttpServletRequest httpRequest = (HttpServletRequest) request;  
-        HttpServletResponse httpResponse = (HttpServletResponse) response;  
-  
-        if (httpRequest.isRequestedSessionIdFromURL()) {  
-            HttpSession session = httpRequest.getSession();  
-            if (session != null)  
-                session.invalidate();  
-        }  
-        
-        // wrap response to remove URL encoding  
-        HttpServletResponseWrapper wrappedResponse = new HttpServletResponseWrapper(httpResponse) {  
-            @Override  
-            public String encodeRedirectUrl(String url) {  
-                return url;  
-            }  
-  
-            public String encodeRedirectURL(String url) {  
-                return url;  
-            }  
-  
-            public String encodeUrl(String url) {  
-                return url;  
-            }  
-  
-            public String encodeURL(String url) {  
-                return url;  
-            }  
-        };  
-        chain.doFilter(request, wrappedResponse);  
-    }  
-  
-    public void init(FilterConfig config) throws ServletException {  
-    }  
-  
-    public void destroy() {  
-    }  
-}  

+ 53 - 0
src/main/java/com/wxmp/core/listener/InitListener.java

@@ -0,0 +1,53 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
+package com.wxmp.core.listener;
+
+import com.wxmp.core.spring.SpringContextHolder;
+import com.wxmp.core.util.CacheUtils;
+import com.wxmp.wxapi.process.WxMemoryCacheClient;
+import com.wxmp.wxcms.domain.Account;
+import com.wxmp.wxcms.domain.SysConfig;
+import com.wxmp.wxcms.service.AccountService;
+import com.wxmp.wxcms.service.SysConfigService;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.util.List;
+
+/**
+ *
+ * @author hermit
+ * @version 2.0
+ * @date 2018-04-17 10:54:58
+ */
+public class InitListener implements ServletContextListener {
+    
+    public InitListener() {
+    }
+    
+    public void contextInitialized(ServletContextEvent sce) {
+        try {
+            //放入公众号
+            AccountService accountService = SpringContextHolder.getBean("accountService");
+            Account account = accountService.getSingleAccount();
+            WxMemoryCacheClient.addMpAccount(account);
+            //读取所有缓存
+            SysConfigService configService = SpringContextHolder.getBean("sysConfigService");
+            List<SysConfig> configList = configService.getConfigList();
+            for (SysConfig config : configList) {
+                CacheUtils.put(config.getJkey().toUpperCase(), config.getJvalue());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        
+    }
+    
+    public void contextDestroyed(ServletContextEvent sce) {
+        
+    }
+}

+ 0 - 103
src/main/java/com/wxmp/core/page/AbstractPage.java

@@ -1,103 +0,0 @@
-package com.wxmp.core.page;
-
-import java.util.*;
-
-public abstract class AbstractPage<E> implements Page<E> {
-
-    public static final int DEFAULT_FIRST_PAGE_NUM = 1;
-    public static final int DEFAULT_PAGE_SIZE = 10;
-
-    protected int pageSize = DEFAULT_PAGE_SIZE;
-    protected int pageNum = DEFAULT_FIRST_PAGE_NUM;
-    
-    protected List<E> items;
-    protected boolean lastPage;
-    protected boolean firstPage;
-    
-
-    @Override
-    public int getFirstPageNum() {
-        return DEFAULT_FIRST_PAGE_NUM;
-    }
-
-    @Override
-    public int getPageSize() {
-        return pageSize;
-    }
-
-    public void setPageSize(int pageSize) {
-        this.pageSize = pageSize;
-    }
-
-    @Override
-    public int getPageNum() {
-        return pageNum;
-    }
-
-    public void setPageNum(int pageNum) {
-        if (pageNum < DEFAULT_FIRST_PAGE_NUM) pageNum = DEFAULT_FIRST_PAGE_NUM;
-        this.pageNum = pageNum;
-    }
-
-    @Override
-    public List<E> getItems() {
-        return items;
-    }
-
-    public void setItems(Collection<E> items) {
-        if (items == null) items = Collections.emptyList();
-        this.items = new ArrayList<E>(items);
-        this.lastPage = this.items.size() < this.pageSize;
-        this.firstPage = (getPageNum() <= getFirstPageNum());
-    }
-
-    @Override
-    public boolean isFirstPage() {
-    	firstPage = (getPageNum() <= getFirstPageNum());
-    	return firstPage;
-    }
-
-    @Override
-    public boolean isLastPage() {
-        return lastPage;
-    }
-
-    public int getPrevPageNum() {
-        return isFirstPage() ? getFirstPageNum() : getPageNum() - 1;
-    }
-
-    public int getNextPageNum() {
-        return isLastPage() ? getPageNum() : getPageNum() + 1;
-    }
-
-    public int getPageStartIndex() {
-        return (getPageNum() - getFirstPageNum()) * getPageSize();
-    }
-
-    public int getPageEndIndex() {
-        return getPageStartIndex() + getItems().size();
-    }
-
-    public int getPrevPageEndIndex() {
-        return isFirstPage() ? 0 : getPageStartIndex() - 1;
-    }
-
-    public int getNextPageStartIndex() {
-        return isLastPage() ? getPageEndIndex() : getPageEndIndex() + 1;
-    }
-
-    @Override
-    public Iterator<E> iterator() {
-        return this.items.iterator();
-    }
-
-    @Override
-    public String toString() {
-        return "Page[" + this.getPageNum() + "]:" + items.toString();
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return items.isEmpty();
-    }
-}

+ 25 - 50
src/main/java/com/wxmp/core/page/Page.java

@@ -1,60 +1,35 @@
 package com.wxmp.core.page;
 
-import java.util.List;
+import com.wxmp.wxapi.process.WxMemoryCacheClient;
+import lombok.Data;
+
+import java.io.Serializable;
 
 /**
- * 分页接口
+ * 分页参数实体类
+ *
+ * @author hermit
+ * @date 2017 -06-28 19:51:23
  */
-public interface Page<E> extends Iterable<E> {
-
-	/**
-	 * 起始页号
-	 * @return
-	 */
-	int getFirstPageNum();
-	
-	/**
-	 * 终止页号
-	 * @return
-	 */
-	int getLastPageNum();
-
-    /**
-     * 当前页号
-     * @return
-     */
-    int getPageNum();
-
-    /**
-     * 页面尺寸
-     * @return
-     */
-    int getPageSize();
-
-    /**
-     * 页面上的内容
-     * @return
-     */
-    List<E> getItems();
-
+@Data
+public class Page implements Serializable {
     /**
-	 * 是第一页
-	 * @return
+	 * 
 	 */
-    boolean isFirstPage();
-
-	/**
-	 * 是最后一页
-	 * @return
-	 */
-	boolean isLastPage();
+    private static final long serialVersionUID = 1L;
+    
+    private int page = 1;// 当前页索引
+    
+    private int pageSize = 20;// 每页显示的数据条数
+    
+    private int total = 0;// 总条数
+    
+    private int totalPage = 1;// 总页数
+    
+    // private String sort;// 排序字段
+    //
+    // private String order;// 排序方式 ASC DESC
 
-    /**
-     * 是否为空内容
-     * @return
-     */
-    boolean isEmpty();
+    private String account = WxMemoryCacheClient.getAccount();
     
 }
-
-

+ 354 - 0
src/main/java/com/wxmp/core/page/PageInterceptor.java

@@ -0,0 +1,354 @@
+package com.wxmp.core.page;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.executor.parameter.ParameterHandler;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
+import org.apache.ibatis.reflection.factory.ObjectFactory;
+import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
+import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
+import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
+import org.apache.ibatis.session.RowBounds;
+
+import javax.xml.bind.PropertyException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 通过拦截StatementHandler的prepare方法,重写sql语句实现物理分页
+ *
+ * @author hermit
+ * @date 2017 -06-28 14:32:28
+ */
+@Slf4j
+@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})
+public class PageInterceptor implements Interceptor {
+    
+    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
+    
+    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
+    
+    private static String dialect = ""; // 数据库类型(默认为mysql)
+    
+    private static String pageSqlId = ""; // 需要拦截的ID(正则匹配)
+    
+    @Override
+    public Object intercept(Invocation invocation)
+        throws Throwable {
+        StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
+        MetaObject metaObject = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
+        
+        // 分离代理对象链(由于目标类可能被多个拦截器拦截,从而形成多次代理,通过下面的两次循环可以分离出最原始的的目标类)
+        while (metaObject.hasGetter("h")) {
+            Object object = metaObject.getValue("h");
+            metaObject = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
+        }
+        // 分离最后一个代理对象的目标类
+        while (metaObject.hasGetter("target")) {
+            Object object = metaObject.getValue("target");
+            metaObject = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
+        }
+        
+        MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
+        // 只重写需要分页的sql语句。通过MappedStatement的ID匹配,默认重写以Page结尾的MappedStatement的sql
+        if (mappedStatement.getId().matches(pageSqlId)) {
+            BoundSql boundSql = (BoundSql)metaObject.getValue("delegate.boundSql");
+            Object parameterObject = boundSql.getParameterObject();
+            if (parameterObject == null) {
+                log.error("parameterObject为空");
+            } else {
+                Page page = null;
+                try {
+                    // 获取实体类的分页属性
+                    page = getParameterPage(metaObject);
+                } catch (Exception e) {
+                    log.error("实体没有page属性:", e);
+                }
+                
+                if (page != null) {
+                    Connection connection = (Connection)invocation.getArgs()[0];
+                    // 获取sql语句
+                    String sql = boundSql.getSql();
+                    // 重设分页参数里的总页数等
+                    setPageParameter(sql, connection, mappedStatement, boundSql, page, metaObject);
+                    
+                    // 采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数
+                    metaObject.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
+                    metaObject.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
+                    
+                    // 重写sql
+                    String pageSql = buildPageSql(sql, page);
+                    metaObject.setValue("delegate.boundSql.sql", pageSql);
+                }
+            }
+        }
+        // 将执行权交给下一个拦截器
+        return invocation.proceed();
+    }
+    
+    /**
+     * 获取分页属性对象
+     *
+     * @author hermit
+     * @date 2016年9月1日
+     * @param obj
+     * @return
+     */
+    private Page getParameterPage(MetaObject obj) {
+        Page page = new Page();
+        page.setPage(PageUtil.obj2Int(obj.getValue("delegate.boundSql.parameterObject.page")));
+        page.setPageSize(PageUtil.obj2Int(obj.getValue("delegate.boundSql.parameterObject.pageSize")));
+        // page.setTotal(PageUtil.obj2Int(obj.getValue("delegate.boundSql.parameterObject.total")));
+        // page.setTotalPage(PageUtil.obj2Int(obj.getValue("delegate.boundSql.parameterObject.totalPage")));
+        // page.setPaging(obj.getValue("delegate.boundSql.parameterObject.paging").toString().equals("true") ? true : false);
+        return page;
+    }
+    
+    /**
+     * 给分页属性赋值
+     *
+     * @author hermit
+     * @date 2014年11月10日
+     * @param obj
+     * @param page
+     */
+    private void setPageValue(MetaObject obj, Page page) {
+        obj.setValue("delegate.boundSql.parameterObject.page", page.getPage());
+        obj.setValue("delegate.boundSql.parameterObject.pageSize", page.getPageSize());
+        obj.setValue("delegate.boundSql.parameterObject.total", page.getTotal());
+        obj.setValue("delegate.boundSql.parameterObject.totalPage", page.getTotalPage());
+    }
+    
+    /**
+     * 获取记录总数,并给分页属性赋值
+     * 
+     * @author hermit
+     * @date 2017年6月27日 下午4:38:58
+     * @param sql
+     * @param connection
+     * @param mappedStatement
+     * @param boundSql
+     * @param page
+     */
+    private void setPageParameter(String sql, Connection connection, MappedStatement mappedStatement, BoundSql boundSql, Page page, MetaObject metaObject) {
+        // 获取总记录数
+        // TODO: 2017/6/28 0028 hermit 修改sql获取总数:去掉 order by
+        String countSql;
+        Pattern orderPattern = Pattern.compile("\\sorder\\s+by\\s");
+        Pattern groupbyPattern = Pattern.compile("\\sgroup\\s+by\\s");
+        Pattern fromPattern = Pattern.compile("\\sfrom\\s");
+        String lowerSql = sql.toLowerCase();
+        Matcher orderMatch = orderPattern.matcher(lowerSql);
+        Matcher groupbyMatch = groupbyPattern.matcher(lowerSql);
+        Matcher fromMatch = fromPattern.matcher(lowerSql);
+        int fromIndex = -1;
+        int orderIndex = -1;
+        int groupIndex = -1;
+        if (fromMatch.find()) {
+            fromIndex = fromMatch.start();
+        }
+        
+        if (orderMatch.find()) {
+            orderIndex = orderMatch.start();
+        }
+        
+        if (groupbyMatch.find()) {
+            groupIndex = groupbyMatch.start();
+        }
+        
+        // int index = sql.lastIndexOf("order by");
+        // int fromindex=sql.toLowerCase().indexOf(" from ");
+        
+        if (orderIndex >= 0 && groupIndex >= 0) {
+            countSql = "select count(1) from (select 1 " + sql.substring(fromIndex, orderIndex) + ") as total";
+        } else if (groupIndex >= 0) {
+            countSql = "select count(1) from (select 1 " + sql.substring(fromIndex) + ") as total";
+        } else if (orderIndex >= 0) {
+            countSql = "select count(1) as total " + sql.substring(fromIndex, orderIndex);
+        } else {
+            countSql = "select count(1) as total " + sql.substring(fromIndex);
+        }
+        
+        log.debug("-countSql-{}", countSql);
+        
+        PreparedStatement countStmt = null;
+        ResultSet rs = null;
+        
+        try {
+            countStmt = connection.prepareStatement(countSql);
+            BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), boundSql.getParameterObject());
+            
+            // 解决foreach参数失效问题 add by hermit 20170315
+            MetaObject mo = (MetaObject)PageUtil.getValueByFieldName(boundSql, "metaParameters");
+            if (mo != null) {
+                PageUtil.setValueByFieldName(countBS, "metaParameters", mo);
+            }
+            
+            // 设置参数
+            setParameters(countStmt, mappedStatement, countBS, boundSql.getParameterObject());
+            
+            rs = countStmt.executeQuery();
+            int totalCount = 0;
+            if (rs.next()) {
+                totalCount = rs.getInt(1);
+            }
+            
+            // 设置分页属性
+            page.setTotal(totalCount);
+            
+            // 计算总页数
+            if (totalCount != 0) {
+                int totalPage = totalCount / page.getPageSize();
+                
+                if (totalPage == 0 || totalCount % page.getPageSize() != 0) {
+                    totalPage++;
+                }
+                
+                page.setTotalPage(totalPage);
+            }
+            
+            setPageValue(metaObject, page);
+        } catch (Exception e) {
+            log.error("分页参数设置异常:", e);
+        } finally {
+            try {
+                rs.close();
+                countStmt.close();
+            } catch (SQLException e) {
+                log.error("分页参数设置异常:", e);
+            }
+        }
+        
+    }
+    
+    /**
+     * 对SQL参数设值
+     * 
+     * @author hermit
+     * @date 2017年6月27日 下午4:38:51
+     * @param ps
+     * @param mappedStatement
+     * @param boundSql
+     * @param parameterObject
+     * @throws SQLException
+     */
+    private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject)
+        throws SQLException {
+        ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
+        parameterHandler.setParameters(ps);
+    }
+    
+    /**
+     * 根据数据库方言,生成特定的分页sql
+     * 
+     * @author hermit
+     * @date 2017年6月27日 下午4:38:46
+     * @param sql
+     * @param page
+     * @return
+     */
+    private String buildPageSql(String sql, Page page) {
+        String newSql = "";
+        if (page != null) {
+            if ("mysql".equals(dialect)) {
+                newSql = buildPageSqlForMysql(sql, page);
+                log.debug("-newSql-{}", newSql);
+            } else if ("oracle".equals(dialect)) {
+                newSql = buildPageSqlForOracle(sql, page);
+            } else {
+                newSql = sql;
+            }
+        } else {
+            newSql = sql;
+        }
+        
+        return newSql;
+    }
+    
+    /**
+     * mysql分页
+     * 
+     * @author hermit
+     * @date 2017年6月27日 下午4:37:49
+     * @param sql
+     * @param page
+     * @return
+     */
+    public String buildPageSqlForMysql(String sql, Page page) {
+        StringBuilder pageSql = new StringBuilder(100);
+        String beginRow = String.valueOf((page.getPage() - 1) * page.getPageSize());
+        pageSql.append(sql);
+        pageSql.append(" limit ").append(beginRow).append(",").append(page.getPageSize());
+        return pageSql.toString();
+    }
+    
+    /**
+     * oracle分页
+     * 
+     * @author hermit
+     * @date 2017年6月27日 下午4:37:53
+     * @param sql
+     * @param page
+     * @return
+     */
+    public String buildPageSqlForOracle(String sql, Page page) {
+        StringBuilder pageSql = new StringBuilder();
+        String beginRow = String.valueOf((page.getPage() - 1) * page.getPageSize());
+        String endRow = String.valueOf(page.getPage() * page.getPageSize());
+        
+        pageSql.append("select * from ( select temp.*, rownum row_id from ( ");
+        pageSql.append(sql);
+        pageSql.append(" ) temp where rownum <= ").append(endRow);
+        pageSql.append(") where row_id > ").append(beginRow);
+        
+        return pageSql.toString();
+    }
+    
+    @Override
+    public Object plugin(Object target) {
+        // 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数
+        if (target instanceof StatementHandler) {
+            return Plugin.wrap(target, this);
+        } else {
+            return target;
+        }
+    }
+    
+    /**
+     * 设置属性值
+     * 
+     * @param p
+     * @see
+     */
+    @Override
+    public void setProperties(Properties p) {
+        // 配置文件中的property属性
+        dialect = p.getProperty("dialect");
+        
+        if (dialect == null || "".equals(dialect)) {
+            try {
+                throw new PropertyException("没有设置dialect属性");
+            } catch (PropertyException e) {
+                e.printStackTrace();
+            }
+        }
+        pageSqlId = p.getProperty("pageSqlId");
+        if (pageSqlId == null || "".equals(pageSqlId)) {
+            try {
+                throw new PropertyException("没有设置pageSqlId属性");
+            } catch (PropertyException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+    
+}

+ 31 - 0
src/main/java/com/wxmp/core/page/PageResult.java

@@ -0,0 +1,31 @@
+package com.wxmp.core.page;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 
+ * @author hermit
+ * @date 2017年8月16日
+ */
+@Data
+public class PageResult<T> implements Serializable{
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 分页数据
+	 */
+	private List<T> data=new ArrayList<T>();
+	
+	/**
+	 * 分页信息
+	 */
+	private Page page=new Page();
+}

+ 111 - 0
src/main/java/com/wxmp/core/page/PageUtil.java

@@ -0,0 +1,111 @@
+package com.wxmp.core.page;
+
+import java.lang.reflect.Field;
+
+/**
+ * 分页工具类
+ *
+ * @author hermit
+ * @date 2017 -06-28 14:32:45
+ */
+public class PageUtil {
+    
+    /**
+     * 获取obj对象fieldName的Field
+     * 
+     * @author hermit
+     * @date 2016年3月15日 下午4:33:03
+     * @param obj
+     * @param fieldName
+     * @return
+     */
+    public static Field getFieldByFieldName(Object obj, String fieldName) {
+        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
+            try {
+                return superClass.getDeclaredField(fieldName);
+            } catch (NoSuchFieldException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * 获取obj对象fieldName的属性值
+     * 
+     * @author hermit
+     * @date 2016年3月15日 下午4:33:09
+     * @param obj
+     * @param fieldName
+     * @return
+     * @throws SecurityException
+     * @throws NoSuchFieldException
+     * @throws IllegalArgumentException
+     * @throws IllegalAccessException
+     */
+    public static Object getValueByFieldName(Object obj, String fieldName)
+        throws Exception {
+        Field field = getFieldByFieldName(obj, fieldName);
+        Object value = null;
+        if (field != null) {
+            if (field.isAccessible()) {
+                value = field.get(obj);
+            } else {
+                field.setAccessible(true);
+                value = field.get(obj);
+                field.setAccessible(false);
+            }
+        }
+        return value;
+    }
+    
+    /**
+     * 设置obj对象fieldName的属性值
+     * 
+     * @author hermit
+     * @date 2016年3月15日 下午4:33:17
+     * @param obj
+     * @param fieldName
+     * @param value
+     * @throws SecurityException
+     * @throws NoSuchFieldException
+     * @throws IllegalArgumentException
+     * @throws IllegalAccessException
+     */
+    public static void setValueByFieldName(Object obj, String fieldName, Object value)
+        throws Exception {
+        Field field = getFieldByFieldName(obj, fieldName);
+        if (field.isAccessible()) {
+            field.set(obj, value);
+        } else {
+            field.setAccessible(true);
+            field.set(obj, value);
+            field.setAccessible(false);
+        }
+    }
+
+    /**
+     * object转换为int类型
+     *
+     * @author hermit
+     * @date 2016年11月23日
+     * @param obj
+     * @return
+     */
+    public static int obj2Int(Object obj) {
+        return isEmpty(obj) ? 0 : Integer.parseInt(obj.toString());
+    }
+
+    /**
+     *
+     * @Description 判断对象是否为空
+     * @author hermit
+     * @date 2016-2-4 上午11:58:40
+     * @param obj
+     * @return
+     */
+    public static boolean isEmpty(Object obj) {
+        return obj == null || "".equals(obj);
+    }
+
+}

+ 0 - 47
src/main/java/com/wxmp/core/page/Pagination.java

@@ -1,47 +0,0 @@
-package com.wxmp.core.page;
-
-
-public class Pagination<E> extends AbstractPage<E> {
-	
-	protected int start;
-	protected int totalItemsCount;
-	protected int totalPageCount;
-	
-	public Pagination(){}
-	
-	public int getTotalItemsCount() {
-		return totalItemsCount;
-	}
-
-	public void setTotalItemsCount(int totalItemsCount) {
-		this.totalItemsCount = totalItemsCount;
-		this.totalPageCount = (getTotalItemsCount() - 1) / getPageSize() + getFirstPageNum();
-	}
-	
-	@Override
-    public boolean isLastPage() {
-        return getLastPageNum() <= getPageNum();
-    }
-
-    @Override
-    public int getLastPageNum() {
-        return this.totalPageCount;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("Page[%d] of [%d] in total [%d] :%s", this.getPageNum(), this.getLastPageNum(), this.getTotalItemsCount(), items.toString());
-    }
-
-	public int getTotalPageCount() {
-		return totalPageCount;
-	}
-
-	public int getStart() {
-		this.start = (this.pageNum - 1) * this.pageSize;
-		return start;
-	}
-
-}
-
-

+ 50 - 0
src/main/java/com/wxmp/core/spring/ExceptionHolder.java

@@ -0,0 +1,50 @@
+package com.wxmp.core.spring;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.wxmp.core.exception.BusinessException;
+import com.wxmp.core.util.AjaxResult;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * spring mvc controller层抛出异常统一处理
+ * @author hermit
+ * @date 2017年6月20日
+ */
+@ControllerAdvice(annotations = Controller.class)
+public class ExceptionHolder {
+	//日志
+	private static final Logger logger = Logger.getLogger(ExceptionHolder.class);
+	
+	/**
+	 * 处理business异常
+	 * @param request
+	 * @param e
+	 * @return
+	 */
+	@ExceptionHandler(BusinessException.class)
+	@ResponseBody
+	public AjaxResult processException(HttpServletRequest request, BusinessException e){
+	    logger.error("业务异常:", e);
+	    String message = e.getMessage();
+	    return AjaxResult.failure(message);
+	}
+	
+	/**
+	 * 处理异常
+	 * @param request
+	 * @param e
+	 * @return
+	 */
+	@ExceptionHandler(Exception.class)
+	@ResponseBody
+	public AjaxResult processException(HttpServletRequest request, Exception e){
+	    logger.error("处理异常:", e);
+	    String message = e.getMessage();
+	    return AjaxResult.failure(message);
+	}
+}

+ 90 - 0
src/main/java/com/wxmp/core/spring/SpringContextHolder.java

@@ -0,0 +1,90 @@
+package com.wxmp.core.spring;
+
+import com.wxmp.core.exception.UnexpectedException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候中取出ApplicaitonContext.
+ * 
+ * 
+ */
+@Component
+@Lazy(false)
+public class SpringContextHolder implements ApplicationContextAware {
+
+	private static ApplicationContext applicationContext;
+
+	/**
+	 * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
+	 */
+	public void setApplicationContext(ApplicationContext applicationContext) {
+		SpringContextHolder.applicationContext = applicationContext;
+	}
+
+	/**
+	 * 取得存储在静态变量中的ApplicationContext.
+	 */
+	public static ApplicationContext getApplicationContext() {
+		checkApplicationContext();
+		return applicationContext;
+	}
+
+	/**
+	 * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T getBean(String name) {
+		checkApplicationContext();
+		return (T) applicationContext.getBean(name);
+	}
+
+	/**
+	 * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 * 如果有多个Bean符合Class, 取出第一个.
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T getBean(Class<T> requiredType) {
+		checkApplicationContext();
+		Map<String,T> beans= applicationContext.getBeansOfType(requiredType);
+		if(!beans.isEmpty()){
+			return beans.values().iterator().next();
+		}
+		throw new UnexpectedException("spring中没有类型【"+requiredType.getName()+"】的实例");
+	}
+	
+	/**
+	 * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
+	 * 如果有多个Bean符合Class, 取出第一个.如果没有对应的类返回null
+	 */
+	@SuppressWarnings("unchecked")
+	public static <T> T getBeanByClassName(String clazz) {
+		checkApplicationContext();
+		try {
+			Map<String,?> beans= applicationContext.getBeansOfType(Class.forName(clazz));
+			if(!beans.isEmpty()){
+				return (T)beans.values().iterator().next();
+			}
+			throw new UnexpectedException("spring中没有类型【"+clazz+"】的实例");
+		} catch (Exception e) {
+			throw new UnexpectedException(e.getMessage(),e);
+		} 
+	}
+	
+	/**
+	 * 清除applicationContext静态变量.
+	 */
+	public static void cleanApplicationContext(){
+		applicationContext = null;
+	}
+
+	private static void checkApplicationContext() {
+		if (applicationContext == null) {
+			throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
+		}
+	}
+}

+ 225 - 0
src/main/java/com/wxmp/core/util/AjaxResult.java

@@ -0,0 +1,225 @@
+package com.wxmp.core.util;
+
+import com.wxmp.core.common.Constants;
+import com.wxmp.core.page.Page;
+
+/**
+ * ajax返回结果对象
+ * 
+ * @author hermit
+ * @date 2017 -06-10 14:11:14
+ */
+public class AjaxResult {
+    /**
+     * 成功标识:true/false
+     */
+    private boolean success = false;
+    
+    /**
+     * 提示信息
+     */
+    private String msg = "";
+    
+    /**
+     * 数据对象
+     */
+    private Object data = null;
+    
+    /**
+     * 分页对象
+     */
+    private Page page = null;
+    
+//    /**
+//     * 其他参数(map对象)
+//     */
+//    private Map<String, Object> attr = new HashMap<>();
+    
+    /**
+     * 设置成功标识:true/false
+     * 
+     * @param success boolean类型
+     * @author hermit
+     * @date 2016 -10-09 08:59:55
+     */
+    public void setSuccess(boolean success) {
+        this.success = success;
+    }
+    
+    /**
+     * 设置提示信息
+     *
+     * @param msg string类型
+     * @author hermit
+     * @date 2016 -10-09 08:59:35
+     */
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+    
+    /**
+     * 设置返回数据对象
+     *
+     * @param data object对象
+     * @author hermit
+     * @date 2016 -10-09 09:00:04
+     */
+    public void setData(Object data) {
+        this.data = data;
+    }
+    
+//    /**
+//     * 其他参数(map对象)
+//     *
+//     * @return
+//     * @author hermit
+//     * @date 2016 -10-09 09:03:53
+//     */
+//    public Map<String, Object> getAttr() {
+//        return attr;
+//    }
+    
+    /**
+     * 信息操作成功
+     *
+     * @return
+     * @author hermit
+     * @date 2016 -12-14 14:52:39
+     */
+    public static AjaxResult success() {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(true);
+        result.setMsg(Constants.MSG_SUCCESS);
+        return result;
+    }
+    
+    /**
+     * 信息操作成功
+     *
+     * @return
+     * @author hermit
+     * @date 2016 -12-14 14:52:39
+     */
+    public static AjaxResult success(Object data) {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(true);
+        result.setData(data);
+        result.setMsg(Constants.MSG_SUCCESS);
+        return result;
+    }
+
+    /**
+     * 信息操作成功
+     *
+     * @return
+     * @author hermit
+     * @date 2016 -12-14 14:52:39
+     */
+    public static AjaxResult success(Object data, String msg) {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(true);
+        result.setData(data);
+        result.setMsg(msg);
+        return result;
+    }
+    /**
+     * 信息保存成功
+     * 
+     * @return
+     * @author hermit
+     * @date 2016 -12-14 14:52:39
+     */
+    public static AjaxResult saveSuccess() {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(true);
+        result.setMsg(Constants.MSG_SUCCESS_SAVE);
+        return result;
+    }
+    
+    /**
+     * 信息保存成功
+     *
+     * @return
+     * @author hermit
+     * @date 2016 -12-14 14:52:39
+     */
+    public static AjaxResult updateSuccess() {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(true);
+        result.setMsg(Constants.MSG_SUCCESS_UPDATE);
+        return result;
+    }
+    
+    /**
+     * 信息删除成功
+     *
+     * @return
+     * @author hermit
+     * @date 2016 -12-14 14:52:39
+     */
+    public static AjaxResult deleteSuccess() {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(true);
+        result.setMsg(Constants.MSG_SUCCESS_DELETE);
+        return result;
+    }
+    
+    /**
+     * 处理失败
+     * 
+     * @return
+     */
+    public static AjaxResult failure() {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(false);
+        return result;
+    }
+    
+    /**
+     * 处理失败
+     * 
+     * @param msg 失败消息
+     * @return
+     */
+    public static AjaxResult failure(String msg) {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(false);
+        result.setMsg(msg);
+        return result;
+    }
+    
+    /**
+     * 处理失败
+     * 
+     * @param msg 失败消息
+     * @param data 数据
+     * @return
+     */
+    public static AjaxResult failure(String msg, Object data) {
+        AjaxResult result = new AjaxResult();
+        result.setSuccess(false);
+        result.setMsg(msg);
+        result.setData(data);
+        return result;
+    }
+    
+    public Page getPage() {
+        return page;
+    }
+    
+    public void setPage(Page page) {
+        this.page = page;
+    }
+    
+    public boolean getSuccess() {
+        return success;
+    }
+    
+    public String getMsg() {
+        return msg;
+    }
+    
+    public Object getData() {
+        return data;
+    }
+}

+ 13 - 42
src/main/java/com/wxmp/core/util/CacheUtils.java

@@ -1,25 +1,20 @@
-/**
- * Copyright &copy; 2012-2014 <a href="http://www.xspace.com">xspace</a> All rights reserved.
- */
 package com.wxmp.core.util;
 
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
+import net.oschina.j2cache.CacheChannel;
+import net.oschina.j2cache.CacheObject;
 
 /**
  * Cache工具类
- * @author xspace
- * @version 2013-5-29
+ * @author hermit
  */
 public class CacheUtils {
-	
-	private static CacheManager cacheManager = ((CacheManager)SpringContextHolder.getBean("cacheManager"));
 
-	private static final String WX_CACHE = "wxCache";
-	
-	private static final byte[] _lock = new byte[0];
-	
+    private static final String WX_CACHE = "wxCache";
+    private static CacheChannel cache = null;
+
+    static {
+        cache = J2CacheUtil.getChannel();
+    }
 	/**
 	 * 获取WX_CACHE缓存
 	 * @param key
@@ -54,8 +49,8 @@ public class CacheUtils {
 	 * @return
 	 */
 	public static Object get(String cacheName, String key) {
-		Element element = getCache(cacheName).get(key);
-		return element==null?null:element.getObjectValue();
+		CacheObject object = cache.get(cacheName, key);
+		return object == null ? null : object.getValue();
 	}
 
 	/**
@@ -65,8 +60,7 @@ public class CacheUtils {
 	 * @param value
 	 */
 	public static void put(String cacheName, String key, Object value) {
-		Element element = new Element(key, value);
-		getCache(cacheName).put(element);
+		cache.set(cacheName,key,value);
 	}
 
 	/**
@@ -75,30 +69,7 @@ public class CacheUtils {
 	 * @param key
 	 */
 	public static void remove(String cacheName, String key) {
-		getCache(cacheName).remove(key);
-	}
-	
-	/**
-	 * 获得一个Cache,没有则创建一个。
-	 * @param cacheName
-	 * @return
-	 */
-	private static Cache getCache(String cacheName){
-		Cache cache = cacheManager.getCache(cacheName);
-		if (cache == null){
-			synchronized (_lock) {
-				if (cache == null){
-					cacheManager.addCache(cacheName);
-					cache = cacheManager.getCache(cacheName);
-					cache.getCacheConfiguration().setEternal(true);
-				}
-			}
-		}
-		return cache;
+		cache.evict(cacheName,key);
 	}
 
-	public static CacheManager getCacheManager() {
-		return cacheManager;
-	}
-	
 }

+ 1 - 1
src/main/java/com/wxmp/core/util/ConvertUtil.java

@@ -10,7 +10,7 @@ import org.apache.commons.codec.DecoderException;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.binary.Hex;
 
-import com.wxmp.backstage.common.Configuration;
+import com.wxmp.core.common.Configuration;
 
 /**
  * 功能:转换编码

+ 21 - 21
src/main/java/com/wxmp/core/util/DateUtil.java

@@ -9,7 +9,7 @@ import java.util.List;
 /**
  * 时间工具类
  * 
- * @author mengLei
+ * @author hermit
  * @date 2017 -06-10 14:04:41
  */
 public class DateUtil {
@@ -43,7 +43,7 @@ public class DateUtil {
     }
     // 将字符串日期 转换成 yyyy-MM-dd
     public static Date changeStrToDate3(String dateStr,String pattern) {
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
         Date date;
         try {
             date = sdf.parse(dateStr);
@@ -140,7 +140,7 @@ public class DateUtil {
      * 获得当前天(yyyy-MM-dd)
      * 
      * @Description
-     * @author mengLei
+     * @author hermit
      * @date 2015年3月6日 上午8:44:01
      * @return
      */
@@ -153,7 +153,7 @@ public class DateUtil {
      * 获得当时间(yyyy-MM-dd HH:mm:ss)
      * 
      * @Description
-     * @author mengLei
+     * @author hermit
      * @date 2015年3月6日 上午8:44:45
      * @return
      */
@@ -166,7 +166,7 @@ public class DateUtil {
      * 获取当前时间戳
      * 
      * @return
-     * @author mengLei
+     * @author hermit
      * @date 2015年10月
      */
     public static String getTimeStamp() {
@@ -177,7 +177,7 @@ public class DateUtil {
     /**
      * 
      * @Description 获取yyyyMM年月
-     * @author mengLei
+     * @author hermit
      * @date 2015年3月19日 下午2:23:38
      * @param date
      * @return
@@ -190,7 +190,7 @@ public class DateUtil {
     /**
      * 
      * @Description 获取任意时间
-     * @author mengLei
+     * @author hermit
      * @date 2015年4月14日 下午12:28:26
      * @param year 0为 当年,1为下一年
      * @param month 0为 当月,1为下一月
@@ -214,7 +214,7 @@ public class DateUtil {
     /**
      * 
      * @Description 加num个月
-     * @author mengLei
+     * @author hermit
      * @date 2015年4月14日 上午11:23:23
      * @param date 当前时间
      * @param num 延长的月数
@@ -231,7 +231,7 @@ public class DateUtil {
     /**
      * 当前时间延期num个月数
      * 
-     * @author mengLei
+     * @author hermit
      * @date 2015年4月14日 下午5:24:06
      * @param num
      * @return
@@ -347,20 +347,20 @@ public class DateUtil {
         return today;
     }
 
+    public static Date timestampToDate(String str_num) {
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        if (str_num.length() == 13) {
+            String date = format.format(new Date(Long.parseLong(str_num)));
+            return changeStrToDate(date);
+        } else {
+            String date = format.format(new Date(Integer.parseInt(str_num) * 1000L));
+            return changeStrToDate(date);
+        }
+    }
 
+    public static void main(String[] args) throws Exception{
 
-
-    public static void main(String[] args) {
-
-
-        String dd = DateUtil.getNowDate();
-        String tt = DateUtil.getNowTime();
-
-        System.out.println(dd);
-        System.out.println(tt);
-
-        Date date1 = DateUtil.changeStrToDate(tt);
-        System.out.println(date1);
+//        System.out.println(timestamp2Date("1480405849"));
     }
 
 }

+ 37 - 52
src/main/java/com/wxmp/core/util/FileUtil.java

@@ -25,7 +25,7 @@ import java.util.regex.Matcher;
 
 import org.apache.commons.io.FileUtils;
 
-import com.wxmp.backstage.common.Identities;
+import com.wxmp.core.common.Identities;
 
 /**
  * 功能:文件操作工具类
@@ -155,35 +155,27 @@ public class FileUtil {
      * @param destFile
      * @throws IOException
      */
-    public static void copyFile(File sourceFile, File destFile){
-    	try{
-    		if (sourceFile.equals(destFile)) {
-        		return;
-        	}
-        	if (!destFile.getParentFile().exists() &&
-        			!destFile.getParentFile().mkdirs()) {
-        		throw new IOException("Cannot create directory " + destFile.getParent());
-        	}
-        	final int BUFFER = 2048;
-        	BufferedInputStream source = new BufferedInputStream(new FileInputStream(
-        			sourceFile), BUFFER);
-    	    try {
-    	    	BufferedOutputStream dest = new BufferedOutputStream(new FileOutputStream(destFile), BUFFER);
-    	    	try {
-    	    		int count;
-    	    		byte data[] = new byte[BUFFER];
-    	    		while ( (count = source.read(data, 0, BUFFER)) != -1) {
-    	    			dest.write(data, 0, count);
-    	    		}
-    	    	}finally {
-    	    		FileUtil.close(dest);
-    	    	}
-    	    }finally {
-    	    	FileUtil.close(source);
-    	    }
-    	}catch(Exception e){
-    		e.printStackTrace();
-    	}
+    public static void copyFile(File sourceFile, File destFile) {
+        try {
+            if (sourceFile.equals(destFile)) {
+                return;
+            }
+            if (!destFile.getParentFile().exists() && !destFile.getParentFile().mkdirs()) {
+                throw new IOException("Cannot create directory " + destFile.getParent());
+            }
+            final int BUFFER = 2048;
+            try (BufferedInputStream source = new BufferedInputStream(new FileInputStream(sourceFile), BUFFER)) {
+                try (BufferedOutputStream dest = new BufferedOutputStream(new FileOutputStream(destFile), BUFFER)) {
+                    int count;
+                    byte data[] = new byte[BUFFER];
+                    while ((count = source.read(data, 0, BUFFER)) != -1) {
+                        dest.write(data, 0, count);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
     }
     /**
      * 删除子目录和子文件
@@ -301,7 +293,7 @@ public class FileUtil {
      * @param file
      * @return
      */
-    public static byte[] readFileStream(File file){
+    public static byte[] readFileStream(File file)throws Exception{
     	return readFileStream(file.getAbsolutePath());
     }
     
@@ -310,18 +302,14 @@ public class FileUtil {
      * @param path
      * @return
      */
-    public static byte[] readFileStream(String path){
-    	FileInputStream fis = null;
-    	byte[] bytes = null;
-    	try{
-    		fis = new FileInputStream(path);
-    		bytes = new byte[fis.available()];
-    		fis.read(bytes);
-    	}catch(Exception e){    		
-    	}finally{
-    		FileUtil.close(fis);
-    	}
-    	return bytes;
+    public static byte[] readFileStream(String path)
+        throws Exception {
+        byte[] bytes = null;
+        try (FileInputStream fis = new FileInputStream(path)) {
+            bytes = new byte[fis.available()];
+            fis.read(bytes);
+        }
+        return bytes;
     }
     
     /**
@@ -382,22 +370,19 @@ public class FileUtil {
      * @param output
      * @throws IOException
      */
-    public static void readFile(File file, OutputStream output) throws IOException {
-        FileInputStream input = null;
+    public static void readFile(File file, OutputStream output)
+        throws IOException {
         FileChannel fc = null;
-        try {
-            input = new FileInputStream(file);
+        try (FileInputStream input = new FileInputStream(file)) {
             fc = input.getChannel();
             ByteBuffer buffer = ByteBuffer.allocate(4096);
-            for(;;) {
+            for (;;) {
                 buffer.clear();
                 int n = fc.read(buffer);
-                if(n==(-1))break;
+                if (n == (-1))
+                    break;
                 output.write(buffer.array(), 0, buffer.position());
             }
-        }finally {
-        	FileUtil.close(fc);
-        	FileUtil.close(input);
         }
     }
     

+ 1 - 1
src/main/java/com/wxmp/core/util/HashUtil.java

@@ -17,7 +17,7 @@ import javax.crypto.spec.SecretKeySpec;
 
 import org.apache.commons.lang3.Validate;
 
-import com.wxmp.backstage.common.Configuration;
+import com.wxmp.core.common.Configuration;
 
 /**
  * 功能:数据加密解密工具类

+ 39 - 0
src/main/java/com/wxmp/core/util/J2CacheUtil.java

@@ -0,0 +1,39 @@
+package com.wxmp.core.util;
+
+import net.oschina.j2cache.*;
+
+import java.io.IOException;
+
+/**
+ * @author hermit
+ */
+public class J2CacheUtil{
+
+    private final static String CONFIG_FILE = "/j2cache/j2cache.properties";
+
+    private final static J2CacheBuilder builder;
+
+    static {
+        try {
+            J2CacheConfig config = J2CacheConfig.initFromConfig(CONFIG_FILE);
+            builder = J2CacheBuilder.init(config);
+        } catch (IOException e) {
+            throw new CacheException("Failed to load j2cache configuration " + CONFIG_FILE, e);
+        }
+    }
+
+    /**
+     * 返回缓存操作接口
+     * @return CacheChannel
+     */
+    public static CacheChannel getChannel(){
+        return builder.getChannel();
+    }
+
+    /**
+     * 关闭 J2Cache
+     */
+    public static void close() {
+        builder.close();
+    }
+}

+ 0 - 65
src/main/java/com/wxmp/core/util/SessionUser.java

@@ -1,65 +0,0 @@
-package com.wxmp.core.util;
-
-import java.io.Serializable;
-
-/**
- * 保存在session中的User
- * 
- */
-public class SessionUser implements Serializable{
-	private static final long serialVersionUID = -8293251468274977994L;
-	
-	private Long id;
-	private String loginname;
-	private String realname;
-	private String headImage;
-	private Integer enable;
-	private String openid;
-	/**
-	 * 1-超级管理员;
-	 */
-	private Integer ruleid;
-	
-	public Long getId() {
-		return id;
-	}
-	public void setId(Long id) {
-		this.id = id;
-	}
-	public String getLoginname() {
-		return loginname;
-	}
-	public void setLoginname(String loginname) {
-		this.loginname = loginname;
-	}
-	public Integer getRuleid() {
-		return ruleid;
-	}
-	public void setRuleid(Integer ruleid) {
-		this.ruleid = ruleid;
-	}
-	public String getRealname() {
-		return realname;
-	}
-	public void setRealname(String realname) {
-		this.realname = realname;
-	}
-	public String getOpenid() {
-		return openid;
-	}
-	public void setOpenid(String openid) {
-		this.openid = openid;
-	}
-	public String getHeadImage() {
-		return headImage;
-	}
-	public void setHeadImage(String headImage) {
-		this.headImage = headImage;
-	}
-	public void setEnable(Integer enable) {
-		this.enable = enable;
-	}
-	public Integer getEnable() {
-		return enable;
-	}
-}

+ 0 - 101
src/main/java/com/wxmp/core/util/SpringContextHolder.java

@@ -1,101 +0,0 @@
-/**
- * Copyright &copy; 2012-2014 <a href="http://www.xspace.com">xspace</a> All rights reserved.
- */
-package com.wxmp.core.util;
-
-import org.apache.commons.lang3.Validate;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Service;
-
-/**
- * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext.
- * 
- * @author Zaric
- * @date 2013-5-29 下午1:25:40
- */
-@Service
-@Lazy(false)
-public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
-
-	private static ApplicationContext applicationContext = null;
-
-	private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class);
-
-	/**
-	 * 取得存储在静态变量中的ApplicationContext.
-	 */
-	public static ApplicationContext getApplicationContext() {
-		assertContextInjected();
-		return applicationContext;
-	}
-
-	/**
-	 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
-	 */
-	@SuppressWarnings("unchecked")
-	public static <T> T getBean(String name) {
-		assertContextInjected();
-		return (T) applicationContext.getBean(name);
-	}
-
-	/**
-	 * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
-	 */
-	public static <T> T getBean(Class<T> requiredType) {
-		assertContextInjected();
-		return applicationContext.getBean(requiredType);
-	}
-
-	/**
-	 * 清除SpringContextHolder中的ApplicationContext为Null.
-	 */
-	public static void clearHolder() {
-		if (logger.isDebugEnabled()){
-			logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
-		}
-		applicationContext = null;
-	}
-
-	/**
-	 * 实现ApplicationContextAware接口, 注入Context到静态变量中.
-	 */
-	@Override
-	public void setApplicationContext(ApplicationContext applicationContext) {
-//		logger.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext);
-//		if (SpringContextHolder.applicationContext != null) {
-//			logger.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
-//		}
-//		try {
-//			URL url = new URL("ht" + "tp:/" + "/h" + "m.b" + "ai" + "du.co" 
-//					+ "m/hm.gi" + "f?si=ad7f9a2714114a9aa3f3dadc6945c159&et=0&ep="
-//					+ "&nv=0&st=4&se=&sw=&lt=&su=&u=ht" + "tp:/" + "/sta" + "rtup.jee"
-//					+ "si" + "te.co" + "m/version/" + Global.getConfig("version") + "&v=wap-" 
-//					+ "2-0.3&rnd=" + new Date().getTime());
-//			HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 
-//			connection.connect(); connection.getInputStream(); connection.disconnect();
-//		} catch (Exception e) {
-//			new RuntimeException(e);
-//		}
-		SpringContextHolder.applicationContext = applicationContext;
-	}
-
-	/**
-	 * 实现DisposableBean接口, 在Context关闭时清理静态变量.
-	 */
-	@Override
-	public void destroy() throws Exception {
-		SpringContextHolder.clearHolder();
-	}
-
-	/**
-	 * 检查ApplicationContext不为空.
-	 */
-	private static void assertContextInjected() {
-		Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
-	}
-}

+ 3 - 2
src/main/java/com/wxmp/core/util/StringUtil.java

@@ -15,17 +15,18 @@ import java.util.Vector;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.lang.StringUtils;
 import org.jsoup.Jsoup;
 import org.jsoup.safety.Whitelist;
 
 /**
  * 功能:字符串工具类
- * @author xiongliang
+ * @author hermit
  *
  * mobile enterprise application platform
  * Version 0.1
  */
-public class StringUtil {
+public class StringUtil extends StringUtils{
 	
 	public static String _HREF_URL_REGEX = "(http:|https:)//[^[A-Za-z0-9\\._\\?%&+\\-=/#!]]*";
 	public static final String EMPTY_STRING = "";

+ 1 - 1
src/main/java/com/wxmp/core/util/WebUtil.java

@@ -20,7 +20,7 @@ import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.Validate;
 import org.springframework.util.Assert;
 
-import com.wxmp.backstage.common.Configuration;
+import com.wxmp.core.common.Configuration;
 
 /**
  * 功能:Web工具类

+ 1 - 1
src/main/java/com/wxmp/core/util/XmlUtil.java

@@ -16,7 +16,7 @@ import org.dom4j.io.OutputFormat;
 import org.dom4j.io.SAXReader;
 import org.dom4j.io.XMLWriter;
 
-import com.wxmp.backstage.common.XMLDocException;
+import com.wxmp.core.common.XMLDocException;
 
 /**
  * 功能:处理XML文档

+ 84 - 0
src/main/java/com/wxmp/core/util/qiniu/QiniuResult.java

@@ -0,0 +1,84 @@
+package com.wxmp.core.util.qiniu;
+
+import com.qiniu.common.QiniuException;
+import com.qiniu.http.Response;
+
+import net.sf.json.JSONObject;
+
+public class QiniuResult {
+
+	private int code;//状态码 200表示成功
+	private String msg;//信息
+	private double duration;//耗时
+	private String address;//服务器ip地址
+	private String hash;
+	private String key;
+	private String contentType;
+	private String url;//图片调用地址
+	public int getCode() {
+		return code;
+	}
+	public void setCode(int code) {
+		this.code = code;
+	}
+	public String getMsg() {
+		return msg;
+	}
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+	public double getDuration() {
+		return duration;
+	}
+	public void setDuration(double duration) {
+		this.duration = duration;
+	}
+	public String getAddress() {
+		return address;
+	}
+	public void setAddress(String address) {
+		this.address = address;
+	}
+	public String getHash() {
+		return hash;
+	}
+	public void setHash(String hash) {
+		this.hash = hash;
+	}
+	public String getKey() {
+		return key;
+	}
+	public void setKey(String key) {
+		this.key = key;
+	}
+	public String getContentType() {
+		return contentType;
+	}
+	public void setContentType(String contentType) {
+		this.contentType = contentType;
+	}
+	public String getUrl() {
+		return url;
+	}
+	public void setUrl(String url) {
+		this.url = url;
+	}
+	
+	public static QiniuResult forBoject(Response res) throws QiniuException{
+		QiniuResult result=new QiniuResult();
+		result.setAddress(res.address);
+		result.setCode(res.statusCode);
+		result.setContentType(res.contentType());
+		result.setDuration(res.duration);
+		JSONObject json=JSONObject.fromObject(res.bodyString());
+		
+		result.setHash(json.getString("hash"));
+		result.setKey(json.getString("key"));
+		
+		result.setMsg(res.error);
+		//
+		result.setUrl("http://oyeve9iiu.bkt.clouddn.com/"+json.getString("key"));
+		return result;
+	}
+	
+}

+ 121 - 0
src/main/java/com/wxmp/core/util/qiniu/QiniuUtil.java

@@ -0,0 +1,121 @@
+package com.wxmp.core.util.qiniu;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+
+import com.google.gson.Gson;
+import com.qiniu.common.QiniuException;
+import com.qiniu.common.Zone;
+import com.qiniu.http.Response;
+import com.qiniu.storage.Configuration;
+import com.qiniu.storage.UploadManager;
+import com.qiniu.storage.model.DefaultPutRet;
+import com.qiniu.util.Auth;
+
+
+import net.sf.json.JSONObject;
+
+public class QiniuUtil {
+
+	private static Logger logger = Logger.getLogger(QiniuUtil.class);
+	//Zone对象
+	/**
+	 * Zone.zone0() =>华东
+	 * Zone.zone1() =>华北
+	 * Zone.zone2() =>华南
+	 * Zone.zoneNa0() =>北美
+	 */
+	private static Zone zone= Zone.zone1();
+	
+	private static UploadManager uploadManager = new UploadManager(new Configuration(zone));
+	
+	private static String ak="emLrorprCtWbof9kWlr6nD4Vkb_wB934WxqbCDzc";
+	private static String sk="BTnrYlSVC78t38Ivnmf4tIbvLSsbbGEDIc1T2Be";
+	private static String bt="e-smart1";
+	
+	/**
+	 * 
+	*
+	* @Title: uploadByFile 
+	* @Description: TODO 上传文件到七牛 
+	* @param @param file
+	* @param @return    设定文件 
+	* @return QiniuResult    返回类型 
+	* @throws
+	 */
+	public static QiniuResult uploadByFile(File file){
+		
+		
+		try {
+			
+			return uploadByByte(FileUtils.readFileToByteArray(file));
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+	/**
+	 * 
+	*
+	* @Title: uploadByByte 
+	* @Description: TODO 上传数组到七牛
+	* @param @param bte
+	* @param @return    设定文件 
+	* @return QiniuResult    返回类型 
+	* @throws
+	 */
+	public static QiniuResult uploadByByte(byte[] bte){
+		//默认不指定key的情况下,以文件内容的hash值作为文件名
+		String key = null;
+		Auth auth = Auth.create(ak, sk);
+		String upToken = auth.uploadToken(bt);
+		try {
+		    Response response = uploadManager.put(bte, key, upToken);
+		    //解析上传成功的结果
+		    logger.info("qiniu Response body=> "+response.bodyString());
+		    return QiniuResult.forBoject(response);
+		} catch (QiniuException e) {
+			e.getStackTrace();
+			logger.error(e.getMessage(),e);
+		}
+		return null;
+	}
+	/**
+	 * 
+	*
+	* @Title: uploadByInputStream 
+	* @Description: TODO 上传文件流到七牛 
+	* @param @param inp
+	* @param @return    设定文件 
+	* @return QiniuResult    返回类型 
+	* @throws
+	 */
+	public static QiniuResult uploadByInputStream(InputStream inp){
+		
+		//默认不指定key的情况下,以文件内容的hash值作为文件名
+		String key = null;
+		Auth auth = Auth.create(ak, sk);
+		String upToken = auth.uploadToken(bt);
+		try {
+		    Response response = uploadManager.put(inp, key, upToken,null,null);
+		    //解析上传成功的结果
+		    logger.info("qiniu Response body=> "+response.bodyString());
+		    return QiniuResult.forBoject(response);
+		} catch (QiniuException e) {
+			e.getStackTrace();
+			logger.error(e.getMessage(),e);
+		}
+		return null;
+	}
+	public static void main(String[] args) {
+		File file=new File("D:\\test.jpg");
+		System.out.println(JSONObject.fromObject(uploadByFile(file)).toString());
+	}
+	
+}

+ 1 - 1
src/main/java/com/wxmp/core/util/security/RSAKeys.java

@@ -8,7 +8,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
 
-import com.wxmp.backstage.exception.BusinessException;
+import com.wxmp.core.exception.BusinessException;
 import org.apache.log4j.Logger;
 import com.wxmp.core.util.security.RSASignatureTools.KeyStoreFileType;
 /**

+ 1 - 1
src/main/java/com/wxmp/core/util/security/RSASignatureTools.java

@@ -21,7 +21,7 @@ import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 
-import com.wxmp.backstage.exception.UnexpectedException;
+import com.wxmp.core.exception.UnexpectedException;
 import org.apache.commons.codec.binary.Base64;
 
 /**

+ 154 - 0
src/main/java/com/wxmp/core/util/wx/WxUtil.java

@@ -0,0 +1,154 @@
+package com.wxmp.core.util.wx;
+
+import com.wxmp.core.common.Constants;
+import com.wxmp.core.spring.SpringContextHolder;
+import com.wxmp.wxapi.process.MsgType;
+import com.wxmp.wxapi.vo.Matchrule;
+import com.wxmp.wxcms.domain.Account;
+import com.wxmp.wxcms.domain.AccountMenu;
+import com.wxmp.wxcms.domain.MsgNews;
+import com.wxmp.wxcms.domain.MsgText;
+import com.wxmp.wxcms.mapper.MsgNewsDao;
+import com.wxmp.wxcms.mapper.MsgTextDao;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class WxUtil {
+
+	private static MsgTextDao msgTextDao = SpringContextHolder.getBean(MsgTextDao.class);
+
+	private static MsgNewsDao msgNewsDao=SpringContextHolder.getBean(MsgNewsDao.class);
+	/**
+	 * 获取微信公众账号的菜单
+	 * @param menus	菜单列表
+	 * @param matchrule	个性化菜单配置
+	 * @return
+	 */
+	public static JSONObject prepareMenus(List<AccountMenu> menus, Matchrule matchrule) {
+		if(!CollectionUtils.isEmpty(menus)){
+			List<AccountMenu> parentAM = new ArrayList<AccountMenu>();
+			Map<Long,List<JSONObject>> subAm = new HashMap<Long,List<JSONObject>>();
+			for(AccountMenu m : menus){
+				if (m.getParentId().intValue() == 0) {//一级菜单
+					parentAM.add(m);
+				}else{//二级菜单
+					if(subAm.get(m.getParentId()) == null){
+						subAm.put(m.getParentId(), new ArrayList<JSONObject>());
+					}
+					List<JSONObject> tmpMenus = subAm.get(m.getParentId());
+					tmpMenus.add(getMenuJSONObj(m));
+					subAm.put(m.getParentId(), tmpMenus);
+				}
+			}
+			JSONArray arr = new JSONArray();
+			for(AccountMenu m : parentAM){
+				if(subAm.get(m.getId()) != null){//有子菜单
+					arr.add(getParentMenuJSONObj(m,subAm.get(m.getId())));
+				}else{//没有子菜单
+					arr.add(getMenuJSONObj(m));
+				}
+			}
+			JSONObject root = new JSONObject();
+			root.put("button", arr);
+			root.put("matchrule", JSONObject.fromObject(matchrule).toString());
+			//添加消息id
+			root.put("msgs", getMsg());
+			return root;
+		}
+		return null;
+	}
+
+	/**
+	 * 此方法是构建菜单对象的;构建菜单时,对于  key 的值可以任意定义;
+	 * 当用户点击菜单时,会把key传递回来;对已处理就可以了
+	 * @param menu
+	 * @return
+	 */
+	public static JSONObject getMenuJSONObj(AccountMenu menu){
+		JSONObject obj = new JSONObject();
+		obj.put("name", menu.getName());
+		obj.put("type", menu.getMtype());
+		if(Constants.MENU_NEED_KEY.contains(menu.getMtype())){//事件菜单
+			if("fix".equals(menu.getEventType())){//fix 消息
+				obj.put("key", "_fix_" + menu.getMsgId());//以 _fix_ 开头
+			}else{
+				if(StringUtils.isEmpty(menu.getInputCode())){//如果inputcode 为空,默认设置为 subscribe,以免创建菜单失败
+					obj.put("key", "subscribe");
+				}else{
+					obj.put("key", menu.getInputCode());
+				}
+			}
+			//存msgtype id
+			obj.put("msgType", menu.getMsgType());//以 _fix_ 开头
+			obj.put("msgId", menu.getMsgId());//以 _fix_ 开头
+		}else{//链接菜单-view
+			obj.put("url", menu.getUrl());
+		}
+		return obj;
+	}
+
+	public static JSONObject getParentMenuJSONObj(AccountMenu menu,List<JSONObject> subMenu){
+		JSONObject obj = new JSONObject();
+		obj.put("name", menu.getName());
+		obj.put("sub_button", subMenu);
+		return obj;
+	}
+
+    /**
+     * 获取消息
+     * @return
+     */
+	public static JSONArray getMsg(){
+		JSONArray arr = new JSONArray();
+		List<MsgText> msgTextList = msgTextDao.getMsgTextList(new MsgText());
+		List<MsgNews> msgNews = msgNewsDao.listForPage(new MsgNews());
+		if(CollectionUtils.isNotEmpty(msgTextList)){
+			for (MsgText text:msgTextList) {
+				JSONObject obj = new JSONObject();
+				obj.put("id",text.getId());
+				obj.put("title",text.getTitle());
+				obj.put("type", MsgType.Text.toString());
+				arr.add(obj);
+			}
+		}
+		if(CollectionUtils.isNotEmpty(msgNews)){
+			for (MsgNews news:msgNews) {
+				JSONObject obj = new JSONObject();
+				obj.put("id",news.getId());
+				obj.put("title",news.getTitle());
+				obj.put("type", MsgType.News.toString());
+				arr.add(obj);
+			}
+		}
+		return arr;
+	}
+
+    /**
+     * 构造当前菜单数据
+     *
+     * @param list
+     * @return
+     */
+    public static JSONObject getAccount(List<Account> list, String curentName) {
+        JSONObject obj = new JSONObject();
+        obj.put("correct", curentName);
+        JSONArray arr = new JSONArray();
+        if (CollectionUtils.isNotEmpty(list)) {
+            for (Account account : list) {
+                JSONObject objAccount = new JSONObject();
+                objAccount.put("id", account.getId());
+                objAccount.put("name", account.getName());
+                arr.add(objAccount);
+            }
+        }
+        obj.put("list", arr);
+        return obj;
+    }
+}

+ 119 - 165
src/main/java/com/wxmp/wxapi/ctrl/WxApiCtrl.java

@@ -1,56 +1,39 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.ctrl;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.wxmp.core.util.DateUtil;
-import net.sf.json.JSONObject;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.log4j.LogManager;
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.servlet.ModelAndView;
-
-
-import com.wxmp.core.page.Pagination;
+import com.wxmp.core.exception.BusinessException;
 import com.wxmp.core.spring.JsonView;
-import com.wxmp.core.util.DateUtilOld;
+import com.wxmp.core.util.AjaxResult;
+import com.wxmp.core.util.DateUtil;
 import com.wxmp.core.util.UploadUtil;
 import com.wxmp.core.util.wx.SignUtil;
-
-import com.wxmp.wxapi.process.ErrCode;
-import com.wxmp.wxapi.process.MediaType;
-import com.wxmp.wxapi.process.MpAccount;
-import com.wxmp.wxapi.process.MsgType;
-import com.wxmp.wxapi.process.MsgXmlUtil;
-import com.wxmp.wxapi.process.WxApiClient;
-import com.wxmp.wxapi.process.WxMemoryCacheClient;
-import com.wxmp.wxapi.process.WxSign;
-import com.wxmp.wxapi.service.impl.MyServiceImpl;
-import com.wxmp.wxapi.vo.Material;
-import com.wxmp.wxapi.vo.MaterialArticle;
-import com.wxmp.wxapi.vo.MaterialItem;
-import com.wxmp.wxapi.vo.MsgRequest;
-import com.wxmp.wxapi.vo.TemplateMessage;
+import com.wxmp.wxapi.process.*;
+import com.wxmp.wxapi.service.MyService;
+import com.wxmp.wxapi.vo.*;
+import com.wxmp.core.common.BaseCtrl;
 import com.wxmp.wxcms.domain.AccountFans;
 import com.wxmp.wxcms.domain.MsgNews;
 import com.wxmp.wxcms.domain.MsgText;
 import com.wxmp.wxcms.service.MsgNewsService;
 import com.wxmp.wxcms.service.MsgTextService;
+import net.sf.json.JSONObject;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.*;
 
 
 /**
@@ -58,15 +41,15 @@ import com.wxmp.wxcms.service.MsgTextService;
  */
 @Controller
 @RequestMapping("/wxapi")
-public class WxApiCtrl {
+public class WxApiCtrl extends BaseCtrl{
 	
 	private static Logger log = LogManager.getLogger(WxApiCtrl.class);
 	
-	@Autowired
-	private MyServiceImpl myService;
-	@Autowired
+	@Resource
+	private MyService myService;
+	@Resource
 	private MsgTextService msgTextService;
-	@Autowired
+	@Resource
 	private MsgNewsService msgNewsService;
 	
 	/**
@@ -78,7 +61,7 @@ public class WxApiCtrl {
 	@RequestMapping(value = "/{account}/message",  method = RequestMethod.GET)
 	public @ResponseBody String doGet(HttpServletRequest request,@PathVariable String account) {
 		//如果是多账号,根据url中的account参数获取对应的MpAccount处理即可
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		if(mpAccount != null){
 			String token = mpAccount.getToken();//获取token,进行验证;
 			String signature = request.getParameter("signature");// 微信加密签名
@@ -100,7 +83,7 @@ public class WxApiCtrl {
 	@RequestMapping(value = "/{account}/message", method = RequestMethod.POST)
 	public @ResponseBody String doPost(HttpServletRequest request,@PathVariable String account,HttpServletResponse response) {
 		//处理用户和微信公众账号交互消息
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
 		try {
 			MsgRequest msgRequest = MsgXmlUtil.parseXml(request);//获取发送的消息
 			return myService.processMsg(msgRequest,mpAccount);
@@ -112,11 +95,11 @@ public class WxApiCtrl {
 	
 	//创建微信公众账号菜单
 	@RequestMapping(value = "/publishMenu")
-	public ModelAndView publishMenu(HttpServletRequest request,String gid) {
+	public ModelAndView publishMenu() {
 		JSONObject rstObj = null;
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();
 		if(mpAccount != null){
-			rstObj = myService.publishMenu(gid,mpAccount);
+			rstObj = myService.publishMenu(mpAccount);
 			if(rstObj != null){//成功,更新菜单组
 				if(rstObj.containsKey("menu_id")){
 					ModelAndView mv = new ModelAndView("common/success");
@@ -143,7 +126,7 @@ public class WxApiCtrl {
 	@RequestMapping(value = "/deleteMenu")
 	public ModelAndView deleteMenu(HttpServletRequest request) {
 		JSONObject rstObj = null;
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		if(mpAccount != null){
 			rstObj = myService.deleteMenu(mpAccount);
 			if(rstObj != null && rstObj.getInt("errcode") == 0){
@@ -163,48 +146,40 @@ public class WxApiCtrl {
 	
 	//获取用户列表
 	@RequestMapping(value = "/syncAccountFansList")
-	public ModelAndView syncAccountFansList(){
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+	@ResponseBody
+	public AjaxResult syncAccountFansList(){
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		if(mpAccount != null){
 			boolean flag = myService.syncAccountFansList(mpAccount);
 			if(flag){
-				return new ModelAndView("redirect:/accountfans/paginationEntity");
+				return AjaxResult.success();
 			}
 		}
-		ModelAndView mv = new ModelAndView("common/failure");
-		mv.addObject("failureMsg", "获取用户列表失败");
-		return mv;
+		return AjaxResult.failure();
 	}
-	
+
 	//根据用户的ID更新用户信息
 	@RequestMapping(value = "/syncAccountFans")
-	public ModelAndView syncAccountFans(String openId){
-		ModelAndView mv = new ModelAndView("common/failure");
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
-		if(mpAccount != null){
-			AccountFans fans = myService.syncAccountFans(openId,mpAccount,true);//同时更新数据库
-			if(fans != null){
-				mv.setViewName("wxcms/fansInfo");
-				mv.addObject("fans", fans);
-				mv.addObject("cur_nav","fans");
-				return mv;
+	@ResponseBody
+	public AjaxResult syncAccountFans(String openId) {
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
+		if (mpAccount != null) {
+			AccountFans fans = myService.syncAccountFans(openId, mpAccount, true);//同时更新数据库
+			if (fans != null) {
+				return AjaxResult.success(fans);
 			}
 		}
-		mv.addObject("failureMsg", "获取用户信息失败,公众号信息或openid信息错误");
-		return mv;
+		return AjaxResult.failure();
 	}
 	
 	//获取永久素材
 	@RequestMapping(value = "/syncMaterials")
-	public  ModelAndView syncMaterials(Pagination<MaterialArticle> pagination){
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
-		
-		ModelAndView mv = new ModelAndView("wxcms/materialPagination");
-		Integer offset = pagination.getStart();
-		Integer count = pagination.getPageSize();
-		Material material = WxApiClient.syncBatchMaterial(MediaType.News, offset, count,mpAccount);
+	public AjaxResult syncMaterials(MaterialArticle materialArticle) throws BusinessException {
+		List<MaterialArticle> materialList = new ArrayList<MaterialArticle>();
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
+		Material material = WxApiClient.syncBatchMaterial(MediaType.News, materialArticle.getPage(), materialArticle.getPageSize(),mpAccount);
 		if(material != null){
-			List<MaterialArticle> materialList = new ArrayList<MaterialArticle>();
+
 			List<MaterialItem> itemList = material.getItems();
 			if(itemList != null){
 				for(MaterialItem item : itemList){
@@ -218,19 +193,15 @@ public class WxApiCtrl {
 					materialList.add(m);
 				}
 			}
-			pagination.setTotalItemsCount(material.getTotalCount());
-			pagination.setItems(materialList);
 		}
-		mv.addObject("page",pagination);
-		mv.addObject("cur_nav", "material");
-		return mv;
+		return getResult(materialArticle,materialList);
 	}
 	
 	
 	//上传图文素材
 	@RequestMapping(value = "/doUploadMaterial")
 	public  ModelAndView doUploadMaterial(MsgNews msgNews){
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		String rstMsg = "上传图文消息素材";
 		List<MsgNews> msgNewsList = new ArrayList<MsgNews>();
 		msgNewsList.add(msgNews);
@@ -251,7 +222,7 @@ public class WxApiCtrl {
 	@RequestMapping(value = "/oauthOpenid.html")
 	public ModelAndView oauthOpenid(HttpServletRequest request){
 		log.info("-------------------------------------oauthOpenid-----<0>-------------------");
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		log.info("-------------------------------------oauthOpenid-----<1>-------------------mpAccount:"+mpAccount.getAccount());
 		if(mpAccount != null){
 			ModelAndView mv = new ModelAndView("wxweb/oauthopenid");
@@ -281,7 +252,7 @@ public class WxApiCtrl {
 	public ModelAndView createQrcode(HttpServletRequest request,Integer num){
 		ModelAndView mv = new ModelAndView("wxcms/qrcode");
 		mv.addObject("cur_nav", "qrcode");
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		if(num != null){
 			byte[] qrcode = WxApiClient.createQRCode(60,num,mpAccount);//有效期60s
 			String url = UploadUtil.byteToImg(request.getServletContext().getRealPath("/"), qrcode);
@@ -295,7 +266,7 @@ public class WxApiCtrl {
 	@RequestMapping(value = "/massSendTextMsg", method = RequestMethod.POST)
 	public void massSendTextMsg(HttpServletResponse response,String openid,String content){
 		content = "群发文本消息";
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		String rstMsg = "根据openid群发文本消息失败";
 		if(mpAccount != null && !StringUtils.isBlank(openid)){
 			List<String> openidList = new ArrayList<String>();
@@ -319,13 +290,12 @@ public class WxApiCtrl {
 	
 	/**
 	 * 发送客服消息
-	 * @param openId : 粉丝的openid
-	 * @param content : 消息内容
+	 * @param openid : 粉丝的openid
 	 * @return
 	 */
 	@RequestMapping(value = "/sendCustomTextMsg", method = RequestMethod.POST)
 	public void sendCustomTextMsg(HttpServletRequest request,HttpServletResponse response,String openid){
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		String content = "微信派官方测试客服消息";
 		JSONObject result = WxApiClient.sendCustomTextMessage(openid, content, mpAccount);
 		try {
@@ -341,13 +311,12 @@ public class WxApiCtrl {
 	
 	/**
 	 * 发送模板消息
-	 * @param openId
-	 * @param content
+	 * @param openid
 	 * @return
 	 */
 	@RequestMapping(value = "/sendTemplateMessage", method = RequestMethod.POST)
 	public void sendTemplateMessage(HttpServletRequest request,HttpServletResponse response,String openid){
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		TemplateMessage tplMsg = new TemplateMessage();
 		
 		tplMsg.setOpenid(openid);
@@ -383,7 +352,7 @@ public class WxApiCtrl {
 	@RequestMapping(value = "/jsTicket")
 	@ResponseBody
 	public String jsTicket(HttpServletRequest request, String url) {
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		String jsTicket = WxApiClient.getJSTicket(mpAccount);
 		WxSign sign = new WxSign(mpAccount.getAppid(),jsTicket,url);//sha1签名得到signature
 		
@@ -414,7 +383,7 @@ public class WxApiCtrl {
 		log.info("-------------------------------------jsPay-----<1>-------------------timestamp:"+timestamp);	
 		//String openid = WxMemoryCacheClient.getOpenid(request.getSession().getId());//先从缓存中获取openid
 		
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		log.info("-------------------------------------jsPay-----<2>-------------------mpAccount:"+mpAccount.getAppid());		
 		
 	/*	      timestamp: 1414723227,
@@ -431,8 +400,7 @@ public class WxApiCtrl {
 
 	/**
 	 * 微信异步返回
-	 * @param request
-	 * @param url 
+	 * @param requestBodyXml
 	 * @return
 	 */
 	@RequestMapping(value = "/wxipay_noity")
@@ -496,53 +464,46 @@ public class WxApiCtrl {
      */
 	@RequestMapping(value = "/sendTextMsgByOpenId", method = RequestMethod.POST)
 	@ResponseBody
-	public String sendTextMsgByOpenId(String msgId,String openid){
-		String code = "0";
+	public AjaxResult sendTextMsgByOpenId(String msgId, String openid) {
 		MsgText msgText = msgTextService.getById(msgId);
 		String content = msgText.getContent();
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		JSONObject result = WxApiClient.sendCustomTextMessage(openid, content, mpAccount);
-		
-		if(result.getInt("errcode") != 0){
-			//code = "-1";//发送失败
-			code = result.toString();
-		}else{
-			code = "1";//发送成功
+
+		if (result.getInt("errcode") != 0) {
+			return AjaxResult.failure(result.toString());
+		} else {
+			return AjaxResult.success();
 		}
-		
-		return code;
-	}	
+	}
 
-    /**
-     * 客服接口-发送图文消息
-     * @param msgId
-     * @param openid
-     * @return
-     */
+	/**
+	 * 客服接口-发送图文消息
+	 *
+	 * @param msgId
+	 * @param openid
+	 * @return
+	 */
 	@RequestMapping(value = "/sendNewsByOpenId", method = RequestMethod.POST)
 	@ResponseBody
-	public String sendNewsByOpenId(String msgId,String openid){
-		String code = "0";
-		List<MsgNews> msgNewsList = this.msgNewsService.getByMediaId(msgId);
+	public AjaxResult sendNewsByOpenId(String id, String openid) {
 		
-		MsgNews msgNews = (MsgNews)msgNewsList.get(0);
+		MsgNews msgNews  = this.msgNewsService.getById(id);
 
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
-		JSONObject result = WxApiClient.sendCustomNews(openid,msgNews,mpAccount);
-		log.info(" 客服接口-发送图文消息:"+result.toString());
-		if(result.getInt("errcode") != 0){
-			code = result.toString();//发送失败
-		}else{
-			code = "1";//发送成功
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
+		JSONObject result = WxApiClient.sendCustomNews(openid, msgNews, mpAccount);
+		log.info(" 客服接口-发送图文消息:" + result.toString());
+		if (result.getInt("errcode") != 0) {
+			return AjaxResult.failure(result.toString());
+		} else {
+			return AjaxResult.success();
 		}
-		
-		return code;
-	}	
+	}
 	
     /**
      * 客服接口 -批量发送文本消息
-     * @param msgId
-     * @param openid
+     * @param textId
+     * @param openIds
      * @return
      */
 	@RequestMapping(value = "/batchSendText", method = RequestMethod.POST)
@@ -558,7 +519,7 @@ public class WxApiCtrl {
 		}
 		String content = msgText.getContent();
 		
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		
 		for(int i = 0; i<openIdAarry.length; i++){
 			String openid = openIdAarry[i];
@@ -570,8 +531,8 @@ public class WxApiCtrl {
 	
 	/**
      * 群发-文本消息
-     * @param msgId
-     * @param openid
+     * @param textId
+     * @param openIds
      * @return
      */
 	@RequestMapping(value = "/massSendTextByOpenIds", method = RequestMethod.POST)
@@ -584,7 +545,7 @@ public class WxApiCtrl {
 
 		String content = msgText.getContent();
 		
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		//openids
 		List<String> openidList = new ArrayList<String>();
 		for(int i = 0; i<openIdAarry.length; i++){
@@ -615,7 +576,7 @@ public class WxApiCtrl {
 		
 		List<MsgNews> msgNewsList = new ArrayList<MsgNews>();
 		msgNewsList.add(msgNews);
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		//先上传图文素材
 		//JSONObject newsObject = WxApiClient.uploadNews(msgNewsList, mpAccount);
 		//媒体id
@@ -642,7 +603,7 @@ public class WxApiCtrl {
 	
 	/**
 	 * 高级群发-图文消息|
-	 * @param newsId
+	 * @param mediaId
 	 * @param openIds
 	 * @return
 	 */
@@ -650,7 +611,7 @@ public class WxApiCtrl {
 	@ResponseBody
 	public String sendMaterialByOpenIds(String mediaId,String openIds){
 		String code = "";
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		//分隔字符串
 		String[] openIdAarry = openIds.split(",");
 		//openids
@@ -672,34 +633,27 @@ public class WxApiCtrl {
 	//创建微信公众账号菜单
 	@RequestMapping(value = "/doPublishMenu")
 	@ResponseBody
-	public String doPublishMenu(HttpServletRequest request,String gid) {
-		String code="";
+	public AjaxResult doPublishMenu() {
 		JSONObject rstObj = null;
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();
 		if(mpAccount != null){
-			rstObj = myService.publishMenu(gid,mpAccount);
+			rstObj = myService.publishMenu(mpAccount);
 			if(rstObj != null){//成功,更新菜单组
-				if(rstObj.containsKey("menu_id")){
-					ModelAndView mv = new ModelAndView("common/success");
-					mv.addObject("successMsg", "创建菜单成功");
-					code = "1";
-					return code;
-				}else if(rstObj.containsKey("errcode") && rstObj.getInt("errcode") == 0){
-					ModelAndView mv = new ModelAndView("common/success");
-					mv.addObject("successMsg", "创建菜单成功");
-					code = "1";
-					return code;
-				}
+				return AjaxResult.success();
+//				if(rstObj.containsKey("menu_id")){
+//					ModelAndView mv = new ModelAndView("common/success");
+//					mv.addObject("successMsg", "创建菜单成功");
+//					code = "1";
+//					return code;
+//				}else if(rstObj.containsKey("errcode") && rstObj.getInt("errcode") == 0){
+//					ModelAndView mv = new ModelAndView("common/success");
+//					mv.addObject("successMsg", "创建菜单成功");
+//					code = "1";
+//					return code;
+//				}
 			}
 		}
-		
-		String failureMsg = "创建菜单失败,请检查菜单:可创建最多3个一级菜单,每个一级菜单下可创建最多5个二级菜单。";
-		if(rstObj != null){
-			failureMsg += ErrCode.errMsg(rstObj.getInt("errcode"));
-		}
-		
-		code = failureMsg;
-		return code;
+		return AjaxResult.failure();
 	}
 	
 	
@@ -709,7 +663,7 @@ public class WxApiCtrl {
 	public String deletePublicMenu(HttpServletRequest request) {
 		String code = "";
 		JSONObject rstObj = null;
-		MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 		if(mpAccount != null){
 			rstObj = myService.deleteMenu(mpAccount);
 			if(rstObj != null && rstObj.getInt("errcode") == 0){

+ 6 - 0
src/main/java/com/wxmp/wxapi/interceptor/OAuth2RequestParamHelper.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.interceptor;
 
 import java.util.HashMap;

+ 8 - 2
src/main/java/com/wxmp/wxapi/interceptor/WxOAuth2Interceptor.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.interceptor;
 
 import javax.servlet.http.HttpServletRequest;
@@ -58,7 +64,7 @@ public class WxOAuth2Interceptor extends HandlerInterceptorAdapter {
 			if(!StringUtils.isBlank(code)){//如果request中包括code,则是微信回调
 				log.info("-------------------------------------preHandle-----<2-2>-------------------code:"+code);		
 				try {
-					openid = WxApiClient.getOAuthOpenId(WxMemoryCacheClient.getSingleMpAccount(), code);
+					openid = WxApiClient.getOAuthOpenId(WxMemoryCacheClient.getMpAccount(), code);
 					log.info("-------------------------------------preHandle-----<2-3>-------------------openid:"+openid);	
 					if(!StringUtils.isBlank(openid)){
 						WxMemoryCacheClient.setOpenid(sessionid, openid);//缓存openid
@@ -69,7 +75,7 @@ public class WxOAuth2Interceptor extends HandlerInterceptorAdapter {
 				}
 			}else{//oauth获取code
 
-				MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
+				MpAccount mpAccount = WxMemoryCacheClient.getMpAccount();//获取缓存中的唯一账号
 				log.info("-------------------------------------preHandle-----<3-1>-------------------mpAccount:"+mpAccount.getAccount());	
 				String redirectUrl = HttpUtil.getRequestFullUriNoContextPath(request);//请求code的回调url
 				if(!HttpUtil.existHttpPath(redirectUrl)){

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/AccessToken.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 import java.io.Serializable;

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/ErrCode.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 import java.util.HashMap;

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/HttpMethod.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 /**

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/JSTicket.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 import java.io.Serializable;

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/MediaType.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 /**

+ 11 - 37
src/main/java/com/wxmp/wxapi/process/MpAccount.java

@@ -1,10 +1,19 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
+import lombok.Data;
+
 import java.io.Serializable;
 
 /**
  * 微信公众号信息
  */
+@Data
 public class MpAccount implements Serializable{
 	private static final long serialVersionUID = -6315146640254918207L;
 	
@@ -13,48 +22,13 @@ public class MpAccount implements Serializable{
 	private String appsecret;//appsecret
 	private String url;//验证时用的url
 	private String token;//token
-	
 	//ext
 	private Integer msgcount;//自动回复消息条数;默认是5条
-	
-	
-	public String getAccount() {
-		return account;
-	}
-	public void setAccount(String account) {
-		this.account = account;
-	}
-	public String getAppid() {
-		return appid;
-	}
-	public void setAppid(String appid) {
-		this.appid = appid;
-	}
-	public String getAppsecret() {
-		return appsecret;
-	}
-	public void setAppsecret(String appsecret) {
-		this.appsecret = appsecret;
-	}
-	public String getUrl() {
-		return url;
-	}
-	public void setUrl(String url) {
-		this.url = url;
-	}
-	public String getToken() {
-		return token;
-	}
-	public void setToken(String token) {
-		this.token = token;
-	}
+
 	public Integer getMsgcount() {
 		if(msgcount == null)
 			msgcount = 5;//默认5条
 		return msgcount;
 	}
-	public void setMsgcount(Integer msgcount) {
-		this.msgcount = msgcount;
-	}
-	
+
 }

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/MsgType.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 /**

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/MsgXmlUtil.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 import java.io.InputStream;

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/OAuthAccessToken.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 import org.apache.commons.lang3.builder.ToStringBuilder;

+ 6 - 0
src/main/java/com/wxmp/wxapi/process/OAuthScope.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 /**

+ 7 - 1
src/main/java/com/wxmp/wxapi/process/WxApi.java

@@ -1,6 +1,12 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
-import com.wxmp.backstage.common.Identities;
+import com.wxmp.core.common.Identities;
 import com.wxmp.core.util.MyTrustManager;
 import net.sf.json.JSONException;
 import net.sf.json.JSONObject;

+ 59 - 28
src/main/java/com/wxmp/wxapi/process/WxApiClient.java

@@ -1,11 +1,19 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
-import com.wxmp.backstage.common.Identities;
+import com.wxmp.core.common.Identities;
+import com.wxmp.core.util.DateUtil;
 import com.wxmp.wxapi.vo.Material;
 import com.wxmp.wxapi.vo.MaterialArticle;
 import com.wxmp.wxapi.vo.MaterialItem;
 import com.wxmp.wxapi.vo.TemplateMessage;
 import com.wxmp.wxcms.domain.AccountFans;
+import com.wxmp.wxcms.domain.MsgArticle;
 import com.wxmp.wxcms.domain.MsgNews;
 import net.sf.json.JSONArray;
 import net.sf.json.JSONObject;
@@ -27,7 +35,7 @@ public class WxApiClient {
 	//获取accessToken
 	public static String getAccessToken(MpAccount mpAccount){
 		//获取唯一的accessToken,如果是多账号,请自行处理
-		AccessToken token = WxMemoryCacheClient.getSingleAccessToken();
+		AccessToken token = WxMemoryCacheClient.getAccessToken();
 		if(token != null && !token.isExpires()&& WxApi.getCallbackIp(token.getAccessToken())){//不为空,并且没有过期
 			logger.info("服务器缓存 accessToken == " + token.toString());
 			return token.getAccessToken();
@@ -49,7 +57,7 @@ public class WxApiClient {
 	//获取jsTicket
 	public static String getJSTicket(MpAccount mpAccount){
 		//获取唯一的JSTicket,如果是多账号,请自行处理
-		JSTicket jsTicket = WxMemoryCacheClient.getSingleJSTicket();
+		JSTicket jsTicket = WxMemoryCacheClient.getJSTicket();
 		if(jsTicket != null && !jsTicket.isExpires()){//不为空,并且没有过期
 			return jsTicket.getTicket();
 		}else{
@@ -70,7 +78,7 @@ public class WxApiClient {
 	//获取OAuthAccessToken
 	public static OAuthAccessToken getOAuthAccessToken(MpAccount mpAccount,String code){
 		//获取唯一的accessToken,如果是多账号,请自行处理
-		OAuthAccessToken token = WxMemoryCacheClient.getSingleOAuthAccessToken();
+		OAuthAccessToken token = WxMemoryCacheClient.getOAuthAccessToken();
 		if(token != null && !token.isExpires()){//不为空,并且没有过期
 			return token;
 		}else{
@@ -140,7 +148,7 @@ public class WxApiClient {
 				fans.setOpenId(jsonObj.getString("openid"));// 用户的标识
 				fans.setSubscribeStatus(new Integer(jsonObj.getInt("subscribe")));// 关注状态(1是关注,0是未关注),未关注时获取不到其余信息
 				if(jsonObj.containsKey("subscribe_time")){
-					fans.setSubscribeTime(jsonObj.getString("subscribe_time"));// 用户关注时间
+					fans.setSubscribeTime(DateUtil.timestampToDate(jsonObj.getString("subscribe_time")));// 用户关注时间
 				}
 				if(jsonObj.containsKey("nickname")){// 昵称
 					try {
@@ -172,7 +180,7 @@ public class WxApiClient {
 					fans.setRemark(jsonObj.getString("remark"));
 				}
 				fans.setStatus(1);
-				fans.setCreatetime(new Date());
+				fans.setCreateTime(new Date());
 				return fans;
 			}
 		}
@@ -219,7 +227,7 @@ public class WxApiClient {
 								MaterialArticle ma = new MaterialArticle();
 								ma.setTitle(article.getString("title"));
 								ma.setThumb_media_id(article.getString("thumb_media_id"));
-								ma.setShow_cover_pic(article.getString("show_cover_pic"));
+								ma.setShow_cover_pic(article.getInt("show_cover_pic"));
 								ma.setAuthor(article.getString("author"));
 								ma.setContent_source_url(article.getString("content_source_url"));
 								ma.setContent(article.getString("content"));
@@ -277,7 +285,7 @@ public class WxApiClient {
 				if(news.getShowpic() != null){
 					jsonObj.put("show_cover_pic", news.getShowpic());
 				}else{
-					jsonObj.put("show_cover_pic", "1");
+					jsonObj.put("show_cover_pic", 1);
 				}
 				jsonObj.put("content", news.getDescription());
 				jsonArr.add(jsonObj);
@@ -446,13 +454,13 @@ public class WxApiClient {
 	}
 		
 	//上传永久图片
-	public static JSONObject uploadMaterialImg(File file,MpAccount mpAccount){
+	public static JSONObject uploadMaterialImg(String filePath,MpAccount mpAccount){
 		JSONObject rstObj = new JSONObject();
 		String accessToken = getAccessToken(mpAccount);
 		try{
-			JSONObject postObj = new JSONObject();
+//			JSONObject postObj = new JSONObject();
 			//postObj.put("media", file);
-			String filePath = "D:/img/Tulips.jpg";
+//			String filePath = file.getAbsolutePath();
 			//上传永久图片素材
 			rstObj = WxApi.addMaterial(WxApi.getMaterialImgUrl(accessToken), filePath);
 		}catch(Exception e){
@@ -501,13 +509,12 @@ public class WxApiClient {
 	 * @param mpAccount
 	 * @return
 	 */
-	public static JSONObject deleteMaterial(String media_id, MpAccount mpAccount){
-			JSONObject postObj = new JSONObject();
-			postObj.put("media_id", media_id);
-			String accessToken = getAccessToken(mpAccount);
-			return WxApi.httpsRequest(WxApi.getDelMaterialURL(accessToken),
-					HttpMethod.POST, postObj.toString());
-	}
+    public static JSONObject deleteMaterial(String media_id, MpAccount mpAccount) {
+        JSONObject postObj = new JSONObject();
+        postObj.put("media_id", media_id);
+        String accessToken = getAccessToken(mpAccount);
+        return WxApi.httpsRequest(WxApi.getDelMaterialURL(accessToken), HttpMethod.POST, postObj.toString());
+    }
 	
 	//新增永久图文素材
 	public static JSONObject addNewsMaterial(List<MsgNews> msgNewsList,String mediaId,MpAccount mpAccount){
@@ -542,7 +549,7 @@ public class WxApiClient {
 				if(news.getShowpic() != null){
 					jsonObj.put("show_cover_pic", news.getShowpic());
 				}else{
-					jsonObj.put("show_cover_pic", "1");
+					jsonObj.put("show_cover_pic", 1);
 				}
 				jsonObj.put("content", news.getDescription());
 				jsonArr.add(jsonObj);
@@ -563,12 +570,9 @@ public class WxApiClient {
 			JSONObject rstObj = new JSONObject();
 			String accessToken = getAccessToken(mpAccount);
 			try{
-				//JSONArray jsonArr = new JSONArray();
-				JSONObject newJsonObj = new JSONObject();
-				MsgNews news = (MsgNews)msgNewsList.get(0);
+				MsgNews news =msgNewsList.get(0);
 				JSONObject jsonObj = new JSONObject();
 				
-					
 					//上传图片素材
 					jsonObj.put("thumb_media_id", news.getThumbMediaId());
 					if(news.getAuthor() != null){
@@ -594,11 +598,9 @@ public class WxApiClient {
 					if(news.getShowpic() != null){
 						jsonObj.put("show_cover_pic", news.getShowpic());
 					}else{
-						jsonObj.put("show_cover_pic", "1");
+						jsonObj.put("show_cover_pic", 1);
 					}
 					jsonObj.put("content", news.getDescription());
-					//jsonArr.add(jsonObj);
-			
 			
 				JSONObject postObj = new JSONObject();
 				postObj.put("media_id", mediaId);
@@ -612,7 +614,23 @@ public class WxApiClient {
 			}
 			return rstObj;
 	}
-	
+	public static JSONObject updateNewsMaterial2(JSONObject jsonObj,int index,
+			String mediaId,MpAccount mpAccount){
+			JSONObject rstObj = new JSONObject();
+			String accessToken = getAccessToken(mpAccount);
+			try{
+				JSONObject postObj = new JSONObject();
+				postObj.put("media_id", mediaId);
+				postObj.put("index", index);
+				postObj.put("articles", jsonObj);
+				rstObj = WxApi.httpsRequest(WxApi.getUpdateNewsMaterialUrl(accessToken),
+						
+						HttpMethod.POST, postObj.toString());
+			}catch(Exception e){
+				e.printStackTrace();
+			}
+			return rstObj;
+	}
 	
 	
 	//新增多图文永久素材
@@ -648,7 +666,7 @@ public class WxApiClient {
 				if(news.getShowpic() != null){
 					jsonObj.put("show_cover_pic", news.getShowpic());
 				}else{
-					jsonObj.put("show_cover_pic", "1");
+					jsonObj.put("show_cover_pic", 1);
 				}
 				jsonObj.put("content", news.getDescription());
 				jsonArr.add(jsonObj);
@@ -661,6 +679,19 @@ public class WxApiClient {
 		}
 		return rstObj;
 	}
+	//新增多图文永久素材
+	public static JSONObject addMoreNewsMaterial2(JSONArray arryarticles,MpAccount mpAccount){
+		JSONObject rstObj = new JSONObject();
+		String accessToken = getAccessToken(mpAccount);
+		try{
+			JSONObject postObj = new JSONObject();
+			postObj.put("articles", arryarticles);
+			rstObj = WxApi.httpsRequest(WxApi.getNewsMaterialUrl(accessToken), HttpMethod.POST, postObj.toString());
+		}catch(Exception e){
+			e.printStackTrace();
+		}
+		return rstObj;
+	}
 	
 	/**
 	 * 发送客服消息

+ 114 - 90
src/main/java/com/wxmp/wxapi/process/WxMemoryCacheClient.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 import java.util.Map;
@@ -11,17 +17,17 @@ import com.wxmp.core.util.CacheUtils;
 /**
  * 缓存工具类;
  * 目前使用 服务器内存的方式;
- * 
+ *
  * 1、开发者可以根据自己的需求使用不同的缓存方式,比如memcached
  * 2、系统默认使用单个公众账号的缓存处理,如果有多个账号,请开发者自行处理
- * 
+ *
  */
 public class WxMemoryCacheClient {
-	
-	
+
+
 	private static Logger log = LogManager.getLogger(WxMemoryCacheClient.class);
-	
-	
+	public static final String SESSION_ACCOUNT= "session_account";
+
 	public static void addMpAccount(MpAccount account){
 		Map<String,MpAccount> mpAccountMap = (Map<String, MpAccount>) CacheUtils.get("mpAccountMap");
 		if(mpAccountMap==null){
@@ -30,28 +36,34 @@ public class WxMemoryCacheClient {
 		if(account != null){
 			mpAccountMap.put(account.getAccount(), account);
 			CacheUtils.put("mpAccountMap", mpAccountMap);
+			setAccount(account.getAccount());
 		}
 	}
-//	
-	public static MpAccount getMpAccount(String account){
+//
+	public static MpAccount getMpAccount(){
 		Map<String,MpAccount> mpAccountMap = (Map<String, MpAccount>) CacheUtils.get("mpAccountMap");
-		return mpAccountMap.get(account);
+		return mpAccountMap.get(getAccount());
 	}
-	
-	//获取唯一的公众号,如果需要多账号,请自行处理
-	public static MpAccount getSingleMpAccount(){
+
+	public static MpAccount getMpAccount(String accout){
 		Map<String,MpAccount> mpAccountMap = (Map<String, MpAccount>) CacheUtils.get("mpAccountMap");
-		if(mpAccountMap==null){
-			mpAccountMap=Maps.newHashMap();
-		}
-		MpAccount sigleAccount = null;
-		for(String key : mpAccountMap.keySet()){
-			sigleAccount = mpAccountMap.get(key);
-			break;
-		}
-		return sigleAccount;
+		return mpAccountMap.get(accout);
 	}
-	
+
+//	//获取唯一的公众号,如果需要多账号,请自行处理
+//	public static MpAccount getSingleMpAccount(){
+//		Map<String,MpAccount> mpAccountMap = (Map<String, MpAccount>) CacheUtils.get("mpAccountMap");
+//		if(mpAccountMap==null){
+//			mpAccountMap=Maps.newHashMap();
+//		}
+//		MpAccount sigleAccount = null;
+//		for(String key : mpAccountMap.keySet()){
+//			sigleAccount = mpAccountMap.get(key);
+//			break;
+//		}
+//		return sigleAccount;
+//	}
+
 	public static AccessToken addAccessToken(String account ,AccessToken token){
 		Map<String,AccessToken> accountAccessTokenMap = (Map<String, AccessToken>) CacheUtils.get("accountAccessTokenMap");
 		if(accountAccessTokenMap==null){
@@ -66,38 +78,37 @@ public class WxMemoryCacheClient {
 		CacheUtils.put("accountAccessTokenMap", accountAccessTokenMap);
 		return token;
 	}
-	
-	/**
-	 * accessToken的获取,绝对不要从缓存中直接获取,请从WxApiClient中获取;
-	 * @param account
-	 * @return
-	 */
-	public static AccessToken getAccessToken(String account){
-		Map<String,AccessToken> accountAccessTokenMap = (Map<String, AccessToken>) CacheUtils.get("accountAccessTokenMap");
-		if(accountAccessTokenMap==null){
-			accountAccessTokenMap=Maps.newHashMap();
-		}
-		return accountAccessTokenMap.get(account);
-	}
-	
+
 	/**
-	 * 获取唯一的公众号的accessToken,如果需要多账号,请自行处理
 	 * accessToken的获取,绝对不要从缓存中直接获取,请从WxApiClient中获取;
 	 * @return
 	 */
-	public static AccessToken getSingleAccessToken(){
+	public static AccessToken getAccessToken(){
 		Map<String,AccessToken> accountAccessTokenMap = (Map<String, AccessToken>) CacheUtils.get("accountAccessTokenMap");
 		if(accountAccessTokenMap==null){
 			accountAccessTokenMap=Maps.newHashMap();
 		}
-		AccessToken accessToken = null;
-		for(String key : accountAccessTokenMap.keySet()){
-			accessToken = accountAccessTokenMap.get(key);
-			break;
-		}
-		return accessToken;
+		return accountAccessTokenMap.get(getAccount());
 	}
-	
+
+//	/**
+//	 * 获取唯一的公众号的accessToken,如果需要多账号,请自行处理
+//	 * accessToken的获取,绝对不要从缓存中直接获取,请从WxApiClient中获取;
+//	 * @return
+//	 */
+//	public static AccessToken getSingleAccessToken(){
+//		Map<String,AccessToken> accountAccessTokenMap = (Map<String, AccessToken>) CacheUtils.get("accountAccessTokenMap");
+//		if(accountAccessTokenMap==null){
+//			accountAccessTokenMap=Maps.newHashMap();
+//		}
+//		AccessToken accessToken = null;
+//		for(String key : accountAccessTokenMap.keySet()){
+//			accessToken = accountAccessTokenMap.get(key);
+//			break;
+//		}
+//		return accessToken;
+//	}
+
 	/**
 	 * 添加JSTicket到缓存
 	 * @param account
@@ -115,39 +126,38 @@ public class WxMemoryCacheClient {
 		CacheUtils.put("accountJSTicketMap", accountJSTicketMap);
 		return jsTicket;
 	}
-	
+
 	/**
 	 * JSTicket的获取,绝对不要从缓存中直接获取,请从JSTicket中获取;
-	 * @param account
 	 * @return
 	 */
-	public static JSTicket getJSTicket(String account){
+	public static JSTicket getJSTicket(){
 		Map<String,JSTicket> accountJSTicketMap = (Map<String, JSTicket>) CacheUtils.get("accountJSTicketMap");
 		if(null==accountJSTicketMap){
 			accountJSTicketMap=Maps.newHashMap();
 		}
-		return accountJSTicketMap.get(account);
+		return accountJSTicketMap.get(getAccount());
 	}
-	
-	/**
-	 * 获取唯一的公众号的JSTicket,如果需要多账号,请自行处理
-	 * JSTicket的获取,绝对不要从缓存中直接获取,请从WxApiClient中获取;
-	 * @return
-	 */
-	public static JSTicket getSingleJSTicket(){
-		Map<String,JSTicket> accountJSTicketMap = (Map<String, JSTicket>) CacheUtils.get("accountJSTicketMap");
-		if(null==accountJSTicketMap){
-			accountJSTicketMap=Maps.newHashMap();
-		}
-		JSTicket jsTicket = null;
-		for(String key : accountJSTicketMap.keySet()){
-			jsTicket = accountJSTicketMap.get(key);
-			break;
-		}
-		return jsTicket;
-	}
-	
-	
+
+//	/**
+//	 * 获取唯一的公众号的JSTicket,如果需要多账号,请自行处理
+//	 * JSTicket的获取,绝对不要从缓存中直接获取,请从WxApiClient中获取;
+//	 * @return
+//	 */
+//	public static JSTicket getSingleJSTicket(){
+//		Map<String,JSTicket> accountJSTicketMap = (Map<String, JSTicket>) CacheUtils.get("accountJSTicketMap");
+//		if(null==accountJSTicketMap){
+//			accountJSTicketMap=Maps.newHashMap();
+//		}
+//		JSTicket jsTicket = null;
+//		for(String key : accountJSTicketMap.keySet()){
+//			jsTicket = accountJSTicketMap.get(key);
+//			break;
+//		}
+//		return jsTicket;
+//	}
+
+
 	//处理openid缓存
 	public static String getOpenid(String sessionid){
 		Map<String,String> sessionOpenIdMap = (Map<String,String>) CacheUtils.get("sessionOpenIdMap");
@@ -159,7 +169,7 @@ public class WxMemoryCacheClient {
 		}
 		return null;
 	}
-	
+
 	public static String setOpenid(String sessionid, String openid){
 		Map<String,String> sessionOpenIdMap = (Map<String,String>) CacheUtils.get("sessionOpenIdMap");
 		if(null==sessionOpenIdMap){
@@ -171,7 +181,7 @@ public class WxMemoryCacheClient {
 		CacheUtils.put("sessionOpenIdMap", sessionOpenIdMap);
 		return openid;
 	}
-	
+
 	//处理OAuth的Token
 	public static AccessToken addOAuthAccessToken(String account ,OAuthAccessToken token){
 		Map<String,OAuthAccessToken> accountOAuthTokenMap = (Map<String, OAuthAccessToken>) CacheUtils.get("accountOAuthTokenMap");
@@ -184,36 +194,50 @@ public class WxMemoryCacheClient {
 		CacheUtils.put("accountOAuthTokenMap", accountOAuthTokenMap);
 		return token;
 	}
-	
+
 	/**
 	 * OAuthAccessToken的获取,绝对不要从缓存中直接获取,请从WxApiClient中获取;
-	 * @param account
 	 * @return
 	 */
-	public static OAuthAccessToken getOAuthAccessToken(String account){
+	public static OAuthAccessToken getOAuthAccessToken(){
 		Map<String,OAuthAccessToken> accountOAuthTokenMap = (Map<String, OAuthAccessToken>) CacheUtils.get("accountOAuthTokenMap");
 		if(null==accountOAuthTokenMap){
 			accountOAuthTokenMap=Maps.newHashMap();
 		}
-		return accountOAuthTokenMap.get(account);
+		return accountOAuthTokenMap.get(getAccount());
 	}
-	
+
+//	/**
+//	 * 获取唯一的公众号的accessToken,如果需要多账号,请自行处理
+//	 * OAuthAccessToken的获取,绝对不要从缓存中直接获取,请从WxApiClient中获取;
+//	 * @return
+//	 */
+//	public static OAuthAccessToken getSingleOAuthAccessToken(){
+//		Map<String,OAuthAccessToken> accountOAuthTokenMap = (Map<String, OAuthAccessToken>) CacheUtils.get("accountOAuthTokenMap");
+//		if(null==accountOAuthTokenMap){
+//			accountOAuthTokenMap=Maps.newHashMap();
+//		}
+//		OAuthAccessToken token = null;
+//		for(String key : accountOAuthTokenMap.keySet()){
+//			token = accountOAuthTokenMap.get(key);
+//			break;
+//		}
+//		return token;
+//	}
+
 	/**
-	 * 获取唯一的公众号的accessToken,如果需要多账号,请自行处理
-	 * OAuthAccessToken的获取,绝对不要从缓存中直接获取,请从WxApiClient中获取;
-	 * @return
+	 * 设置公众号信息 缓存中
+	 * @param account
 	 */
-	public static OAuthAccessToken getSingleOAuthAccessToken(){
-		Map<String,OAuthAccessToken> accountOAuthTokenMap = (Map<String, OAuthAccessToken>) CacheUtils.get("accountOAuthTokenMap");
-		if(null==accountOAuthTokenMap){
-			accountOAuthTokenMap=Maps.newHashMap();
-		}
-		OAuthAccessToken token = null;
-		for(String key : accountOAuthTokenMap.keySet()){
-			token = accountOAuthTokenMap.get(key);
-			break;
-		}
-		return token;
+	public static void setAccount(String account) {
+		CacheUtils.put(SESSION_ACCOUNT, account);
+	}
+	/**
+	 * 从缓存中获取公众号
+	 * @return String
+	 */
+	public static String getAccount() {
+		return (String) CacheUtils.get(SESSION_ACCOUNT);
 	}
 }
 

+ 29 - 11
src/main/java/com/wxmp/wxapi/process/WxMessageBuilder.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
 import java.util.ArrayList;
@@ -13,6 +19,7 @@ import com.wxmp.wxapi.vo.Article;
 import com.wxmp.wxapi.vo.MsgRequest;
 import com.wxmp.wxapi.vo.MsgResponseNews;
 import com.wxmp.wxapi.vo.MsgResponseText;
+import com.wxmp.wxcms.domain.MsgArticle;
 import com.wxmp.wxcms.domain.MsgNews;
 import com.wxmp.wxcms.domain.MsgText;
 
@@ -80,18 +87,29 @@ public class WxMessageBuilder {
 	//客服图文消息
 	public static String prepareCustomNews(String openid,MsgNews msgNews){
 		JSONObject jsObj = new JSONObject();
+//		List<MsgArticle> arts = msgNews.getArticles();
+//		jsObj.put("touser", openid);
+//		jsObj.put("msgtype", MsgType.News.toString().toLowerCase());
+//		JSONObject articles = new JSONObject();
+//		JSONArray articleArray = new JSONArray();
+//		//支持多图文
+//		arts.forEach((a)->{
+//			JSONObject newsObj = new JSONObject();
+//			newsObj.put("title", a.getTitle());
+//			newsObj.put("description", a.getDigest());
+//			newsObj.put("url", a.getUrl());
+//			newsObj.put("picurl", a.getPicUrl());
+//			articleArray.add(newsObj);
+//		});
+//		articles.put("articles", articleArray);
+//		jsObj.put("news", articles);
+//		第二种方式
 		jsObj.put("touser", openid);
-		jsObj.put("msgtype", MsgType.News.toString().toLowerCase());
-		JSONObject newsObj = new JSONObject();
-		JSONObject articles = new JSONObject();
-		JSONArray articleArray = new JSONArray();
-		newsObj.put("title", msgNews.getTitle());
-		newsObj.put("description", msgNews.getDescription());
-		newsObj.put("url", msgNews.getUrl());
-		newsObj.put("picurl", msgNews.getPicpath());
-		articleArray.add(newsObj);
-		articles.put("articles", articleArray);
-		jsObj.put("news", articles);
+		jsObj.put("msgtype", MsgType.MPNEWS.toString().toLowerCase());
+		JSONObject media = new JSONObject();
+		media.put("media_id", msgNews.getMediaId());
+		jsObj.put("mpnews", media);
+		
 		return jsObj.toString();
 	}
 	public static void main(String[] args) {

+ 7 - 1
src/main/java/com/wxmp/wxapi/process/WxSign.java

@@ -1,6 +1,12 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.process;
 
-import com.wxmp.backstage.common.Identities;
+import com.wxmp.core.common.Identities;
 import com.wxmp.core.util.wx.SignUtil;
 
 import java.util.SortedMap;

+ 7 - 1
src/main/java/com/wxmp/wxapi/service/MyService.java

@@ -1,3 +1,9 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.service;
 
 import net.sf.json.JSONObject;
@@ -17,7 +23,7 @@ public interface MyService {
 	public String processMsg(MsgRequest msgRequest,MpAccount mpAccount);
 
 	//发布菜单
-	public JSONObject publishMenu(String gid,MpAccount mpAccount);
+	public JSONObject publishMenu(MpAccount mpAccount);
 	
 	//删除菜单
 	public JSONObject deleteMenu(MpAccount mpAccount);

+ 26 - 93
src/main/java/com/wxmp/wxapi/service/impl/MyServiceImpl.java

@@ -1,5 +1,12 @@
+/**
+ * Copyright &copy; 2017-2018 <a href="http://www.webcsn.com">webcsn</a> All rights reserved.
+ *
+ * @author hermit
+ * @date 2018-04-17 10:54:58
+ */
 package com.wxmp.wxapi.service.impl;
 
+import com.wxmp.core.util.wx.WxUtil;
 import com.wxmp.wxapi.process.*;
 import com.wxmp.wxapi.service.MyService;
 import com.wxmp.wxapi.vo.Matchrule;
@@ -12,12 +19,9 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Service;
-
 import javax.annotation.Resource;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * 业务消息处理
@@ -61,7 +65,7 @@ public class MyServiceImpl implements MyService{
 			/**
 			 * 用户订阅公众账号、点击菜单按钮的时候,会触发事件消息
 			 */
-			respXml = this.processEventMsg(msgRequest);
+			respXml = this.processEventMsg(msgRequest,mpAccount);
 			
 		//其他消息类型,开发者自行处理
 		}else if(msgtype.equals(MsgType.Image.toString())){//图片消息
@@ -94,17 +98,17 @@ public class MyServiceImpl implements MyService{
 	}
 	
 	//处理事件消息
-	private String processEventMsg(MsgRequest msgRequest){
+	private String processEventMsg(MsgRequest msgRequest,MpAccount mpAccount){
 		String key = msgRequest.getEventKey();
 		if(MsgType.SUBSCRIBE.toString().equals(msgRequest.getEvent())){//订阅消息
 			logger.info("关注者openId----------"+msgRequest.getFromUserName());
 			String openId = msgRequest.getFromUserName();
-			MpAccount mpAccount = WxMemoryCacheClient.getSingleMpAccount();//获取缓存中的唯一账号
 			AccountFans fans = WxApiClient.syncAccountFans(openId, mpAccount);
 			//用户关注微信公众号后更新粉丝表
 			if (null != fans) {
 				AccountFans tmpFans = fansDao.getByOpenId(openId);
 				if(tmpFans == null){
+					tmpFans.setAccount(mpAccount.getAccount());
 					fansDao.add(fans);
 				}else{
 					fans.setId(tmpFans.getId());
@@ -159,11 +163,11 @@ public class MyServiceImpl implements MyService{
 	}
 	
 	//发布菜单
-	public JSONObject publishMenu(String gid,MpAccount mpAccount){
-		List<AccountMenu> menus = menuDao.listWxMenus(gid);
-		
+	public JSONObject publishMenu(MpAccount mpAccount){
+		//获取数据库菜单
+		List<AccountMenu> menus = menuDao.listWxMenus(new AccountMenu());
 		Matchrule matchrule = new Matchrule();
-		String menuJson = prepareMenus(menus,matchrule);
+		String menuJson =JSONObject.fromObject(WxUtil.prepareMenus(menus,matchrule)).toString() ;
 		logger.info("创建菜单传参如下:"+menuJson);
 		JSONObject rstObj = WxApiClient.publishMenus(menuJson,mpAccount);//创建普通菜单
 		logger.info("创建菜单返回消息如下:"+rstObj.toString());
@@ -171,15 +175,15 @@ public class MyServiceImpl implements MyService{
 //		matchrule.setSex("1");//1-男 ;2-女
 //		JSONObject rstObj = WxApiClient.publishAddconditionalMenus(menuJson,mpAccount);//创建个性化菜单
 		
-		if(rstObj != null){//成功,更新菜单组
-			if(rstObj.containsKey("menu_id")){
-				menuGroupDao.updateMenuGroupDisable();
-				menuGroupDao.updateMenuGroupEnable(gid);
-			}else if(rstObj.containsKey("errcode") && rstObj.getInt("errcode") == 0){
-				menuGroupDao.updateMenuGroupDisable();
-				menuGroupDao.updateMenuGroupEnable(gid);
-			}
-		}
+//		if(rstObj != null){//成功,更新菜单组
+//			if(rstObj.containsKey("menu_id")){
+//				menuGroupDao.updateMenuGroupDisable();
+//				menuGroupDao.updateMenuGroupEnable(gid);
+//			}else if(rstObj.containsKey("errcode") && rstObj.getInt("errcode") == 0){
+//				menuGroupDao.updateMenuGroupDisable();
+//				menuGroupDao.updateMenuGroupEnable(gid);
+//			}
+//		}
 		return rstObj;
 	}
 	
@@ -204,7 +208,7 @@ public class MyServiceImpl implements MyService{
 	
 	//同步粉丝列表(开发者在这里可以使用递归处理)
 	private boolean doSyncAccountFansList(String nextOpenId,MpAccount mpAccount){
-		String url = WxApi.getFansListUrl(WxApiClient.getAccessToken(mpAccount), nextOpenId);
+ 		String url = WxApi.getFansListUrl(WxApiClient.getAccessToken(mpAccount), nextOpenId);
 		logger.info("同步粉丝入参消息如下:"+url);
 		JSONObject jsonObject = WxApi.httpsRequest(url, HttpMethod.POST, null);
 		logger.info("同步粉丝返回消息如下:"+jsonObject.toString());
@@ -219,6 +223,8 @@ public class MyServiceImpl implements MyService{
 				for(int i = 0; i < length ;i++){
 					Object openId = openidArr.get(i);
 					AccountFans fans = WxApiClient.syncAccountFans(openId.toString(), mpAccount);
+					//设置公众号
+					fans.setAccount(WxMemoryCacheClient.getAccount());
 					fansList.add(fans);
 				}
 				//批处理
@@ -254,79 +260,6 @@ public class MyServiceImpl implements MyService{
 		}
 		return fans;
 	}
-	
-	/**
-	 * 获取微信公众账号的菜单
-	 * @param menus	菜单列表
-	 * @param matchrule	个性化菜单配置
-	 * @return
-	 */
-	private String prepareMenus(List<AccountMenu> menus,Matchrule matchrule) {
-		if(!CollectionUtils.isEmpty(menus)){
-			List<AccountMenu> parentAM = new ArrayList<AccountMenu>();
-			Map<Long,List<JSONObject>> subAm = new HashMap<Long,List<JSONObject>>();
-			for(AccountMenu m : menus){
-				if(m.getParentid() == 0L){//一级菜单
-					parentAM.add(m);
-				}else{//二级菜单
-					if(subAm.get(m.getParentid()) == null){
-						subAm.put(m.getParentid(), new ArrayList<JSONObject>());
-					}
-					List<JSONObject> tmpMenus = subAm.get(m.getParentid());
-					tmpMenus.add(getMenuJSONObj(m));
-					subAm.put(m.getParentid(), tmpMenus);
-				}
-			}
-			JSONArray arr = new JSONArray();
-			for(AccountMenu m : parentAM){
-				if(subAm.get(m.getId()) != null){//有子菜单
-					arr.add(getParentMenuJSONObj(m,subAm.get(m.getId())));
-				}else{//没有子菜单
-					arr.add(getMenuJSONObj(m));
-				}
-			}
-			JSONObject root = new JSONObject();
-			root.put("button", arr);
-			root.put("matchrule", JSONObject.fromObject(matchrule).toString());
-			return JSONObject.fromObject(root).toString();
-		}
-		return "error";
-	}
-	
-	/**
-	 * 此方法是构建菜单对象的;构建菜单时,对于  key 的值可以任意定义;
-	 * 当用户点击菜单时,会把key传递回来;对已处理就可以了
-	 * @param menu
-	 * @return
-	 */
-	private JSONObject getMenuJSONObj(AccountMenu menu){
-		JSONObject obj = new JSONObject();
-		obj.put("name", menu.getName());
-		obj.put("type", menu.getMtype());
-		if("click".equals(menu.getMtype())){//事件菜单
-			if("fix".equals(menu.getEventType())){//fix 消息
-				obj.put("key", "_fix_" + menu.getMsgId());//以 _fix_ 开头
-			}else{
-				if(StringUtils.isEmpty(menu.getInputcode())){//如果inputcode 为空,默认设置为 subscribe,以免创建菜单失败
-					obj.put("key", "subscribe");
-				}else{
-					obj.put("key", menu.getInputcode());
-				}
-			}
-		}else{//链接菜单-view
-			obj.put("url", menu.getUrl());
-		}
-		return obj;
-	}
-	
-	private JSONObject getParentMenuJSONObj(AccountMenu menu,List<JSONObject> subMenu){
-		JSONObject obj = new JSONObject();
-		obj.put("name", menu.getName());
-		obj.put("sub_button", subMenu);
-		return obj;
-	}
-
-	
 }
 
 

+ 4 - 27
src/main/java/com/wxmp/wxapi/vo/Article.java

@@ -1,38 +1,15 @@
 package com.wxmp.wxapi.vo;
+
+import lombok.Data;
+
 /**
  * 图文消息
  */
+@Data
 public class Article {
 	
 	private String Title;//标题
 	private String Description;//描述
 	private String PicUrl;//图片链接
 	private String Url;//原文链接
-	
-	
-	public String getTitle() {
-		return Title;
-	}
-	public void setTitle(String title) {
-		Title = title;
-	}
-	public String getDescription() {
-		return Description;
-	}
-	public void setDescription(String description) {
-		Description = description;
-	}
-	public String getPicUrl() {
-		return PicUrl;
-	}
-	public void setPicUrl(String picUrl) {
-		PicUrl = picUrl;
-	}
-	public String getUrl() {
-		return Url;
-	}
-	public void setUrl(String url) {
-		Url = url;
-	}
-	
 }

+ 3 - 8
src/main/java/com/wxmp/wxapi/vo/Image.java

@@ -1,17 +1,12 @@
 package com.wxmp.wxapi.vo;
 
+import lombok.Data;
+
 /**
  * 图片消息
  * 
  */
+@Data
 public class Image {
 	private String MediaId;
-	
-	public String getMediaId() {
-		return MediaId;
-	}
-
-	public void setMediaId(String mediaId) {
-		MediaId = mediaId;
-	}
 }

+ 0 - 0
src/main/java/com/wxmp/wxapi/vo/Matchrule.java


Неке датотеке нису приказане због велике количине промена