Repository: RojerAlone/shop Branch: master Commit: 1161b7b7ad35 Files: 167 Total size: 422.6 KB Directory structure: gitextract_t46sxuk1/ ├── .gitignore ├── LICENSE.txt ├── README.md ├── pom.xml └── src/ ├── main/ │ ├── java/ │ │ └── cn/ │ │ └── cie/ │ │ ├── aop/ │ │ │ └── LogAspectj.java │ │ ├── controller/ │ │ │ ├── AbstractController.java │ │ │ ├── AdminController.java │ │ │ ├── CommonController.java │ │ │ ├── GameController.java │ │ │ ├── KindController.java │ │ │ ├── OrderController.java │ │ │ ├── TagController.java │ │ │ └── UserController.java │ │ ├── entity/ │ │ │ ├── Code.java │ │ │ ├── Game.java │ │ │ ├── Img.java │ │ │ ├── Kind.java │ │ │ ├── Kindmapper.java │ │ │ ├── Order.java │ │ │ ├── Orderitem.java │ │ │ ├── Ordermapper.java │ │ │ ├── Tag.java │ │ │ ├── Tagmapper.java │ │ │ ├── Token.java │ │ │ ├── User.java │ │ │ ├── Validatecode.java │ │ │ └── dto/ │ │ │ ├── GameDTO.java │ │ │ ├── OrderDTO.java │ │ │ └── OrderItemDTO.java │ │ ├── event/ │ │ │ ├── EventConsumer.java │ │ │ ├── EventModel.java │ │ │ ├── EventProducer.java │ │ │ ├── EventType.java │ │ │ └── handler/ │ │ │ ├── EventHandler.java │ │ │ ├── SendFindPwdMailHandler.java │ │ │ └── SendValidateMailHandler.java │ │ ├── exception/ │ │ │ └── NotFoundException.java │ │ ├── interceptor/ │ │ │ ├── AdminInterceptor.java │ │ │ ├── AuthInterceptor.java │ │ │ └── LoginInterceptor.java │ │ ├── mapper/ │ │ │ ├── CodeMapper.java │ │ │ ├── GameMapper.java │ │ │ ├── ImgMapper.java │ │ │ ├── KindMapper.java │ │ │ ├── KindmapperMapper.java │ │ │ ├── OrderMapper.java │ │ │ ├── OrderitemMapper.java │ │ │ ├── OrdermapperMapper.java │ │ │ ├── TagMapper.java │ │ │ ├── TagmapperMapper.java │ │ │ ├── TokenMapper.java │ │ │ └── UserMapper.java │ │ ├── schedule/ │ │ │ └── Scheduler.java │ │ ├── services/ │ │ │ ├── AdminService.java │ │ │ ├── GameService.java │ │ │ ├── KindService.java │ │ │ ├── OrderService.java │ │ │ ├── TagService.java │ │ │ ├── UserService.java │ │ │ └── impl/ │ │ │ ├── AdminServiceImpl.java │ │ │ ├── GameServiceImpl.java │ │ │ ├── KindServiceImpl.java │ │ │ ├── OrderServiceImpl.java │ │ │ ├── TagServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ └── utils/ │ │ ├── MailUtil.java │ │ ├── MsgCenter.java │ │ ├── PageUtil.java │ │ ├── PasswordUtil.java │ │ ├── RedisUtil.java │ │ ├── Result.java │ │ └── UserHolder.java │ ├── resources/ │ │ ├── dbdata.sql │ │ ├── generator/ │ │ │ └── generatorConfig.xml │ │ ├── jdbc.properties │ │ ├── log4j-acc.properties │ │ ├── log4j-error.properties │ │ ├── mapper/ │ │ │ ├── CodeMapper.xml │ │ │ ├── GameMapper.xml │ │ │ ├── ImgMapper.xml │ │ │ ├── KindMapper.xml │ │ │ ├── KindmapperMapper.xml │ │ │ ├── OrderMapper.xml │ │ │ ├── OrderitemMapper.xml │ │ │ ├── OrdermapperMapper.xml │ │ │ ├── TagMapper.xml │ │ │ ├── TagmapperMapper.xml │ │ │ ├── TokenMapper.xml │ │ │ └── UserMapper.xml │ │ ├── mybatis-config.xml │ │ ├── schema.sql │ │ ├── spring-dao.xml │ │ ├── spring-mvc.xml │ │ └── spring-service.xml │ └── webapp/ │ └── WEB-INF/ │ ├── css/ │ │ ├── adminlogin.css │ │ ├── adminpage.css │ │ ├── base.css │ │ ├── fenleixiangqing.css │ │ ├── login.css │ │ ├── order.css │ │ ├── personal.css │ │ ├── regist.css │ │ ├── sanji.css │ │ ├── self.css │ │ └── shoppingcart.css │ ├── js/ │ │ ├── adminlogin.js │ │ ├── adminpage.js │ │ ├── biaoqian.js │ │ ├── fenlei.js │ │ ├── findpassword.js │ │ ├── fishjs/ │ │ │ ├── ane.js │ │ │ ├── baby.js │ │ │ ├── background.js │ │ │ ├── collision.js │ │ │ ├── commonFunctions.js │ │ │ ├── data.js │ │ │ ├── dust.js │ │ │ ├── fruit.js │ │ │ ├── halo.js │ │ │ ├── main.js │ │ │ ├── mom.js │ │ │ └── wave.js │ │ ├── index.js │ │ ├── login.js │ │ ├── order.js │ │ ├── personal.js │ │ ├── regist.js │ │ ├── sanji.js │ │ ├── search.js │ │ ├── shoppingcart.js │ │ ├── top.js │ │ ├── updateUserInfo.js │ │ └── updatepassword.js │ ├── jsp/ │ │ ├── adminlogin.jsp │ │ ├── adminpage.jsp │ │ ├── checkemail.jsp │ │ ├── common/ │ │ │ ├── bottom.jsp │ │ │ ├── head.jsp │ │ │ └── top.jsp │ │ ├── error/ │ │ │ ├── ErrorCode400.jsp │ │ │ ├── ErrorCode404.jsp │ │ │ └── ErrorCode500.jsp │ │ ├── findpassword.jsp │ │ ├── fishjs.jsp │ │ ├── gameInfo.jsp │ │ ├── index.jsp │ │ ├── kinds.jsp │ │ ├── login.jsp │ │ ├── order.jsp │ │ ├── order_1.jsp │ │ ├── order_2.jsp │ │ ├── personal.jsp │ │ ├── register.jsp │ │ ├── search.jsp │ │ ├── shoppingcart.jsp │ │ ├── taggames.jsp │ │ ├── updateUserInfo.jsp │ │ ├── updatepassword.jsp │ │ └── validate.jsp │ └── web.xml └── test/ └── java/ └── cn/ └── cie/ ├── common/ │ └── CommonTest.java ├── mapper/ │ ├── GameMapperTest.java │ ├── KindmapperMapperTest.java │ └── UserMapperTest.java ├── services/ │ ├── KindServiceTest.java │ └── UserServiceTest.java └── utils/ └── RedisUtilTest.java ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Compiled class file *.class # Log file *.log # IDEA file .idea/ *.iml target/ upload/ # BlueJ files *.ctxt # Mobile Tools for Java (J2ME) .mtj.tmp/ # Package Files # *.jar *.war *.ear *.zip *.tar.gz *.rar # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* ================================================ FILE: LICENSE.txt ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. 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} {name of author} 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 . 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: {project} Copyright (C) {year} {fullname} 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 . 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 . ================================================ FILE: README.md ================================================ # Shop SSM框架搭建的网上游戏商城 ## 项目信息 - 项目名字:WePlay - 项目描述:基于SSM框架的网上游戏商城 ## 环境配置 - JDK 1.8 - Spring 5.1.7 - MyBatis 3.4 - MySQL 5.7.18 - Maven 3 - Redis 3.0 - Tomcat 8.5.15 ### maven 阿里云仓库 ```xml alimaven aliyun maven http://maven.aliyun.com/nexus/content/groups/public/ central ``` # 一些问题及解决方案 ## 跨域请求   在`Controller`控制器中添加了`@CrossOrigin`注解。 ## 用`token`验证用户身份   使用唯一识别码`token`来识别每一个用户,用户登陆后生成一个`token`写入数据库和缓存中,同时写入到response中的cookie中,这样以后每次请求都会带上这个`token`,用`AuthInterceptor`对所有的请求进行拦截,根据`token`从缓存中查取对应的`uid`,再从数据库中查取对应的用户详情,并存到[`UserHolder`](https://github.com/RojerAlone/shop/blob/master/src/main/java/cn/cie/utils/UserHolder.java)这个工具类中。 ## 拦截器进行权限处理   很多接口只有用户验证了才能进行下一步操作,写了一个拦截器对特定的请求进行拦截,如果用户没有登录,就跳转到登陆页面,登陆成功后跳转到之前的页面。 ## 使用`Redis`   几乎所有的页面都会加载商品种类,因此将商品的种类信息放入缓存中;网站首页有一个每日推荐,是每天零时随机生成5个商品,由于这些商品访问频率高,因此将这5个商品放入缓存中,可将访问速度由10\~20ms 缩减到3\~5ms。   同时用户`token`也放入了缓存中,并设置过期时间为1天,如果用户选择了保持登陆状态7天,那么`token`过期后再从数据库中取出放入缓存中。   用户注册后需要验证邮箱,将验证码放入缓存中,15分钟过期。   将重量型事件抽取出来,用Redis模拟消息队列,创建多线程添加到线程池中,线程从队列中获取消息并执行,比如发送邮件操作。 ================================================ FILE: pom.xml ================================================ 4.0.0 cn.cie shop war 1.0 shop Maven Webapp http://maven.apache.org 5.3.14 1.8.10 3.5.6 1.2.17 junit junit 4.13.1 test javax.servlet javax.servlet-api 3.1.0 org.springframework spring-core ${spring.version} org.springframework spring-web ${spring.version} org.springframework spring-oxm ${spring.version} org.springframework spring-tx ${spring.version} org.springframework spring-jdbc ${spring.version} org.springframework spring-webmvc ${spring.version} org.springframework spring-aop ${spring.version} org.springframework spring-context-support ${spring.version} org.springframework spring-context ${spring.version} org.springframework spring-test ${spring.version} org.aspectj aspectjrt ${aop.version} org.aspectj aspectjweaver ${aop.version} com.fasterxml.jackson.core jackson-databind 2.10.0.pr1 org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring 1.3.1 mysql mysql-connector-java 8.0.16 commons-dbcp commons-dbcp 1.4 jstl jstl 1.2 log4j log4j ${log4j.version} org.slf4j slf4j-simple 1.7.24 org.apache.commons commons-email 1.3.1 redis.clients jedis 2.9.0 com.alibaba fastjson 1.2.25 org.apache.commons commons-lang3 3.5 commons-fileupload commons-fileupload 1.3.3 shop org.mybatis.generator mybatis-generator-maven-plugin 1.3.5 ${basedir}/src/main/resources/generator/generatorConfig.xml true true ================================================ FILE: src/main/java/cn/cie/aop/LogAspectj.java ================================================ package cn.cie.aop; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; /** * Created by RojerAlone on 2017/6/8. * 日志记录,包括请求日志和错误日志 */ @Component @Aspect public class LogAspectj { private final Logger logger = Logger.getLogger(this.getClass()); @Before("execution(* cn.cie.controller.*Controller.*(..)) && !execution( * cn.cie.controller.AbstractController.*(..))") // 切面为controller中的所有方法 public void logAccess(JoinPoint joinPoint) { PropertyConfigurator.configure(this.getClass().getClassLoader().getResource("/").getPath() + "log4j-acc.properties"); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); StringBuilder sb = new StringBuilder(); String token = ""; if (request.getCookies() != null && request.getCookies().length > 0) { for (Cookie cookie : request.getCookies()) { if (cookie.getName().equals("token")) { token = cookie.getValue(); } } } sb.append("token: " + token); sb.append("\tip: " + request.getRemoteAddr()); sb.append("\tmethod: " + request.getMethod()); sb.append("\turl: " + request.getRequestURI()); sb.append("\tparams: "); for (Object object : joinPoint.getArgs()) { if (object != null) { sb.append("\t" + object.getClass().getSimpleName() + " " + object.toString()); } } logger.info(sb.toString()); } @AfterThrowing(value = "execution(* cn.cie.controller.*Controller.*(..)) && !execution( * cn.cie.controller.AbstractController.*(..))", throwing = "e") // 切面为controller中的所有方法 public void errorAccess(Throwable e) { PropertyConfigurator.configure(this.getClass().getClassLoader().getResource("/").getPath() + "log4j-error.properties"); if (e instanceof Exception) { logger.error("", e); } } } ================================================ FILE: src/main/java/cn/cie/controller/AbstractController.java ================================================ /* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cn.cie.controller; import org.apache.log4j.Logger; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * 从左潇龙博客源码复制过来 * 基础controller,各个web项目应该在此基础上扩展自己的基础controller. * * @author Boren You * @date 2016/5/12 21:28 * @since 1.0.0 */ public abstract class AbstractController { /** * 日志对象 */ protected Logger logger = Logger.getLogger(this.getClass()); /** * 存放当前线程的HttpServletRequest对象 */ private static ThreadLocal httpServletRequestThreadLocal = new ThreadLocal(); /** * 存放当前线程的Model对象 */ private static ThreadLocal modelThreadLocal = new ThreadLocal(); /** * 使用@ModelAttribute注解标识的方法会在每个控制器中的方法访问之前先调用 * * @param request * @param model */ @ModelAttribute protected void setThreadLocal(HttpServletRequest request, Model model) { httpServletRequestThreadLocal.set(request); modelThreadLocal.set(model); } /** * 获取当前线程的HttpServletRequest对象 * * @return 当前线程的HttpServletRequest对象 */ protected HttpServletRequest getRequest() { return httpServletRequestThreadLocal.get(); } /** * 获取当前线程的HttpSession对象 * * @return 当前线程的HttpSession对象 */ protected HttpSession getSession() { return getRequest().getSession(); } /** * 获取当前线程的Model对象 * * @return 当前线程的Model对象 */ protected Model getModel() { return modelThreadLocal.get(); } /** * 获取当前的ServletContext对象 * * @return 当前的ServletContext对象 */ protected ServletContext getContext() { return getRequest().getServletContext(); } /** * 向 Model 设置属性值 * * @param name 属性名 * @param value 属性值 */ protected void setModelAttribute(String name, Object value) { getModel().addAttribute(name, value); } /** * 向 HttpServletRequest 设置属性值 * * @param name 属性名 * @param value 属性值 */ protected void setRequestAttribute(String name, Object value) { HttpServletRequest request = this.getRequest(); request.setAttribute(name, value); } /** * 向 HttpSession 设置属性值 * * @param name 属性名 * @param value 属性值 */ public void setSessionAttribute(String name, Object value) { HttpSession session = this.getSession(); session.setAttribute(name, value); } /** * 从 HttpSession 中获取属性值 * * @param name 属性名 * @return 属性值 */ protected Object getSessionAttribute(String name) { HttpSession session = this.getSession(); Object value = session.getAttribute(name); return value; } /** * 从 HttpServletRequest 中获取属性值 * * @param name 属性名 * @return 属性值 */ protected Object getRequestAttribute(String name) { HttpServletRequest request = this.getRequest(); Object value = request.getAttribute(name); return value; } protected String getUserAgent() { return this.getRequest().getHeader("User-Agent"); } protected String getRemoteIp() { String remoteIp; remoteIp = this.getRequest().getHeader("x-forwarded-for"); if (remoteIp == null || remoteIp.length() == 0 || "unknown".equalsIgnoreCase(remoteIp)) { remoteIp = this.getRequest().getHeader("Proxy-Client-IP"); } if (remoteIp == null || remoteIp.length() == 0 || "unknown".equalsIgnoreCase(remoteIp)) { remoteIp = this.getRequest().getHeader("WL-Proxy-Client-IP"); } if (remoteIp == null || remoteIp.length() == 0 || "unknown".equalsIgnoreCase(remoteIp)) { remoteIp = this.getRequest().getHeader("HTTP_CLIENT_IP"); } if (remoteIp == null || remoteIp.length() == 0 || "unknown".equalsIgnoreCase(remoteIp)) { remoteIp = this.getRequest().getHeader("HTTP_X_FORWARDED-FOR"); } if (remoteIp == null || remoteIp.length() == 0 || "unknown".equalsIgnoreCase(remoteIp)) { remoteIp = this.getRequest().getRemoteAddr(); } //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 if (remoteIp != null && remoteIp.length() > 15) { //"***.***.***.***".length() = 15 if (remoteIp.indexOf(",") > 0) { remoteIp = remoteIp.substring(0, remoteIp.indexOf(",")); } } return remoteIp; } } ================================================ FILE: src/main/java/cn/cie/controller/AdminController.java ================================================ package cn.cie.controller; import cn.cie.entity.Game; import cn.cie.services.AdminService; import cn.cie.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; import java.util.Date; /** * Created by RojerAlone on 2017/6/15. */ @CrossOrigin @Controller @RequestMapping(value = "admin") public class AdminController extends AbstractController { @Autowired private AdminService adminService; @GetMapping(value = "login") public String login() { return "adminlogin"; } @PostMapping(value = "login") @ResponseBody public Result login(String username, String password, HttpServletResponse response) { Result result = adminService.login(username, password); if (result.isSuccess()) { Cookie cookie = new Cookie("token", (String) result.getData()); cookie.setPath("/"); response.addCookie(cookie); return Result.success(); } return result; } @GetMapping(value = "home") public String adminPage() { return "adminpage"; } @PostMapping(value = "getuser") @ResponseBody public Result getUser(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page) { return adminService.getUser(page); } @PostMapping(value = "restrictuser") @ResponseBody public Result restrict(Integer uid) { return adminService.restrict(uid); } @PostMapping(value = "relieveuser") @ResponseBody public Result relieve(Integer uid) { return adminService.relieve(uid); } @PostMapping(value = "deluser") @ResponseBody public Result delUser(Integer uid) { return adminService.delete(uid); } @PostMapping(value = "getgames") @ResponseBody public Result getGames(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page) { return adminService.getGames(page); } @PostMapping(value = "addgame") @ResponseBody public Result addGame(Game game, Integer[] kinds, MultipartFile header, @RequestParam(value = "pics") MultipartFile[] pics) throws IOException { return adminService.addGame(game, kinds, header, pics, this.getSession().getServletContext().getRealPath("/WEB-INF/image").replaceAll("\\\\", "/")); } @PostMapping(value = "updategameinfo") @ResponseBody public Result updateGameInfo(Game game) { return adminService.updateGameInfo(game); } @PostMapping(value = "getgamekind") @ResponseBody public Result getGameKind(Integer game) { return adminService.getGameKind(game); } @PostMapping(value = "updategamekind") @ResponseBody public Result updateGameKind(Integer game, Integer[] kinds) { return adminService.updateGameKind(game, Arrays.asList(kinds)); } @PostMapping(value = "upgame") @ResponseBody public Result upGame(Integer game, @RequestParam(value = "date", required = false) Date date) { return adminService.upGame(game, date); } @PostMapping(value = "downgame") @ResponseBody public Result downGame(Integer game) { return adminService.downGame(game); } @PostMapping(value = "addkind") @ResponseBody public Result addKind(String kind) { return adminService.addKind(kind); } @PostMapping(value = "getallgames") @ResponseBody public Result getAllGames() { return adminService.getAllGames(); } @PostMapping(value = "managerkind") @ResponseBody public Result managerKind(Integer kind, Integer[] games) { return adminService.managerKind(kind, Arrays.asList(games)); } } ================================================ FILE: src/main/java/cn/cie/controller/CommonController.java ================================================ package cn.cie.controller; import cn.cie.entity.User; import cn.cie.services.GameService; import cn.cie.services.UserService; import cn.cie.utils.MsgCenter; import cn.cie.utils.Result; import cn.cie.utils.UserHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map; /** * Created by RojerAlone on 2017/6/9. */ @CrossOrigin @Controller public class CommonController extends AbstractController { @Autowired private UserHolder userHolder; @Autowired private UserService userService; @Autowired private GameService gameService; @RequestMapping(value = {"/", "/index"}) public String index() { return "index"; } @GetMapping(value = "login") public String login() { String referer = getReferer(); // 如果用户已经登陆并且状态正常,那么跳转到之前的页面 if (userHolder.getUser() != null && userHolder.getUser().getStat().equals(User.STAT_OK)) { return "redirect:" + referer; } return "login"; } @PostMapping(value = "login") @ResponseBody public Result login(String username, String password, @RequestParam(value = "remember", defaultValue = "false", required = false) boolean remember, HttpServletResponse response) { String referer = getReferer(); // 如果用户已经登陆,那么跳转到之前的页面 if (userHolder.getUser() != null && userHolder.getUser().getStat().equals(User.STAT_OK)) { return Result.fail(MsgCenter.OK, referer); } Result result = userService.login(username, password, remember, this.getRemoteIp(), this.getUserAgent()); if (result.isSuccess()) { Map data = new HashMap(); data.put("referer", referer); // response中添加cookie,以后每次请求都会带上cookie Cookie cookie = new Cookie("token", (String) result.getData()); cookie.setPath("/"); if (remember) { cookie.setMaxAge(60 * 60 * 24 * 7); } else { cookie.setMaxAge(60 * 60 * 24); } response.addCookie(cookie); return Result.success(data); } else { return result; } } @PostMapping(value = "logout") @ResponseBody public Result logout() { String token = null; // 从请求中获取token if (this.getRequest().getCookies() != null) { for (Cookie cookie : this.getRequest().getCookies()) { if (cookie.getName().equals("token")) { token = cookie.getValue(); } } } return userService.logout(token); } @GetMapping(value = "register") public String register() { String referer = getReferer(); if (userHolder.getUser() != null) { return "redirect:" + referer; } return "register"; } @PostMapping(value = "register") @ResponseBody public Result register(User user, HttpServletResponse response) { Result result = userService.register(user); String pwd = user.getPassword(); // 注册成功就自动登录,前台跳转到验证页面 if (result.isSuccess()) { login(user.getUsername(), pwd, false, response); return Result.success(); } return result; } /** * 获取每日推荐,随机选取5个游戏,每日生成一次 * * @return */ @PostMapping(value = "everyday") @ResponseBody public Result everyday() { return gameService.getRandomGames(); } @GetMapping(value = "shoppingcart") public String shoppingcart() { return "shoppingcart"; } /** * 最新的5个游戏,根据上架时间排序,放在缓存中 * * @return */ @PostMapping(value = "newestgames") @ResponseBody public Result newestGames() { return gameService.newestGames(); } /** * 最新的5个未上架游戏,根据时间排序,放在缓存中 * * @return */ @PostMapping(value = "preupgames") @ResponseBody public Result preUpGames() { return gameService.preUpGames(); } @PostMapping(value = "freegames") @ResponseBody public Result getFreeGames() { return gameService.getFreeGames(); } @GetMapping(value = "search") public String search() { return "search"; } @PostMapping(value = "search") @ResponseBody public Result search(String info) { return gameService.search(info); } /** * 检查用户是否登陆,如果登陆就返回应该跳转到的页面,否则执行接下来的逻辑 * 每次登陆之前都从request的header中获取跳转之前的链接referer * 如果为空(从别的网站跳转过来的),那么应该跳转到首页 * 登陆流程中第一次登陆就会调用本方法获取跳转链接,登陆失败将referer写入session中 * 如果是从登录页跳转过来的,可能是登陆出错了,但是跳转到登录页之前的referer在session存着,从session中获取 * 如果sesson中有referer,那么登陆成功跳转到referer,并且从session中删除referer * * @return */ private String getReferer() { String referer = null; String tmp = this.getRequest().getHeader("Referer"); // 如果为空,不是从本站跳转过来的,应该跳转到首页 if (tmp == null) { referer = "/"; } else if (tmp.endsWith("/login")) { referer = (String) this.getSession().getAttribute("Referer"); } else { referer = tmp; } this.getSession().setAttribute("Referer", referer); return referer; } } ================================================ FILE: src/main/java/cn/cie/controller/GameController.java ================================================ package cn.cie.controller; import cn.cie.exception.NotFoundException; import cn.cie.services.GameService; import cn.cie.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; /** * Created by RojerAlone on 2017/6/8. */ @CrossOrigin @Controller @RequestMapping(value = "game") public class GameController extends AbstractController { @Autowired private GameService gameService; @GetMapping(value = "{id}") public String gameInfo(@PathVariable(value = "id") Integer id) { if (!gameService.exists(id)) { throw new NotFoundException(); } this.getModel().addAttribute("id", id); return "gameInfo"; } @PostMapping(value = "{id}") @ResponseBody public Result selectById(@PathVariable(value = "id") Integer id) { return gameService.getById(id); } } ================================================ FILE: src/main/java/cn/cie/controller/KindController.java ================================================ package cn.cie.controller; import cn.cie.exception.NotFoundException; import cn.cie.services.KindService; import cn.cie.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; /** * Created by RojerAlone on 2017/6/6. */ @CrossOrigin @Controller @RequestMapping(value = "kind") public class KindController extends AbstractController { @Autowired private KindService kindService; @PostMapping(value = "all") @ResponseBody public Result allkinds(HttpServletResponse response) { Result result = kindService.getAll(); return result; } @GetMapping(value = "{kind}/games") public String getGames(@PathVariable(value = "kind") Integer kind) { String name = kindService.getNameById(kind); if (name == null) { throw new NotFoundException(); } this.getModel().addAttribute("id", kind); this.getModel().addAttribute("name", name); return "kinds"; } @PostMapping(value = "{kind}/games") @ResponseBody public Result getGamesByKind(@PathVariable(value = "kind") Integer kind, @RequestParam(value = "page", required = false, defaultValue = "1") Integer page) { return kindService.getGamesByKind(kind, page); } } ================================================ FILE: src/main/java/cn/cie/controller/OrderController.java ================================================ package cn.cie.controller; import cn.cie.exception.NotFoundException; import cn.cie.services.OrderService; import cn.cie.utils.Result; import cn.cie.utils.UserHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.Arrays; /** * Created by RojerAlone on 2017/6/12. */ @CrossOrigin @Controller @RequestMapping(value = "/order") public class OrderController extends AbstractController { @Autowired private OrderService orderService; @Autowired private UserHolder userHolder; @GetMapping(value = "orders") public String orders() { return "order"; } @PostMapping(value = "order") @ResponseBody public Result order(@RequestParam(value = "games") Integer[] games) { return orderService.addOrders(userHolder.getUser().getId(), Arrays.asList(games)); } @PostMapping(value = "{orderid}/cancel") @ResponseBody public Result cancelOrder(@PathVariable(value = "orderid") Integer orderid) { return orderService.cancelOrder(userHolder.getUser().getId(), orderid); } @GetMapping(value = "{orderid}/payway") public String payway(@PathVariable(value = "orderid") Integer orderid) { if (!orderService.exists(orderid)) { throw new NotFoundException(); } this.getModel().addAttribute("id", orderid); return "order_1"; } @GetMapping(value = "{orderid}/pay") public String pay(@PathVariable(value = "orderid") Integer orderid) { if (!orderService.exists(orderid)) { throw new NotFoundException(); } this.getModel().addAttribute("id", orderid); return "order_2"; } @PostMapping(value = "{orderid}/pay") @ResponseBody public Result payOrder(@PathVariable(value = "orderid") Integer orderid) { return orderService.pay(userHolder.getUser().getId(), orderid); } @PostMapping(value = "notpay/{page}") @ResponseBody public Result getNotPayOrders(@PathVariable(value = "page") Integer page) { return orderService.getNotPayOrders(userHolder.getUser().getId(), page); } @PostMapping(value = "paid/{page}") @ResponseBody public Result getPaidOrders(@PathVariable(value = "page") Integer page) { return orderService.getPaidOrders(userHolder.getUser().getId(), page); } @PostMapping(value = "cancel/{page}") @ResponseBody public Result getCancelOrders(@PathVariable(value = "page") Integer page) { return orderService.getCancelOrders(userHolder.getUser().getId(), page); } } ================================================ FILE: src/main/java/cn/cie/controller/TagController.java ================================================ package cn.cie.controller; import cn.cie.entity.dto.GameDTO; import cn.cie.exception.NotFoundException; import cn.cie.services.TagService; import cn.cie.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.List; /** * Created by RojerAlone on 2017/6/7. */ @CrossOrigin @Controller @RequestMapping(value = "tag") public class TagController extends AbstractController { @Autowired private TagService tagService; @GetMapping(value = "/{tag}/games") public String getGames(@PathVariable(value = "tag") Integer tag) { String name = tagService.getNameById(tag); if (name == null) { throw new NotFoundException(); } this.getModel().addAttribute("id", tag); this.getModel().addAttribute("name", name); return "taggames"; } @PostMapping(value = "/{tag}/games") @ResponseBody public Result> getGamesByTag(@PathVariable(value = "tag") Integer tag, @RequestParam(value = "page", required = false, defaultValue = "1") Integer page) { return tagService.getGamesByTag(tag, page); } } ================================================ FILE: src/main/java/cn/cie/controller/UserController.java ================================================ package cn.cie.controller; import cn.cie.entity.User; import cn.cie.services.UserService; import cn.cie.utils.MsgCenter; import cn.cie.utils.Result; import cn.cie.utils.UserHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; /** * Created by RojerAlone on 2017/6/6. */ @CrossOrigin @Controller @RequestMapping(value = "user") public class UserController extends AbstractController { @Autowired private UserService userService; @Autowired private UserHolder userHolder; @GetMapping(value = "validate") public String validate() { String referer = getReferer(); if (userHolder.getUser().getStat().equals(User.STAT_OK)) { return "redirect:" + referer; } return "validate"; } @PostMapping(value = "validate") @ResponseBody public Result validate(String code) { if (userHolder.getUser() == null) { return Result.fail(MsgCenter.USER_NOT_LOGIN); } if (userHolder.getUser().getStat().equals(User.STAT_OK)) { // 用户已经验证过了 return Result.fail(MsgCenter.USER_VALIDATED); } Result result = userService.validate(userHolder.getUser().getId(), code); if (result.isSuccess()) { return Result.success("/"); } return result; } @PostMapping(value = "sendMail") @ResponseBody public Result sendMail() { if (userHolder.getUser() == null) { return Result.fail(MsgCenter.USER_NOT_LOGIN); } return userService.sendMail(userHolder.getUser()); } @GetMapping(value = "personal") public String personal() { return "personal"; } @PostMapping(value = "personal") @ResponseBody public Result getPersonInfo() { User user = userHolder.getUser(); if (user == null) { return Result.fail(MsgCenter.USER_NOT_LOGIN); } user.setPassword(null); return Result.success(user); } @GetMapping(value = "update") public String update() { return "updateUserInfo"; } @PostMapping(value = "update") @ResponseBody public Result update(User user) { return userService.updateUserInfo(user); } @GetMapping(value = "updatepassword") public String updatePassword() { return "updatepassword"; } @PostMapping(value = "updatepassword") @ResponseBody public Result updatePassword(String password) { return userService.updatePassword(password); } @GetMapping(value = "findpassword") public String findPassword() { return "findpassword"; } @PostMapping(value = "sendfetchpwdmail") @ResponseBody public Result sendFetchPwdMail(String email) { return userService.sendFetchPwdMail(email); } @PostMapping(value = "findpassword") @ResponseBody public Result findPassword(String password, String email, String code) { return userService.forgetPassword(password, email, code); } /** * 检查用户是否登陆,如果登陆就返回应该跳转到的页面,否则执行接下来的逻辑 * 每次登陆之前都从request的header中获取跳转之前的链接referer * 如果为空(从别的网站跳转过来的),那么应该跳转到首页 * 登陆流程中第一次登陆就会调用本方法获取跳转链接,登陆失败将referer写入session中 * 如果是从登录页跳转过来的,可能是登陆出错了,但是跳转到登录页之前的referer在session存着,从session中获取 * 如果sesson中有referer,那么登陆成功跳转到referer,并且从session中删除referer * * @return */ private String getReferer() { String referer = null; String tmp = this.getRequest().getHeader("Referer"); // 如果为空,不是从本站跳转过来的,应该跳转到首页 if (tmp == null) { referer = "/"; } else if (tmp.endsWith("/login")) { referer = (String) this.getSession().getAttribute("Referer"); } else { referer = tmp; } this.getSession().setAttribute("Referer", referer); return referer; } } ================================================ FILE: src/main/java/cn/cie/entity/Code.java ================================================ package cn.cie.entity; /** * 游戏激活码 */ public class Code { /** * 未使用 */ public static final Byte STAT_NOT_USED = 0; /** * 已使用 */ public static final Byte STAT_USED = 1; private Integer id; private Integer item; private Integer uid; private String code; private Byte stat; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getItem() { return item; } public void setItem(Integer item) { this.item = item; } public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public Byte getStat() { return stat; } public void setStat(Byte stat) { this.stat = stat; } } ================================================ FILE: src/main/java/cn/cie/entity/Game.java ================================================ package cn.cie.entity; import java.util.Date; /** * 游戏 */ public class Game { /** * 未上架 */ public static final Byte STAT_PRE = 0; /** * 已上架 */ public static final Byte STAT_OK = 1; /** * 已下架 */ public static final Byte STAT_DEL = 2; private Integer id; private String creater; private String name; private String desc; private String systemcfg; private Double price; private Double discount; private Date ctime; private Date utime; private Byte stat; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getCreater() { return creater; } public void setCreater(String creater) { this.creater = creater; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getSystemcfg() { return systemcfg; } public void setSystemcfg(String systemcfg) { this.systemcfg = systemcfg; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public Double getDiscount() { return discount; } public void setDiscount(Double discount) { this.discount = discount; } public Date getCtime() { return ctime; } public void setCtime(Date ctime) { this.ctime = ctime; } public Date getUtime() { return utime; } public void setUtime(Date utime) { this.utime = utime; } public Byte getStat() { return stat; } public void setStat(Byte stat) { this.stat = stat; } } ================================================ FILE: src/main/java/cn/cie/entity/Img.java ================================================ package cn.cie.entity; /** * 游戏图片 */ public class Img { private Integer game; private String img; public Integer getGame() { return game; } public void setGame(Integer game) { this.game = game; } public String getImg() { return img; } public void setImg(String img) { this.img = img; } } ================================================ FILE: src/main/java/cn/cie/entity/Kind.java ================================================ package cn.cie.entity; public class Kind { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: src/main/java/cn/cie/entity/Kindmapper.java ================================================ package cn.cie.entity; /** * 游戏和种类映射 */ public class Kindmapper { private Integer game; private Integer kind; public Integer getGame() { return game; } public void setGame(Integer game) { this.game = game; } public Integer getKind() { return kind; } public void setKind(Integer kind) { this.kind = kind; } } ================================================ FILE: src/main/java/cn/cie/entity/Order.java ================================================ package cn.cie.entity; import java.util.Date; /** * 订单 */ public class Order { /** * 未支付 */ public static final Byte STAT_NOT_PAY = 0; /** * 已支付 */ public static final Byte STAT_PAY = 1; /** * 取消 */ public static final Byte STAT_CANCEL = 2; private Integer id; private Integer uid; private Double price; private Date ctime; private Date utime; private Byte stat; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public Date getCtime() { return ctime; } public void setCtime(Date ctime) { this.ctime = ctime; } public Date getUtime() { return utime; } public void setUtime(Date utime) { this.utime = utime; } public Byte getStat() { return stat; } public void setStat(Byte stat) { this.stat = stat; } } ================================================ FILE: src/main/java/cn/cie/entity/Orderitem.java ================================================ package cn.cie.entity; import java.util.Date; /** * 订单详情 */ public class Orderitem { private Integer id; private Integer gid; private Double price; private Integer code; private Date ctime; private Date utime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getGid() { return gid; } public void setGid(Integer gid) { this.gid = gid; } public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public Date getCtime() { return ctime; } public void setCtime(Date ctime) { this.ctime = ctime; } public Date getUtime() { return utime; } public void setUtime(Date utime) { this.utime = utime; } } ================================================ FILE: src/main/java/cn/cie/entity/Ordermapper.java ================================================ package cn.cie.entity; /** * 订单-订单详情映射 */ public class Ordermapper { private Integer order; private Integer item; public Integer getOrder() { return order; } public void setOrder(Integer order) { this.order = order; } public Integer getItem() { return item; } public void setItem(Integer item) { this.item = item; } } ================================================ FILE: src/main/java/cn/cie/entity/Tag.java ================================================ package cn.cie.entity; /** * 游戏标签 */ public class Tag { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: src/main/java/cn/cie/entity/Tagmapper.java ================================================ package cn.cie.entity; /** * 游戏游戏标签映射 */ public class Tagmapper { private Integer game; private Integer tag; public Integer getGame() { return game; } public void setGame(Integer game) { this.game = game; } public Integer getTag() { return tag; } public void setTag(Integer tag) { this.tag = tag; } } ================================================ FILE: src/main/java/cn/cie/entity/Token.java ================================================ package cn.cie.entity; import java.util.Date; /** * token,用来标识一个用户 */ public class Token { /** * 正常状态 */ public static final Byte STAT_OK = 0; /** * token已过期 */ public static final Byte STAT_EXPIRED = 1; private Integer uid; private String token; private Date expiredTime; private String ip; private String device; private Date ctime; private Byte stat; public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } public Date getExpiredTime() { return expiredTime; } public void setExpiredTime(Date expiredTime) { this.expiredTime = expiredTime; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getDevice() { return device; } public void setDevice(String device) { this.device = device; } public Date getCtime() { return ctime; } public void setCtime(Date ctime) { this.ctime = ctime; } public Byte getStat() { return stat; } public void setStat(Byte stat) { this.stat = stat; } } ================================================ FILE: src/main/java/cn/cie/entity/User.java ================================================ package cn.cie.entity; import java.util.Date; public class User { /** * 未验证,需要邮箱验证 */ public static final Byte STAT_NOT_VALIDATE = 0; /** * 正常 */ public static final Byte STAT_OK = 1; /** * 受限 */ public static final Byte STAT_RESTRICT = 2; /** * 已删除 */ public static final Byte STAT_DEL = 3; private Integer id; private String username; private String password; private String nickname; private String email; private Long phone; private Date ctime; private Date utime; private Byte stat; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Long getPhone() { return phone; } public void setPhone(Long phone) { this.phone = phone; } public Date getCtime() { return ctime; } public void setCtime(Date ctime) { this.ctime = ctime; } public Date getUtime() { return utime; } public void setUtime(Date utime) { this.utime = utime; } public Byte getStat() { return stat; } public void setStat(Byte stat) { this.stat = stat; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", nickname='" + nickname + '\'' + ", email='" + email + '\'' + ", phone=" + phone + ", ctime=" + ctime + ", utime=" + utime + ", stat=" + stat + '}'; } } ================================================ FILE: src/main/java/cn/cie/entity/Validatecode.java ================================================ package cn.cie.entity; /** * 注册时发送到邮箱的验证码,用来验证用户邮箱 */ public class Validatecode { /** * 验证码有效期,默认为10分钟 */ public static final int TIMEOUT = 60 * 10; } ================================================ FILE: src/main/java/cn/cie/entity/dto/GameDTO.java ================================================ package cn.cie.entity.dto; import cn.cie.entity.Game; import cn.cie.entity.Kind; import cn.cie.entity.Tag; import java.util.Date; import java.util.List; /** * Created by RojerAlone on 2017/6/6. */ public class GameDTO { private Integer id; private String creater; private String name; private String desc; private String systemcfg; private Double price; private Double discount; private Date ctime; private Date utime; private Byte stat; private List kinds; private List tags; private List img; public GameDTO() {} public GameDTO(Game game, List tags, List img) { this.id = game.getId(); this.creater = game.getCreater(); this.name = game.getName(); this.desc = game.getDesc(); this.systemcfg = game.getSystemcfg(); this.price = game.getPrice(); this.discount = game.getDiscount(); this.ctime = game.getCtime(); this.utime = game.getUtime(); this.stat = game.getStat(); this.tags = tags; this.img = img; } public GameDTO(Game game, List kinds, List tags, List img) { this.id = game.getId(); this.creater = game.getCreater(); this.name = game.getName(); this.desc = game.getDesc(); this.systemcfg = game.getSystemcfg(); this.price = game.getPrice(); this.discount = game.getDiscount(); this.ctime = game.getCtime(); this.utime = game.getUtime(); this.stat = game.getStat(); this.kinds = kinds; this.tags = tags; this.img = img; } public Integer getId() { return id; } public String getCreater() { return creater; } public String getName() { return name; } public String getDesc() { return desc; } public String getSystemcfg() { return systemcfg; } public Double getPrice() { return price; } public Double getDiscount() { return discount; } public Date getCtime() { return ctime; } public Date getUtime() { return utime; } public Byte getStat() { return stat; } public List getKinds() { return kinds; } public List getTags() { return tags; } public List getImg() { return img; } } ================================================ FILE: src/main/java/cn/cie/entity/dto/OrderDTO.java ================================================ package cn.cie.entity.dto; import cn.cie.entity.Order; import cn.cie.entity.Orderitem; import java.util.Date; import java.util.List; /** * Created by RojerAlone on 2017/6/12. */ public class OrderDTO { /** * 订单id */ private Integer id; /** * 订单所属用户id */ private Integer uid; /** * 订单的总价格 */ private Double total; /** * 订单创建时间 */ private Date ctime; /** * 订单更新时间 */ private Date utime; /** * 订单状态 */ private Byte stat; /** * 订单详细信息 */ private List orderitems; public OrderDTO(Order order, List orderitems) { this.id = order.getId(); this.uid = order.getUid(); this.total = order.getPrice(); this.ctime = order.getCtime(); this.utime = order.getUtime(); this.stat = order.getStat(); this.orderitems = orderitems; } public Integer getId() { return id; } public Integer getUid() { return uid; } public Double getTotal() { return total; } public Date getCtime() { return ctime; } public Date getUtime() { return utime; } public Byte getStat() { return stat; } public List getOrderitems() { return orderitems; } } ================================================ FILE: src/main/java/cn/cie/entity/dto/OrderItemDTO.java ================================================ package cn.cie.entity.dto; import cn.cie.entity.Code; import cn.cie.entity.Game; import cn.cie.entity.Orderitem; import java.util.Date; /** * Created by RojerAlone on 2017/6/12. */ public class OrderItemDTO { private Integer id; private Double price; private String code; private Byte codeStat; private Date ctime; private Date utime; private Game game; public OrderItemDTO(Orderitem orderitem, Game game, Code code) { this.id = orderitem.getId(); this.price = orderitem.getPrice(); this.game = game; this.ctime = orderitem.getCtime(); this.utime = orderitem.getUtime(); if (code != null) { this.code = code.getCode(); this.codeStat = code.getStat(); } } public Integer getId() { return id; } public Double getPrice() { return price; } public String getCode() { return code; } public Byte getCodeStat() { return codeStat; } public Date getCtime() { return ctime; } public Date getUtime() { return utime; } public Game getGame() { return game; } } ================================================ FILE: src/main/java/cn/cie/event/EventConsumer.java ================================================ package cn.cie.event; import cn.cie.event.handler.EventHandler; import cn.cie.utils.RedisUtil; import org.apache.log4j.Logger; import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; /** * Created by RojerAlone on 2017/6/25. * 事件消费者,不断从事件队列中获取事件,根据事件类型处理不同的事件 */ @Service public class EventConsumer implements InitializingBean, ApplicationContextAware, DisposableBean { private final Logger logger = Logger.getLogger(this.getClass()); private ApplicationContext applicationContext; @Autowired private RedisUtil redisUtil; private ThreadPoolExecutor threadPool; /** * 事件类型以及执行这些事件的handler */ private Map> handlers = new HashMap>(); public void afterPropertiesSet() throws Exception { // 从上下文中获取所有的handler Map beans = applicationContext.getBeansOfType(EventHandler.class); if (beans != null) { for (Map.Entry entry : beans.entrySet()) { // 遍历所有的 hander ,将 event-handler 的映射加入 handlers 中 List types = entry.getValue().getSupportEvent(); for (EventType type : types) { if (!handlers.containsKey(type)) { handlers.put(type, new ArrayList()); } handlers.get(type).add(entry.getValue()); } } } // 设置线程池的大小为 CPU 的核数 * 2 threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 2); new Thread(new Runnable() { public void run() { while (true) { EventModel event = redisUtil.lpopObject(EventModel.EVENT_KEY, EventModel.class); if (event == null) { continue; } if (!handlers.containsKey(event.getEventType())) { logger.error("error event type"); continue; } for (EventHandler handler : handlers.get(event.getEventType())) { threadPool.execute(new EventConsumerThread(handler, event)); } } } }).start(); } class EventConsumerThread implements Runnable { private EventHandler handler; private EventModel event; public EventConsumerThread(EventHandler handler, EventModel event) { this.handler = handler; this.event = event; } public void run() { handler.doHandler(event); } } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void destroy() throws Exception { if (threadPool != null) { while (threadPool.getQueue().size() != 0 || threadPool.getActiveCount() != 0) { // 等待所有任务执行完毕 } threadPool.shutdownNow(); } } } ================================================ FILE: src/main/java/cn/cie/event/EventModel.java ================================================ package cn.cie.event; import java.util.HashMap; import java.util.Map; /** * Created by RojerAlone on 2017/6/25. * 事件实体 */ public class EventModel { /** * 在缓存中事件队列的key */ public static final String EVENT_KEY = "event"; /** * 事件类型 */ private EventType eventType; /** * 事件发出者id */ private int fromId; /** * 事件接受者id */ private int toId; /** * 触发事件的实体,比如评论点赞 */ private int entityId; /** * 实体拥有者 */ private int entityOwnerId; /** * 可能会有的额外信息 */ private Map exts = new HashMap(); public EventModel() { } public EventModel(EventType eventType) { this.eventType = eventType; } public EventType getEventType() { return eventType; } public EventModel setEventType(EventType eventType) { this.eventType = eventType; return this; } public int getFromId() { return fromId; } public EventModel setFromId(int fromId) { this.fromId = fromId; return this; } public int getToId() { return toId; } public EventModel setToId(int toId) { this.toId = toId; return this; } public int getEntityId() { return entityId; } public EventModel setEntityId(int entityId) { this.entityId = entityId; return this; } public int getEntityOwnerId() { return entityOwnerId; } public EventModel setEntityOwnerId(int entityOwnerId) { this.entityOwnerId = entityOwnerId; return this; } public String getExts(String key) { return exts.get(key); } public EventModel setExts(String key, String value) { this.exts.put(key, value); return this; } public Map getExts() { return exts; } public void setExts(Map exts) { this.exts = exts; } } ================================================ FILE: src/main/java/cn/cie/event/EventProducer.java ================================================ package cn.cie.event; import cn.cie.utils.RedisUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * Created by RojerAlone on 2017/6/25. * 事件生产者 */ @Component public class EventProducer { @Autowired private RedisUtil redisUtil; public long product(EventModel model) { return redisUtil.rpushObject(EventModel.EVENT_KEY, EventModel.class, model); } } ================================================ FILE: src/main/java/cn/cie/event/EventType.java ================================================ package cn.cie.event; /** * Created by RojerAlone on 2017/6/25. * 异步事件类型 */ public enum EventType { SEND_VALIDATE_EMAIL(1), SEND_FIND_PWD_EMAIL(2); private int value; EventType(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: src/main/java/cn/cie/event/handler/EventHandler.java ================================================ package cn.cie.event.handler; import cn.cie.event.EventModel; import cn.cie.event.EventType; import java.util.List; /** * Created by RojerAlone on 2017/6/25. * 事件处理接口,包含了事件处理以及关心的所有事件 */ public interface EventHandler { /** * 处理事件 */ void doHandler(EventModel eventModel); /** * 获取支持的事件类型 * @return */ List getSupportEvent(); } ================================================ FILE: src/main/java/cn/cie/event/handler/SendFindPwdMailHandler.java ================================================ package cn.cie.event.handler; import cn.cie.event.EventModel; import cn.cie.event.EventType; import cn.cie.utils.MailUtil; import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.List; /** * Created by RojerAlone on 2017/6/25. * 发送找回密码邮件事件 */ @Service public class SendFindPwdMailHandler implements EventHandler { public void doHandler(EventModel model) { MailUtil.sendFetchPwdMail(model.getExts("mail"), model.getExts("code")); } public List getSupportEvent() { return Arrays.asList(EventType.SEND_FIND_PWD_EMAIL); } } ================================================ FILE: src/main/java/cn/cie/event/handler/SendValidateMailHandler.java ================================================ package cn.cie.event.handler; import cn.cie.event.EventModel; import cn.cie.event.EventType; import cn.cie.utils.MailUtil; import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.List; /** * Created by RojerAlone on 2017/6/25. * 发送注册用户时邮箱验证码事件 */ @Service public class SendValidateMailHandler implements EventHandler { public void doHandler(EventModel model) { MailUtil.sendValidateMail(model.getExts("mail"), model.getExts("code")); } public List getSupportEvent() { return Arrays.asList(EventType.SEND_VALIDATE_EMAIL); } } ================================================ FILE: src/main/java/cn/cie/exception/NotFoundException.java ================================================ package cn.cie.exception; import cn.cie.utils.MsgCenter; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; /** * Created by RojerAlone on 2017/6/8. * 自定义异常 */ @ResponseStatus(value = HttpStatus.NOT_FOUND) public class NotFoundException extends RuntimeException { public NotFoundException() { super(MsgCenter.NOT_FOUND); } } ================================================ FILE: src/main/java/cn/cie/interceptor/AdminInterceptor.java ================================================ package cn.cie.interceptor; import cn.cie.utils.UserHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Created by RojerAlone on 2017/6/21. * 管理员权限拦截,如果用户不是管理员,那么跳转到管理员的登陆页面 */ public class AdminInterceptor implements HandlerInterceptor { @Autowired private UserHolder userHolder; public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getRequestURI().equals("/admin/login")) { return true; } if (userHolder.getUser() != null && userHolder.getUser().getUsername().equals("admin")) { return true; } response.sendRedirect("/admin/login"); return false; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } ================================================ FILE: src/main/java/cn/cie/interceptor/AuthInterceptor.java ================================================ package cn.cie.interceptor; import cn.cie.entity.Token; import cn.cie.entity.User; import cn.cie.mapper.TokenMapper; import cn.cie.mapper.UserMapper; import cn.cie.utils.RedisUtil; import cn.cie.utils.UserHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Date; /** * Created by RojerAlone on 2017/6/11. * 拦截器,根据token获取用户身份 * 先从缓存中查找,如果找不到再从数据库中找 */ @Component public class AuthInterceptor implements HandlerInterceptor { @Autowired private TokenMapper tokenMapper; @Autowired private UserMapper userMapper; @Autowired private RedisUtil redisUtil; @Autowired private UserHolder userHolder; public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { // 如果请求静态资源直接pass if (httpServletRequest.getRequestURI().matches("^/img/[\\S]+\\.(png|jpg)$") || httpServletRequest.getRequestURI().matches("^/css/[\\S]+\\.css$") || httpServletRequest.getRequestURI().matches("^/js/[\\S]+\\.js$")) { return true; } String token = null; // 从请求中获取token if (httpServletRequest.getCookies() != null) { for (Cookie cookie : httpServletRequest.getCookies()) { if (cookie.getName().equals("token")) { token = cookie.getValue(); } } } // 如果获取到了token if (token != null) { String userid = redisUtil.get(token); int uid = 0; // 缓存中没有token,从数据库中查找 if (userid == null) { Token t = tokenMapper.selectByTokenAndStat(token, Token.STAT_OK); // 如果token为空或者已经过期但是定时任务还没有来得及更改状态 Date now = new Date(); if (t == null || t.getExpiredTime().before(now)) { return true; } // token不为空,但是缓存中没有了,将token加入缓存中 uid = t.getUid(); long oneday = 86400000L; long expired = t.getExpiredTime().getTime() - now.getTime(); // 如果token剩余有效期大于1天,加入缓存中的token有效期为1天 if (expired > oneday) { redisUtil.putEx(token, String.valueOf(uid), 60 * 60 * 24); } else { // 否则有效期为剩下的时间 redisUtil.putEx(token, String.valueOf(uid), (int) (expired / 1000)); } } else { uid = Integer.valueOf(userid); } // token有效,将当前用户暂时存放起来,之后在所有的地方都可以通过依赖注入的UserHolder获取当前用户 User user = userMapper.selectById(uid); if (user == null) { return true; } userHolder.setUser(user); // 跳过post方法 if (httpServletRequest.getMethod().equals("POST")) { return true; } // 如果用户登陆成功但是没有验证邮箱,跳转到邮箱验证页面(防止请求的url就是验证页时会循环跳转) if (user.getStat().equals(User.STAT_NOT_VALIDATE) && !httpServletRequest.getRequestURI().equals("/user/validate")) { httpServletResponse.sendRedirect("/user/validate"); return false; } else if (user.getStat().equals(User.STAT_DEL)) { // 用户被删除 userHolder.remove(); } } return true; } public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { if (modelAndView == null) { return; } if (httpServletRequest.getMethod().equals("GET") && userHolder.getUser() != null) { modelAndView.getModel().put("user", userHolder.getUser().getNickname()); } } public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { userHolder.remove(); } } ================================================ FILE: src/main/java/cn/cie/interceptor/LoginInterceptor.java ================================================ package cn.cie.interceptor; import cn.cie.utils.UserHolder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Created by RojerAlone on 2017/6/12. * 拦截器,某些功能需要登录才能继续,如果没有登录会被拦截,跳转到登录页 */ @Component public class LoginInterceptor implements HandlerInterceptor { @Autowired private UserHolder userHolder; public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { if (userHolder.getUser() == null) { httpServletResponse.sendRedirect("/login"); return false; } return true; } public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } } ================================================ FILE: src/main/java/cn/cie/mapper/CodeMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Code; public interface CodeMapper { int insert(Code record); Code selectById(Integer id); int update(Code record); } ================================================ FILE: src/main/java/cn/cie/mapper/GameMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Game; import org.apache.ibatis.annotations.Param; import java.util.List; public interface GameMapper { int insert(Game record); Game selectById(Integer id); int selectNums(); List selectAll(); List selectByPage(@Param(value = "startPos") Integer startPos, @Param(value = "size") Integer size); List selectByIds(@Param(value = "ids") List ids); List selectByIdsAndStat(@Param(value = "ids") List ids, @Param(value = "stat") Byte stat); List selectByIdsAndStatAndPage(@Param(value = "ids") List ids, @Param(value = "stat") Byte stat, @Param(value = "startPos") Integer startPos, @Param(value = "size") Integer size); List selectByStat(Byte stat); List selectByStatOrderByDate(Byte stat); List selectByIdsAndInfo(@Param(value = "ids") List ids, @Param(value = "info") String info); List selectByInfo(String info); List selectFreeGames(); int update(Game record); } ================================================ FILE: src/main/java/cn/cie/mapper/ImgMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Img; import org.apache.ibatis.annotations.Param; import java.util.List; public interface ImgMapper { int insert(Img record); int insertBatch(@Param(value = "game") Integer game, @Param(value = "imgs") List imgs); List selectByGame(Integer game); } ================================================ FILE: src/main/java/cn/cie/mapper/KindMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Kind; import org.apache.ibatis.annotations.Param; import java.util.List; public interface KindMapper { int insert(Kind record); Kind selectById(Integer id); List selectAll(); List selectByIds(@Param(value = "ids") List ids); Kind selectByName(String name); List selectIdByLikeName(String name); int delete(Integer id); int update(Kind record); } ================================================ FILE: src/main/java/cn/cie/mapper/KindmapperMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Kindmapper; import org.apache.ibatis.annotations.Param; import java.util.List; public interface KindmapperMapper { int insert(Kindmapper record); int insertKindBatch(@Param(value = "game") Integer game, @Param(value = "kinds") List kinds); int insertGameBatch(@Param(value = "kind") Integer kind, @Param(value = "games") List games); List selectByKind(Integer kind); List selectByGame(Integer game); List selectBatchByKinds(@Param(value = "kinds") List kinds); int deleteByGame(Integer game); int deleteByKind(Integer kind); } ================================================ FILE: src/main/java/cn/cie/mapper/OrderMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Order; import org.apache.ibatis.annotations.Param; import java.util.Date; import java.util.List; public interface OrderMapper { int insert(Order record); Order selectById(Integer id); List selectByUidAndStat(@Param(value = "uid") Integer uid, @Param(value = "stat") Byte stat); List selectByUidAndStatAndPage(@Param(value = "uid") Integer uid, @Param(value = "stat") Byte stat, @Param(value = "startPos") Integer startPos, @Param(value = "size") Integer size); int getOrderNumsByUidAndStat(@Param(value = "uid") Integer uid, @Param(value = "stat") Byte stat); int updateStatByDate(@Param(value = "oldstat") Byte oldstat, @Param(value = "newstat") Byte newstat, @Param(value = "date") Date date); int update(Order record); } ================================================ FILE: src/main/java/cn/cie/mapper/OrderitemMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Orderitem; import org.apache.ibatis.annotations.Param; import java.util.List; public interface OrderitemMapper { int insert(Orderitem record); List selectByIds(@Param(value = "ids") List ids); int update(Orderitem record); } ================================================ FILE: src/main/java/cn/cie/mapper/OrdermapperMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Order; import cn.cie.entity.Ordermapper; import java.util.List; public interface OrdermapperMapper { int insert(Ordermapper record); List selectByOrder(Integer order); } ================================================ FILE: src/main/java/cn/cie/mapper/TagMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Tag; import org.apache.ibatis.annotations.Param; import java.util.List; public interface TagMapper { int insert(Tag record); Tag selectById(Integer id); List selectByIds(@Param(value = "ids") List ids); List selectIdByLikeName(String info); List selectAll(); int update(Tag record); } ================================================ FILE: src/main/java/cn/cie/mapper/TagmapperMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Tagmapper; import org.apache.ibatis.annotations.Param; import java.util.List; public interface TagmapperMapper { int insert(Tagmapper record); List selectByTag(Integer tag); List selectByGame(Integer game); List selectBatchByTags(@Param(value = "tags") List tags); } ================================================ FILE: src/main/java/cn/cie/mapper/TokenMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.Token; import org.apache.ibatis.annotations.Param; import java.util.Date; import java.util.List; public interface TokenMapper { int insert(Token record); Token selectByToken(String token); Token selectByTokenAndStat(@Param(value = "token") String token, @Param(value = "stat") Byte stat); List selectByUid(Integer uid); int updateStatByDate(@Param(value = "date") Date date, @Param(value = "stat") Byte stat); int updateStatByToken(@Param(value = "stat") Byte stat, @Param(value = "token") String token); } ================================================ FILE: src/main/java/cn/cie/mapper/UserMapper.java ================================================ package cn.cie.mapper; import cn.cie.entity.User; import org.apache.ibatis.annotations.Param; import java.util.List; public interface UserMapper { int insert(User record); User selectById(Integer id); User selectByName(String username); User selectByEmail(String email); int selectAllNums(); List selectByPage(@Param(value = "startPos") Integer startPos, @Param(value = "size") Integer size); List selectByStat(Byte stat); int update(User record); int deleteById(Integer id); } ================================================ FILE: src/main/java/cn/cie/schedule/Scheduler.java ================================================ package cn.cie.schedule; import cn.cie.services.OrderService; import cn.cie.services.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * Created by RojerAlone on 2017/6/9. * 定时任务 * http://blog.csdn.net/sd4000784/article/details/7745947 */ @Component public class Scheduler { @Autowired private UserService userService; @Autowired private OrderService orderService; @Scheduled(fixedRate = 1000 * 60 * 3) public void delNotValidateUser() { userService.delNotValidateUser(); } @Scheduled(fixedRate = 1000 * 60 * 10) public void expireToken() { userService.expireToken(); } @Scheduled(fixedRate = 1000 * 60) public void cancelOrder() { orderService.autoCancelOrder(); } } ================================================ FILE: src/main/java/cn/cie/services/AdminService.java ================================================ package cn.cie.services; import cn.cie.entity.Game; import cn.cie.utils.Result; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.Date; import java.util.List; /** * Created by RojerAlone on 2017/6/15. * 管理员相关 */ public interface AdminService { /** * 管理员登陆 * @param username * @param password * @return */ Result login(String username, String password); /** * 获取所有的用户 * @param page 当前的页数 * @return User Page */ Result getUser(int page); /** * 限制账户操作 * @param uid * @return */ Result restrict(Integer uid); /** * 解除账户限制 * @param uid * @return */ Result relieve(Integer uid); /** * 删除用户 * @param uid * @return */ Result delete(Integer uid); /** * 获取所有游戏 * @param page 获取游戏的页数 * @return GameDTO Page */ Result getGames(int page); /** * 添加游戏 * @param game 游戏实体,需要游戏名字、开发者、描述、配置、价格 * @param kind 游戏种类,数组类型 * @param header 游戏图片 * @param pics 至少5张游戏截图 * @param path 图片存储路径 * @return */ Result addGame(Game game, Integer[] kind, MultipartFile header, MultipartFile[] pics, String path) throws IOException; /** * 更新游戏信息 * @param game * @return */ Result updateGameInfo(Game game); /** * 获取游戏种类 * @param game * @return */ Result getGameKind(Integer game); /** * 更新游戏的种类 * @param game * @param kinds * @return */ Result updateGameKind(Integer game, List kinds); /** * 将游戏上架 * @param id * @param date 上架时间 * @return */ Result upGame(Integer id, Date date); /** * 下架游戏 * @param id * @return */ Result downGame(Integer id); /** * 添加游戏种类 * @param name * @return */ Result addKind(String name); /** * 管理种类对应的游戏 * @param kind * @param games * @return */ Result managerKind(Integer kind, List games); /** * 获取所有的游戏 * @return */ Result getAllGames(); } ================================================ FILE: src/main/java/cn/cie/services/GameService.java ================================================ package cn.cie.services; import cn.cie.entity.dto.GameDTO; import cn.cie.utils.Result; import java.util.List; /** * Created by RojerAlone on 2017/6/8. */ public interface GameService { /** * 根据游戏id获取游戏详细信息 * @param id * @return */ Result getById(Integer id); /** * 获取随机图片,用于每日推荐 * @return */ Result> getRandomGames(); /** * 从缓存中获取最新的5个游戏,如果没有就从数据库中获取 * @return */ Result> newestGames(); /** * 从缓存中获取最新的5个准备上架的游戏,如果没有就从数据库中获取 * @return */ Result> preUpGames(); /** * 搜索,从种类、标签、游戏信息中搜索 * @param info * @return */ Result> search(String info); /** * 获取免费游戏 * @return */ Result getFreeGames(); /** * 判断游戏是否存在 * @param id * @return */ boolean exists(Integer id); } ================================================ FILE: src/main/java/cn/cie/services/KindService.java ================================================ package cn.cie.services; import cn.cie.entity.Kind; import cn.cie.entity.dto.GameDTO; import cn.cie.utils.Result; import java.util.List; /** * Created by RojerAlone on 2017/6/6. */ public interface KindService { /** * 根据种类id获取种类名字,如果不存在返回null * @param id * @return */ String getNameById(Integer id); /** * 获取所有的种类 * @return */ Result getAll(); /** * 根据种类获取所有的游戏,包括游戏信息和游戏的种类、标签 * @param kind * @param page * @return */ Result> getGamesByKind(int kind, int page); } ================================================ FILE: src/main/java/cn/cie/services/OrderService.java ================================================ package cn.cie.services; import cn.cie.utils.Result; import java.util.List; /** * Created by RojerAlone on 2017/6/8. */ public interface OrderService { /** * 创建新订单 * @param uid * @param gids * @return */ Result addOrders(int uid, List gids); /** * 取消订单 * @param orderid * @return */ Result cancelOrder(int uid, int orderid); /** * 支付订单 * @param uid * @param orderid * @return */ Result pay(int uid, int orderid); /** * 判断订单是否存在 * @param orderid * @return */ boolean exists(int orderid); /** * 获取待支付订单 * @param uid * @return */ Result getNotPayOrders(int uid, int page); /** * 获取支付过的订单 * @param uid * @return */ Result getPaidOrders(int uid, int page); /** * 获取取消的订单 * @param uid * @return */ Result getCancelOrders(int uid, int page); /** * 自动取消15分钟还未支付的订单,定时器每1分钟检查一次 */ void autoCancelOrder(); } ================================================ FILE: src/main/java/cn/cie/services/TagService.java ================================================ package cn.cie.services; import cn.cie.entity.Tag; import cn.cie.entity.dto.GameDTO; import cn.cie.utils.Result; import java.util.List; /** * Created by RojerAlone on 2017/6/7. */ public interface TagService { /** * 根据标签id获取标签名字,如果不存在返回null * @param id * @return */ String getNameById(Integer id); /** * 获取所有的标签 * @return */ Result> getAll(); /** * 添加标签,不绑定到游戏 * @param name * @return */ Result addTag(String name); /** * 添加标签并绑定到游戏 * @param name * @param game * @return */ Result addTag(String name, Integer game); /** * 绑定标签到游戏 * @param tag * @param game * @return */ Result addTag(Integer tag, Integer game); /** * 根据标签获取所有游戏 * @param tag * @param page * @return */ Result> getGamesByTag(Integer tag, Integer page); } ================================================ FILE: src/main/java/cn/cie/services/UserService.java ================================================ package cn.cie.services; import cn.cie.entity.User; import cn.cie.utils.Result; /** * Created by RojerAlone on 2017/5/31. */ public interface UserService { /** * 注册 * @param user * @return */ Result register(User user); /** * 给用户注册的邮箱发送验证码 * @param user * @return */ Result sendMail(User user); /** * 邮箱验证 * @param uid * @param code * @return */ Result validate(Integer uid, String code); /** * 登录 * 登陆时如果选择了“记住我”选项,那么token保持7天,否则保存1天 * 登陆成功,将token存在数据库中记录,同时存入缓存,过期时间为1天 * 每次请求时拦截器先从缓存中查找,如果没有再去数据库中查找 * @param username 用户名 * @param password 密码 * @param remember 是否保持登陆(token生存周期为7天) * @return */ Result login(String username, String password, boolean remember, String ip, String device); /** * 登出 * @return */ Result logout(String token); /** * 更新用户信息 * @param user * @return */ Result updateUserInfo(User user); /** * 更新密码 * @param password * @return */ Result updatePassword(String password); /** * 忘记密码 * @param password * @param code * @return */ Result forgetPassword(String password, String email, String code); /** * 忘记密码时需要给邮箱发送验证码 * @param email * @return */ Result sendFetchPwdMail(String email); /** * 删除没有验证的用户 */ void delNotValidateUser(); /** * 删除已经过期的token */ void expireToken(); } ================================================ FILE: src/main/java/cn/cie/services/impl/AdminServiceImpl.java ================================================ package cn.cie.services.impl; import cn.cie.entity.*; import cn.cie.entity.dto.GameDTO; import cn.cie.mapper.*; import cn.cie.services.AdminService; import cn.cie.utils.*; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.*; /** * Created by RojerAlone on 2017/6/15. */ @Service public class AdminServiceImpl implements AdminService { @Autowired private UserMapper userMapper; @Autowired private GameMapper gameMapper; @Autowired private KindMapper kindMapper; @Autowired private KindmapperMapper kindmapperMapper; @Autowired private TagMapper tagMapper; @Autowired private TagmapperMapper tagmapperMapper; @Autowired private ImgMapper imgMapper; @Autowired private RedisUtil redisUtil; public Result login(String username, String password) { if (username == null || password == null) { return Result.fail(MsgCenter.EMPTY_LOGIN); } else if (username.equals("admin") == false) { return Result.fail(MsgCenter.LOGIN_NOT_ALLOW); } User user = userMapper.selectByName(username); // 用户名不存在或者密码错误或者用户已经被删除 if (user == null || !user.getPassword().equals(PasswordUtil.pwd2Md5(password)) || user.getStat().equals(User.STAT_DEL)) { return Result.fail(MsgCenter.ERROR_LOGIN); } else if (user.getStat().equals(User.STAT_RESTRICT)) { return Result.fail(MsgCenter.USER_RESTRICT); } else { String token = UUID.randomUUID().toString().replaceAll("-", ""); redisUtil.putEx(token, String.valueOf(user.getId()), 60 * 60 * 24); return Result.success(token); } } public Result getUser(int page) { PageUtil pageUtil = new PageUtil(userMapper.selectAllNums(), page); Map map = new HashMap(); map.put("user", userMapper.selectByPage(pageUtil.getStartPos(), pageUtil.getSize())); map.put("page", pageUtil); return Result.success(map); } public Result restrict(Integer uid) { User user = new User(); user.setId(uid); user.setStat(User.STAT_RESTRICT); if (1 == userMapper.update(user)) { return Result.success(); } else { return Result.fail(""); } } public Result relieve(Integer uid) { User user = new User(); user.setId(uid); user.setStat(User.STAT_OK); if (1 == userMapper.update(user)) { return Result.success(); } else { return Result.fail(""); } } public Result delete(Integer uid) { User user = new User(); user.setId(uid); user.setStat(User.STAT_DEL); if (1 == userMapper.update(user)) { return Result.success(); } else { return Result.fail(""); } } public Result getGames(int page) { PageUtil pageUtil = new PageUtil(gameMapper.selectNums(), page); List games = gameMapper.selectByPage(pageUtil.getStartPos(), pageUtil.getSize()); Map map = new HashMap(); map.put("game", paresGameDTO(games)); map.put("page", pageUtil); return Result.success(map); } @Transactional public Result addGame(Game game, Integer[] kind, MultipartFile header, MultipartFile[] pics, String path) throws IOException { // 判断游戏信息 if (StringUtils.isBlank(game.getCreater()) || StringUtils.isBlank(game.getName()) || StringUtils.isBlank(game.getDesc()) || StringUtils.isBlank(game.getSystemcfg()) || game.getPrice() == null || game.getPrice() < 0) { return Result.fail(MsgCenter.ERROR_PARAMS); } // 判断文件类型是否合法 if (!header.getContentType().equalsIgnoreCase("image/jpeg") && !header.getContentType().equalsIgnoreCase("image/png")) { return Result.fail(MsgCenter.ERROR_FILE_TYPE); } for (MultipartFile pic : pics) { if (!pic.getContentType().equalsIgnoreCase("image/jpeg") && !pic.getContentType().equalsIgnoreCase("image/png")) { return Result.fail(MsgCenter.ERROR_FILE_TYPE); } } gameMapper.insert(game); if (kind != null && kind.length > 0) { kindmapperMapper.insertKindBatch(game.getId(), Arrays.asList(kind)); } Img image = new Img(); image.setGame(game.getId()); String headertype = null; if (header.getContentType().equalsIgnoreCase("image/jpeg")) { headertype = "jpg"; } else if (header.getContentType().equalsIgnoreCase("image/png")) { headertype = "png"; } image.setImg("/" + game.getId() + "/header." + headertype); imgMapper.insert(image); FileUtils.copyInputStreamToFile(header.getInputStream(), new File(path + "/" + game.getId(), "header." + headertype)); int index = 1; List imgs = new ArrayList(); for (MultipartFile pic : pics) { String type = null; if (pic.getContentType().equalsIgnoreCase("image/jpeg")) { type = "jpg"; } else if (pic.getContentType().equalsIgnoreCase("image/png")) { type = "png"; } // 拼接写入数据库的图片信息 String img = "/" + game.getId() + "/" + index + "." + type; imgs.add(img); FileUtils.copyInputStreamToFile(pic.getInputStream(), new File(path + "/" + game.getId(), index + "." + type)); index++; } imgMapper.insertBatch(game.getId(), imgs); return Result.success(); } public Result updateGameInfo(Game game) { if (game.getId() == null) { return Result.fail(MsgCenter.ERROR_PARAMS); } gameMapper.update(game); return Result.success(); } public Result getGameKind(Integer game) { if (gameMapper.selectById(game) == null) { return Result.fail(MsgCenter.ERROR_PARAMS); } List kindIds = kindmapperMapper.selectByGame(game); List kinds = kindMapper.selectByIds(kindIds); return Result.success(kinds); } @Transactional public Result updateGameKind(Integer game, List kinds) { kindmapperMapper.deleteByGame(game); kindmapperMapper.insertKindBatch(game, kinds); return Result.success(); } public Result upGame(Integer id, Date date) { Game game = gameMapper.selectById(id); // 如果没有这个游戏返回参数错误 if (game == null) { return Result.fail(MsgCenter.ERROR_PARAMS); } game.setStat(Game.STAT_OK); if (date == null) { game.setUtime(new Date()); } else { game.setUtime(date); } if (1 == gameMapper.update(game)) { redisUtil.delete(RedisUtil.NEWESTGAME); // 上架游戏后将缓存中的最新游戏清空 return Result.success(); } return Result.fail(MsgCenter.ERROR); } public Result downGame(Integer id) { Game game = gameMapper.selectById(id); // 如果没有这个游戏返回参数错误 if (game == null) { return Result.fail(MsgCenter.ERROR_PARAMS); } game.setStat(Game.STAT_DEL); if (1 == gameMapper.update(game)) { redisUtil.delete(RedisUtil.NEWESTGAME); // 下架游戏后将缓存中的最新游戏清空 return Result.success(); } return Result.fail(MsgCenter.ERROR); } @Transactional public Result addKind(String name) { Kind kind = kindMapper.selectByName(name); if (kind != null) { return Result.fail(MsgCenter.NAME_EXISTS); } kind = new Kind(); kind.setName(name); if (1 == kindMapper.insert(kind)) { redisUtil.rpushObject("kinds", Kind.class, kind); // 添加到缓存中 return Result.success(); } else { return Result.fail(MsgCenter.ERROR); } } @Transactional public Result managerKind(Integer kind, List games) { kindmapperMapper.deleteByKind(kind); kindmapperMapper.insertGameBatch(kind, games); return Result.success(); } public Result getAllGames() { List games = gameMapper.selectAll(); List gameDTOS = new ArrayList(); for (Game game : games) { List kinds = null; List kindIds = kindmapperMapper.selectByGame(game.getId()); // 根据游戏id获取所有的种类id if (kindIds.size() != 0) { kinds = kindMapper.selectByIds(kindIds); // 根据种类id获取种类信息 } GameDTO dto = new GameDTO(game, kinds, null, null); gameDTOS.add(dto); } return Result.success(gameDTOS); } private List paresGameDTO(List games) { List gameDTOS = new ArrayList(); for (Game game : games) { List tags = null; List kinds = null; List tagIds = tagmapperMapper.selectByGame(game.getId()); // 获取游戏的标签id if (tagIds.size() != 0) { tags = tagMapper.selectByIds(tagIds); // 根据id获取所有的标签信息 } List img = imgMapper.selectByGame(game.getId()); // 获取所有的图片 List kindIds = kindmapperMapper.selectByGame(game.getId()); // 根据游戏id获取所有的种类id if (kindIds.size() != 0) { kinds = kindMapper.selectByIds(kindIds); // 根据种类id获取种类信息 } GameDTO dto = new GameDTO(game, kinds, tags, img); gameDTOS.add(dto); } return gameDTOS; } } ================================================ FILE: src/main/java/cn/cie/services/impl/GameServiceImpl.java ================================================ package cn.cie.services.impl; import cn.cie.entity.Game; import cn.cie.entity.Kind; import cn.cie.entity.Tag; import cn.cie.entity.dto.GameDTO; import cn.cie.mapper.*; import cn.cie.services.GameService; import cn.cie.utils.MsgCenter; import cn.cie.utils.RedisUtil; import cn.cie.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RequestMapping; import java.util.*; /** * Created by RojerAlone on 2017/6/8. */ @Service public class GameServiceImpl implements GameService { @Autowired private GameMapper gameMapper; @Autowired private KindMapper kindMapper; @Autowired private KindmapperMapper kindmapperMapper; @Autowired private TagmapperMapper tagmapperMapper; @Autowired private TagMapper tagMapper; @Autowired private ImgMapper imgMapper; @Autowired private RedisUtil redisUtil; public Result getById(Integer id) { Game game = gameMapper.selectById(id); if (game == null) { return Result.fail(MsgCenter.ERROR_PARAMS); } List tagIds = tagmapperMapper.selectByGame(id); List tags = null; if (tagIds.size() != 0) { tags = tagMapper.selectByIds(tagIds); } List img = imgMapper.selectByGame(game.getId()); GameDTO res = new GameDTO(game, tags, img); return Result.success(res); } public Result> getRandomGames() { // 先从缓存中取数据,如果没有再自动生成 List res = redisUtil.lall("everyday", GameDTO.class); if (res == null || res.size() == 0) { List allgames = gameMapper.selectByStat(Game.STAT_OK); int count = allgames.size(); Set numSet = new HashSet(); Random random = new Random(); List games = new ArrayList(); // 如果游戏数量大于5个就随机取5个,否则取全部的 if (count > 5) { while (numSet.size() < 5) { numSet.add(random.nextInt(count)); } Iterator i = numSet.iterator(); while (i.hasNext()) { games.add(allgames.get((Integer) i.next())); } } else { games = allgames; } res = paresGameDTO(games); // 将数据存入缓存中 int tmp = 1000 * 3600 * 24; long zero = (System.currentTimeMillis() / tmp * tmp + tmp - TimeZone.getDefault().getRawOffset()) / 1000; //明天零点零分零秒的unix时间戳 redisUtil.rpushObjectExAtTime(RedisUtil.EVERYDAY, GameDTO.class, zero, res.toArray()); } return Result.success(res); } public Result> newestGames() { List res = redisUtil.lall(RedisUtil.NEWESTGAME, GameDTO.class); if (res == null || res.size() == 0) { List games = gameMapper.selectByStatOrderByDate(Game.STAT_OK); res = paresGameDTO(games); redisUtil.rpushObjectEx(RedisUtil.NEWESTGAME, GameDTO.class, 60 * 10, res.toArray()); } return Result.success(res); } public Result> preUpGames() { List res = redisUtil.lall(RedisUtil.PRE_UP_GAMES, GameDTO.class); if (res == null || res.size() == 0) { List games = gameMapper.selectByStatOrderByDate(Game.STAT_PRE); res = paresGameDTO(games); redisUtil.rpushObjectEx(RedisUtil.PRE_UP_GAMES, GameDTO.class, 60 * 10, res.toArray()); } return Result.success(res); } public Result> search(String info) { List kindIds = kindMapper.selectIdByLikeName(info); List tagIds = tagMapper.selectIdByLikeName(info); List gameIdsOfKind = null; if (kindIds != null && kindIds.size() > 0) { gameIdsOfKind = kindmapperMapper.selectBatchByKinds(kindIds); } List gameIdsOfTag = null; if (tagIds != null && tagIds.size() > 0) { gameIdsOfTag = tagmapperMapper.selectBatchByTags(tagIds); } Set tmpGameIds = new HashSet(); if (gameIdsOfKind != null && gameIdsOfKind.size() > 0) { tmpGameIds.addAll(gameIdsOfKind); } if (gameIdsOfTag != null && gameIdsOfTag.size() > 0) { tmpGameIds.addAll(gameIdsOfTag); } List games = null; if (tmpGameIds.size() > 0) { List gameIds = new ArrayList(tmpGameIds); games = gameMapper.selectByIdsAndInfo(gameIds, info); } else { games = gameMapper.selectByInfo(info); } return Result.success(paresGameDTO(games)); } public Result getFreeGames() { List games = gameMapper.selectFreeGames(); return Result.success(paresGameDTO(games)); } public boolean exists(Integer id) { return gameMapper.selectById(id) != null; } private List paresGameDTO(List games) { List gameDTOS = new ArrayList(); for (Game game : games) { List img = imgMapper.selectByGame(game.getId()); // 获取所有的图片 GameDTO dto = new GameDTO(game, null, img); gameDTOS.add(dto); } return gameDTOS; } } ================================================ FILE: src/main/java/cn/cie/services/impl/KindServiceImpl.java ================================================ package cn.cie.services.impl; import cn.cie.entity.Game; import cn.cie.entity.Kind; import cn.cie.entity.Tag; import cn.cie.entity.dto.GameDTO; import cn.cie.mapper.*; import cn.cie.services.KindService; import cn.cie.utils.MsgCenter; import cn.cie.utils.PageUtil; import cn.cie.utils.RedisUtil; import cn.cie.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.lang.reflect.Array; import java.util.*; /** * Created by RojerAlone on 2017/6/6. */ @Service public class KindServiceImpl implements KindService { @Autowired private KindMapper kindMapper; @Autowired private KindmapperMapper kindmapperMapper; @Autowired private GameMapper gameMapper; @Autowired private ImgMapper imgMapper; @Autowired private TagMapper tagMapper; @Autowired private TagmapperMapper tagmapperMapper; @Autowired private RedisUtil redisUtil; public String getNameById(Integer id) { Kind kind = kindMapper.selectById(id); if (kind == null) { return null; } return kind.getName(); } public Result getAll() { List kinds = redisUtil.lall(RedisUtil.KINDS, Kind.class); // 如果缓存中没有,从数据库中查询,并且添加到缓存中 if (kinds == null || kinds.size() == 0) { List data = kindMapper.selectAll(); redisUtil.rpushObject(RedisUtil.KINDS, Kind.class, data.toArray()); return Result.success(data); } return Result.success(kinds); } public Result> getGamesByKind(int kind, int page) { if (kindMapper.selectById(kind) == null) { return Result.fail(MsgCenter.NOT_FOUND); } List gameIds = kindmapperMapper.selectByKind(kind); // 如果没有就返回 if (gameIds == null || gameIds.size() == 0) { return Result.success(); } List games = gameMapper.selectByIdsAndStat(gameIds, Game.STAT_OK); PageUtil pageUtil = new PageUtil(games.size(), page); // 假分页 int size = pageUtil.getStartPos() + 10 > games.size() - 1 ? games.size() : pageUtil.getStartPos() + 10; List gameDTOS = paresGameDTO(games.subList(pageUtil.getStartPos(), size)); Map map = new HashMap(); map.put("game", gameDTOS); map.put("page", pageUtil); return Result.success(map); } private List paresGameDTO(List games) { List gameDTOS = new ArrayList(); for (Game game : games) { List tags = null; List tagIds = tagmapperMapper.selectByGame(game.getId()); // 获取游戏的标签id if (tagIds.size() != 0) { tags = tagMapper.selectByIds(tagIds); // 根据id获取所有的标签信息 } List img = imgMapper.selectByGame(game.getId()); // 获取所有的图片 GameDTO dto = new GameDTO(game, tags, img); gameDTOS.add(dto); } return gameDTOS; } } ================================================ FILE: src/main/java/cn/cie/services/impl/OrderServiceImpl.java ================================================ package cn.cie.services.impl; import cn.cie.entity.*; import cn.cie.entity.dto.OrderDTO; import cn.cie.entity.dto.OrderItemDTO; import cn.cie.mapper.*; import cn.cie.services.OrderService; import cn.cie.utils.MsgCenter; import cn.cie.utils.PageUtil; import cn.cie.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; /** * Created by RojerAlone on 2017/6/12. */ @Service public class OrderServiceImpl implements OrderService { @Autowired private OrderMapper orderMapper; @Autowired private OrderitemMapper orderitemMapper; @Autowired private GameMapper gameMapper; @Autowired private OrdermapperMapper ordermapperMapper; @Autowired private CodeMapper codeMapper; @Transactional public Result addOrders(int uid, List gids) { Order order = new Order(); order.setUid(uid); orderMapper.insert(order); double total = 0; // 对所有的游戏进行存储、计价 for (Integer gid : gids) { Game game = gameMapper.selectById(gid); if (game.getStat() != Game.STAT_OK) { return Result.fail(MsgCenter.ERROR_PARAMS); } Orderitem item = new Orderitem(); item.setGid(gid); // 如果现价不为空,那么就计算现价 if (game.getDiscount() != null) { total += game.getDiscount(); item.setPrice(game.getDiscount()); } else { total += game.getPrice(); item.setPrice(game.getPrice()); } orderitemMapper.insert(item); Ordermapper mapper = new Ordermapper(); mapper.setItem(item.getId()); mapper.setOrder(order.getId()); ordermapperMapper.insert(mapper); } // 更新所有游戏的价格 order.setPrice(total); orderMapper.update(order); return Result.success(order); } public Result cancelOrder(int uid, int orderid) { Order order = orderMapper.selectById(orderid); // 如果orderid错误或者用户与订单不匹配,就返回错误 if (order == null || order.getUid() != uid) { return Result.fail(MsgCenter.ERROR_PARAMS); } order.setStat(Order.STAT_CANCEL); if (1 == orderMapper.update(order)) { return Result.success(); } return Result.fail(MsgCenter.ERROR); } @Transactional public Result pay(int uid, int orderid) { Order order = orderMapper.selectById(orderid); // 如果orderid错误或者用户与订单不匹配,就返回错误 if (order == null || order.getUid() != uid) { return Result.fail(MsgCenter.ERROR_PARAMS); } order.setStat(Order.STAT_PAY); orderMapper.update(order); List orderitems = ordermapperMapper.selectByOrder(orderid); List orderitemList = orderitemMapper.selectByIds(orderitems); for (Orderitem item : orderitemList) { // 生产激活码并插入数据库 String uuid = UUID.randomUUID().toString(); Code code = new Code(); code.setItem(item.getId()); code.setUid(uid); code.setCode(uuid); codeMapper.insert(code); // 插入code后更新orderitem的对应codeid item.setCode(code.getId()); orderitemMapper.update(item); } return Result.success(); } public boolean exists(int orderid) { return orderMapper.selectById(orderid) != null; } public Result getNotPayOrders(int uid, int page) { PageUtil pageUtil = new PageUtil(orderMapper.getOrderNumsByUidAndStat(uid, Order.STAT_NOT_PAY), page); Map map = new HashMap(); map.put("order", parseOrderByStatAndPage(uid, Order.STAT_NOT_PAY, pageUtil)); map.put("page", pageUtil); return Result.success(map); } public Result getPaidOrders(int uid, int page) { PageUtil pageUtil = new PageUtil(orderMapper.getOrderNumsByUidAndStat(uid, Order.STAT_PAY), page); Map map = new HashMap(); map.put("order", parseOrderByStatAndPage(uid, Order.STAT_PAY, pageUtil)); map.put("page", pageUtil); return Result.success(map); } public Result getCancelOrders(int uid, int page) { PageUtil pageUtil = new PageUtil(orderMapper.getOrderNumsByUidAndStat(uid, Order.STAT_CANCEL), page); Map map = new HashMap(); map.put("order", parseOrderByStatAndPage(uid, Order.STAT_CANCEL, pageUtil)); map.put("page", pageUtil); return Result.success(map); } public void autoCancelOrder() { Date date = new Date(); date.setTime(date.getTime() - 1000 * 60 * 15); // 过期时间为15分钟 orderMapper.updateStatByDate(Order.STAT_NOT_PAY, Order.STAT_CANCEL, date); } private List parseOrderByStatAndPage(Integer uid, Byte stat, PageUtil pageUtil) { List res = new ArrayList(); List orders = orderMapper.selectByUidAndStatAndPage(uid, stat, pageUtil.getStartPos(), pageUtil.getSize()); for (Order order : orders) { List orderids = ordermapperMapper.selectByOrder(order.getId()); // 获取订单内所有的订单详情id List orderitemList = orderitemMapper.selectByIds(orderids); // 根据订单详情id获取订单详情 List orderItemDTOList = new ArrayList(); // 拼接订单详情信息,包括订单对应的游戏和激活码 for (Orderitem orderitem : orderitemList) { Game game = gameMapper.selectById(orderitem.getGid()); // 游戏信息 Code code; // 如果code不为空那么获取code if (orderitem.getCode() != null) { code = codeMapper.selectById(orderitem.getCode()); // 激活码信息 } else { code = null; } orderItemDTOList.add(new OrderItemDTO(orderitem, game, code)); } res.add(new OrderDTO(order, orderItemDTOList)); } return res; } } ================================================ FILE: src/main/java/cn/cie/services/impl/TagServiceImpl.java ================================================ package cn.cie.services.impl; import cn.cie.entity.Game; import cn.cie.entity.Tag; import cn.cie.entity.Tagmapper; import cn.cie.entity.dto.GameDTO; import cn.cie.mapper.GameMapper; import cn.cie.mapper.ImgMapper; import cn.cie.mapper.TagMapper; import cn.cie.mapper.TagmapperMapper; import cn.cie.services.TagService; import cn.cie.utils.MsgCenter; import cn.cie.utils.PageUtil; import cn.cie.utils.Result; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by RojerAlone on 2017/6/7. */ @Service public class TagServiceImpl implements TagService { @Autowired private TagMapper tagMapper; @Autowired private TagmapperMapper tagmapperMapper; @Autowired private GameMapper gameMapper; @Autowired private ImgMapper imgMapper; public String getNameById(Integer id) { Tag tag = tagMapper.selectById(id); if (tag == null) { return null; } return tag.getName(); } public Result> getAll() { return Result.success(tagMapper.selectAll()); } public Result addTag(String name) { Tag tag = new Tag(); tag.setName(name); if (1 == tagMapper.insert(tag)) { return Result.success(tag); } else { return Result.fail(MsgCenter.ERROR); } } @Transactional public Result addTag(String name, Integer game) { // 如果没有这个游戏,就返回404 if (gameMapper.selectById(game) == null) { return Result.fail(MsgCenter.NOT_FOUND); } Result result = addTag(name); if (result.isSuccess()) { Tagmapper tagmapper = new Tagmapper(); tagmapper.setGame(game); tagmapper.setTag(((Tag) result.getData()).getId()); if (1 == tagmapperMapper.insert(tagmapper)) { return Result.success(); } } return Result.fail(MsgCenter.ERROR); } public Result addTag(Integer tag, Integer game) { // 如果没有这个游戏,就返回404 if (gameMapper.selectById(game) == null) { return Result.fail(MsgCenter.NOT_FOUND); } Tagmapper tagmapper = new Tagmapper(); tagmapper.setGame(game); tagmapper.setTag(tag); if (1 == tagmapperMapper.insert(tagmapper)) { return Result.success(); } else { return Result.fail(MsgCenter.ERROR); } } public Result> getGamesByTag(Integer tag, Integer page) { // 没有这个标签,返回404 if (tagMapper.selectById(tag) == null) { return Result.fail(MsgCenter.NOT_FOUND); } List gameIds = tagmapperMapper.selectByTag(tag); // 根据标签获取所有的游戏ID List games = gameMapper.selectByIdsAndStat(gameIds, Game.STAT_OK); PageUtil pageUtil = new PageUtil(games.size(), page); // 假分页 int size = pageUtil.getStartPos() + 10 > games.size() - 1 ? games.size() : pageUtil.getStartPos() + 10; List gameDTOS = paresGameDTO(games.subList(pageUtil.getStartPos(), size)); Map map = new HashMap(); map.put("game", gameDTOS); map.put("page", pageUtil); return Result.success(map); } private List paresGameDTO(List games) { List gameDTOS = new ArrayList(); for (Game game : games) { List tags = null; List tagIds = tagmapperMapper.selectByGame(game.getId()); // 获取游戏的标签id if (tagIds.size() != 0) { tags = tagMapper.selectByIds(tagIds); // 根据id获取所有的标签信息 } List img = imgMapper.selectByGame(game.getId()); // 获取所有的图片 GameDTO dto = new GameDTO(game, tags, img); gameDTOS.add(dto); } return gameDTOS; } } ================================================ FILE: src/main/java/cn/cie/services/impl/UserServiceImpl.java ================================================ package cn.cie.services.impl; import cn.cie.entity.Token; import cn.cie.entity.User; import cn.cie.event.EventModel; import cn.cie.event.EventProducer; import cn.cie.event.EventType; import cn.cie.utils.UserHolder; import cn.cie.entity.Validatecode; import cn.cie.mapper.TokenMapper; import cn.cie.mapper.UserMapper; import cn.cie.services.UserService; import cn.cie.utils.*; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.regex.Pattern; /** * Created by RojerAlone on 2017/5/31. */ @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Autowired private TokenMapper tokenMapper; @Autowired private UserHolder userHolder; @Autowired private RedisUtil redisUtil; @Autowired private EventProducer eventProducer; @Transactional public Result register(User user) { // 验证参数是否合法 if (StringUtils.isBlank(user.getUsername())) { return Result.fail(MsgCenter.EMPTY_USERNAME); } else if (StringUtils.isBlank(user.getNickname())) { return Result.fail(MsgCenter.EMPTY_NICKNAME); } else if (user.getNickname().length() > 10) { return Result.fail(MsgCenter.ERROR_NICINAME); } else if (StringUtils.isBlank(user.getPassword())) { return Result.fail(MsgCenter.EMPTY_PASSWORD); } else if (16 < user.getPassword().replaceAll(" ", "").length() || user.getPassword().replaceAll(" ", "").length() < 6) { return Result.fail(MsgCenter.ERROR_PASSWORD_FORMAT); } else if (StringUtils.isBlank(user.getEmail())) { return Result.fail(MsgCenter.EMPTY_EMAIL); } else if (Pattern.compile("^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"). matcher(user.getEmail()).find() == false) { // 判断邮箱格式是否正确 return Result.fail(MsgCenter.ERROR_EMAIL); } else if (user.getPhone() == null) { return Result.fail(MsgCenter.EMPTY_PHONE); } else if (Pattern.compile("1[3|5|7|8|]\\d{9}").matcher(user.getPhone().toString()).find() == false) { // 验证手机号码是否格式正确 return Result.fail(MsgCenter.ERROR_PHONE); } else if (userMapper.selectByName(user.getUsername()) != null) { // 用户名已经被注册 return Result.fail(MsgCenter.USER_USERNAME_EXISTS); } else if (userMapper.selectByEmail(user.getEmail()) != null) { // 邮箱已被注册 return Result.fail(MsgCenter.EMAIL_REGISTERED); } user.setPassword(PasswordUtil.pwd2Md5(user.getPassword().replaceAll(" ", ""))); // 加密密码 if (1 == userMapper.insert(user)) { // 注册成功 String uuid = UUID.randomUUID().toString(); redisUtil.putEx("validatecode_" + user.getId(), uuid, Validatecode.TIMEOUT); // 存入redis eventProducer.product(new EventModel(EventType.SEND_VALIDATE_EMAIL).setExts("mail", user.getEmail()).setExts("code", uuid)); return Result.success(user.getId()); } return Result.fail(MsgCenter.ERROR); } @Transactional public Result sendMail(User user) { if (user.getStat().equals(User.STAT_OK)) { // 用户已经验证过了 return Result.fail(MsgCenter.USER_VALIDATED); } String uuid = UUID.randomUUID().toString(); // 将数据存入redis中,固定时间后过期 redisUtil.putEx("validatecode_" + user.getId(), uuid, Validatecode.TIMEOUT); // 将邮件发送事件添加到异步事件队列中去 eventProducer.product(new EventModel(EventType.SEND_VALIDATE_EMAIL).setExts("mail", user.getEmail()).setExts("code", uuid)); return Result.success(); } @Transactional public Result validate(Integer uid, String code) { String uuid = redisUtil.get("validatecode_" + uid); if (code != null && code.length() == 36 && code.equals(uuid)) { User user = userHolder.getUser(); user.setStat(User.STAT_OK); if (1 == userMapper.update(user)) { redisUtil.delete("validatecode_" + uid); // 验证成功后删除验证码 return Result.success(); } else { return Result.fail(MsgCenter.ERROR); } } return Result.fail(MsgCenter.CODE_ERROR); } @Transactional public Result login(String username, String password, boolean remember, String ip, String device) { if (username == null || password == null) { return Result.fail(MsgCenter.EMPTY_LOGIN); } User user = userMapper.selectByName(username); // 用户名不存在或者密码错误或者用户已经被删除 if (user == null || !user.getPassword().equals(PasswordUtil.pwd2Md5(password)) || user.getStat().equals(User.STAT_DEL)) { return Result.fail(MsgCenter.ERROR_LOGIN); } else if (user.getStat().equals(User.STAT_RESTRICT)) { return Result.fail(MsgCenter.USER_RESTRICT); } else { String uuid = UUID.randomUUID().toString().replaceAll("-", ""); Token token = new Token(); token.setUid(user.getId()); token.setToken(uuid); token.setIp(ip); token.setDevice(device); // 如果保持登陆,过期时间就为7天,否则为1天 if (remember) { token.setExpiredTime(new Date(1000 * 60 * 60 * 24 * 7 + System.currentTimeMillis())); } else { token.setExpiredTime(new Date(1000 * 60 * 60 * 24 + System.currentTimeMillis())); } tokenMapper.insert(token); redisUtil.putEx(uuid, String.valueOf(user.getId()), 60 * 60 * 24); return Result.success(uuid); } } public Result logout(String token) { if (token == null || token.length() != 32) { return Result.fail(MsgCenter.ERROR_PARAMS); } redisUtil.delete(token); tokenMapper.updateStatByToken(Token.STAT_EXPIRED, token); return Result.success(); } public Result updateUserInfo(User user) { if (userHolder.getUser() == null) { return Result.fail(MsgCenter.USER_NOT_LOGIN); } // 验证参数是否合法 if (StringUtils.isBlank(user.getNickname())) { return Result.fail(MsgCenter.EMPTY_NICKNAME); } else if (user.getNickname().length() > 10) { return Result.fail(MsgCenter.ERROR_NICINAME); } else if (StringUtils.isBlank(user.getEmail())) { return Result.fail(MsgCenter.EMPTY_EMAIL); } else if (Pattern.compile("^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"). matcher(user.getEmail()).find() == false) { // 判断邮箱格式是否正确 return Result.fail(MsgCenter.ERROR_EMAIL); } else if (user.getPhone() == null) { return Result.fail(MsgCenter.EMPTY_PHONE); } else if (Pattern.compile("1[3|5|7|8|]\\d{9}").matcher(user.getPhone().toString()).find() == false) { // 验证手机号码是否格式正确 return Result.fail(MsgCenter.ERROR_PHONE); } else if (userMapper.selectByEmail(user.getEmail()) != null && !userHolder.getUser().getEmail().equals(user.getEmail())) { // 更改邮箱同时邮箱已被注册 return Result.fail(MsgCenter.EMAIL_REGISTERED); } user.setId(userHolder.getUser().getId()); user.setPassword(null); user.setStat(null); if (1 == userMapper.update(user)) { return Result.success(); } return Result.fail(MsgCenter.ERROR); } public Result updatePassword(String password) { if (StringUtils.isBlank(password)) { return Result.fail(MsgCenter.EMPTY_PASSWORD); } else if (16 < password.replaceAll(" ", "").length() || password.replaceAll(" ", "").length() < 6) { return Result.fail(MsgCenter.ERROR_PASSWORD_FORMAT); } User user = userHolder.getUser(); user.setPassword(PasswordUtil.pwd2Md5(password.replaceAll(" ", ""))); if (1 == userMapper.update(user)) { return Result.success(); } else { return Result.fail(MsgCenter.ERROR); } } public Result forgetPassword(String password, String email, String code) { User user = null; if (StringUtils.isBlank(email)) { return Result.fail(MsgCenter.EMPTY_EMAIL); } else if (Pattern.compile("^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"). matcher(email).find() == false || (user = userMapper.selectByEmail(email)) == null) { // 判断邮箱格式以及两次邮箱是否一致 return Result.fail(MsgCenter.ERROR_EMAIL); } else if (StringUtils.isBlank(password)) { return Result.fail(MsgCenter.EMPTY_PASSWORD); } else if (16 < password.replaceAll(" ", "").length() || password.replaceAll(" ", "").length() < 6) { return Result.fail(MsgCenter.ERROR_PASSWORD_FORMAT); } String uuid = redisUtil.get(email); if (code != null && code.length() == 36 && code.equals(uuid)) { user.setPassword(PasswordUtil.pwd2Md5(password.replaceAll(" ", ""))); if (1 == userMapper.update(user)) { redisUtil.delete(email); // 验证成功后删除验证码 return Result.success(user.getUsername()); } else { return Result.fail(MsgCenter.ERROR); } } return Result.fail(MsgCenter.CODE_ERROR); } public Result sendFetchPwdMail(String email) { if (StringUtils.isBlank(email)) { return Result.fail(MsgCenter.EMPTY_EMAIL); } else if (Pattern.compile("^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"). matcher(email).find() == false) { // 判断邮箱格式是否正确 return Result.fail(MsgCenter.ERROR_EMAIL); } User user = userMapper.selectByEmail(email); if (user == null) { return Result.fail(MsgCenter.EMAIL_NOT_REGISTERED); } String uuid = UUID.randomUUID().toString(); // 将数据存入redis中,固定时间后过期 redisUtil.putEx(email, uuid, Validatecode.TIMEOUT); eventProducer.product(new EventModel(EventType.SEND_FIND_PWD_EMAIL).setExts("mail", user.getEmail()).setExts("code", uuid)); return Result.success(); } public void delNotValidateUser() { List users = userMapper.selectByStat(User.STAT_NOT_VALIDATE); Date date = new Date(); date.setTime(date.getTime() - 1000 * 60 * 60); // 删除一小时前注册但未验证的用户 for (User user : users) { if (user.getCtime().before(date)) { userMapper.deleteById(user.getId()); } } } public void expireToken() { Date date = new Date(); tokenMapper.updateStatByDate(date, Token.STAT_EXPIRED); } } ================================================ FILE: src/main/java/cn/cie/utils/MailUtil.java ================================================ package cn.cie.utils; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.SimpleEmail; /** * Created by RojerAlone on 2017/6/2. * 邮件工具 */ public class MailUtil { private final static String USERNAME = "rojeralone@163.com"; private final static String PASSWORD = "password"; // 需要打开SMTP并使用此授权码登录 /** * 发送邮件给指定人,需要主题和内容 * @param user * @param title * @param content */ public static void sendMail(String user, String title, String content) { SimpleEmail email = new SimpleEmail(); email.setCharset("UTF8"); email.setHostName("smtp.163.com"); email.setAuthentication(USERNAME, PASSWORD); try { email.setFrom(USERNAME); email.addTo(user); email.setSubject(title); email.setMsg(content); email.send(); } catch (EmailException e) { e.printStackTrace(); } } /** * 发送验证邮件给用户 * @param user * @param code */ public static void sendValidateMail(String user, String code) { String title = "WePlay注册验证码"; String content = "感谢您注册WePlay,您的验证码为 \n" + code + "\n,请注意保存,此验证码有效期为 10分钟 ,并且只能使用一次。"; sendMail(user, title, content); } /** * 忘记密码时发送验证邮件给用户 * @param user * @param code */ public static void sendFetchPwdMail(String user, String code) { String title = "WePlay找回密码"; String content = "这封邮件是在验证您的WePlay邮箱,用来找回密码,如果不是您本人的操作,请忽略此邮件。\n您的验证码为 \n" + code + "\n请注意保存,此验证码有效期为 10分钟 ,并且只能使用一次。"; sendMail(user, title, content); } } ================================================ FILE: src/main/java/cn/cie/utils/MsgCenter.java ================================================ package cn.cie.utils; /** * Created by RojerAlone on 2017/6/6. * 消息字典 */ public class MsgCenter { public static final String OK = "OK"; public static final String ERROR = "服务器内部错误"; public static final String ERROR_PARAMS = "参数错误"; public static final String NOT_FOUND = "没有找到请求的资源"; public static final String ERROR_LOGIN = "用户名或密码错误"; public static final String EMPTY_LOGIN = "用户名或密码不能为空"; public static final String EMPTY_NICKNAME = "昵称不能为空"; public static final String ERROR_NICINAME = "昵称长度不能大于10个字符且不能包含非法字符"; public static final String USER_NOT_VALIDATE = "请先验证邮箱"; public static final String USER_USERNAME_EXISTS = "该用户名已被注册"; public static final String USER_VALIDATED = "您的邮箱已经验证过了,无需再次验证"; public static final String USER_HAVE_LOGIN = "您已经登陆,无需再次登陆"; public static final String USER_NOT_LOGIN = "请先登陆"; public static final String USER_RESTRICT = "你已经被限制登陆,请联系管理员解除限制"; public static final String EMAIL_REGISTERED = "该邮箱已被注册"; public static final String EMAIL_NOT_REGISTERED = "该邮箱还未注册"; public static final String ERROR_EMAIL = "请输入正确的电子邮箱"; public static final String CODE_ERROR = "邮箱验证码错误"; public static final String EMPTY_USERNAME = "用户名不能为空"; public static final String EMPTY_PASSWORD = "密码不能为空"; public static final String EMPTY_PHONE = "手机号不能为空"; public static final String ERROR_PHONE = "请填入真实的手机号码"; public static final String EMPTY_EMAIL = "邮箱不能为空"; public static final String ERROR_PASSWORD_FORMAT = "密码应不少于6位且不大于16位"; public static final String NAME_EXISTS = "该名称已存在"; public static final String LOGIN_NOT_ALLOW = "没有权限,禁止登陆"; public static final String ERROR_FILE_TYPE = "不支持的文件类型"; } ================================================ FILE: src/main/java/cn/cie/utils/PageUtil.java ================================================ package cn.cie.utils; /** * Created by RojerAlone on 2017/6/21. * 分页工具 */ public class PageUtil { private int num; // 记录的总数 private int pages; // 页数总数 private int current; // 当前页数 private int size; // 每页显示记录数 private int startPos; // 从数据库中查询时开始的条数 public PageUtil(int num, int current, int size) { this.num = num; this.size = size; this.pages = num % size == 0 ? num / size : num / size + 1; if (current <= 0) { this.current = 1; } else { this.current = current > pages ? pages : current; } this.startPos = this.size * (this.current - 1) < 0 ? 0 : this.size * (this.current - 1); } /** * 默认每页大小为10 * @param num * @param current */ public PageUtil(int num, int current) { this.num = num; this.size = 10; this.pages = num % size == 0 ? num / size : num / size + 1; if (current <= 0) { this.current = 1; } else { this.current = current > pages ? pages : current; } this.startPos = this.size * (this.current - 1) < 0 ? 0 : this.size * (this.current - 1); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public int getPages() { return pages; } public void setPages(int pages) { this.pages = pages; } public int getCurrent() { return current; } public void setCurrent(int current) { this.current = current; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public int getStartPos() { return startPos; } public void setStartPos(int startPos) { this.startPos = startPos; } } ================================================ FILE: src/main/java/cn/cie/utils/PasswordUtil.java ================================================ package cn.cie.utils; import org.springframework.util.DigestUtils; /** * Created by RojerAlone on 2017/6/6. * 将密码进行MD5加密 */ public class PasswordUtil { private static final String SALT = "gp30#?>2a"; public static String pwd2Md5(String paswword) { return DigestUtils.md5DigestAsHex((paswword + SALT).getBytes()); } } ================================================ FILE: src/main/java/cn/cie/utils/RedisUtil.java ================================================ package cn.cie.utils; import com.alibaba.fastjson.JSON; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import java.util.ArrayList; import java.util.List; /** * Created by RojerAlone on 2017/6/13. * 封装了redis操作,用protostuff进行序列化和反序列化 * 如果要插入对象,需要传入插入对象的Class类型 */ @Component public class RedisUtil implements InitializingBean { private JedisPool jedisPool; private static final String REDIS_URL = "redis://localhost:6379/6"; public static final String EVERYDAY = "everyday"; public static final String KINDS = "kinds"; public static final String NEWESTGAME = "newestgame"; public static final String PRE_UP_GAMES = "preupgames"; /** * 存放一条数据 * * @param key * @param value * @return */ public String put(String key, String value) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.set(key, value); } finally { if (jedis != null) { jedis.close(); } } } /** * 存放一条定时过期的数据 * * @param key * @param value * @param timeout * @return */ public String putEx(String key, String value, int timeout) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.setex(key, timeout, value); } finally { if (jedis != null) { jedis.close(); } } } /** * 根据key获取value * * @param key * @return */ public String get(String key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.get(key); } finally { if (jedis != null) { jedis.close(); } } } /** * 存放一个对象 * * @param key * @param value * @return */ public String putObject(String key, T value) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.set(key, JSON.toJSONString(value)); } finally { if (jedis != null) { jedis.close(); } } } /** * 存放一个定时过期的对象 * * @param key * @param value * @param timeout * @return */ public String putObjectEx(String key, T value, int timeout) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.setex(key, timeout, JSON.toJSONString(value)); } finally { if (jedis != null) { jedis.close(); } } } /** * 根据key获取对应的对象 * * @param key * @return */ public T getObject(String key, Class clazz) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return (T) JSON.parseObject(jedis.get(key), clazz); } finally { if (jedis != null) { jedis.close(); } } } /** * 根据key删除数据 * * @param key * @return */ public long delete(String key) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return jedis.del(key); } finally { if (jedis != null) { jedis.close(); } } } /** * 从队列头部出队一个元素,如果没有,则会阻塞 timeout 秒后返回null * 如果 timeout 为0,那么会一直阻塞直到有元素 * * @param timeout 阻塞的时间,单位为秒 * @param key * @param clazz * @return */ public T blpopObject(int timeout, String key, Class clazz) { Jedis jedis = null; try { jedis = jedisPool.getResource(); List list = jedis.blpop(timeout, key); return (T) JSON.parseObject(list.get(0), clazz); } finally { if (jedis != null) { jedis.close(); } } } /** * 从队列左边出队一个元素 * * @param key * @param clazz * @return */ public T lpopObject(String key, Class clazz) { Jedis jedis = null; try { jedis = jedisPool.getResource(); return (T) JSON.parseObject(jedis.lpop(key), clazz); } finally { if (jedis != null) { jedis.close(); } } } /** * 向列表尾部添加数据 * * @param key * @param values * @return */ public long rpushObject(String key, Class clazz, Object... values) { if (values == null || values.length == 0) { return 0; } Jedis jedis = null; try { jedis = jedisPool.getResource(); String[] jsonStrs = new String[values.length]; int index = 0; for (Object value : values) { jsonStrs[index] = JSON.toJSONString(value); ++index; } return jedis.rpush(key, jsonStrs); } finally { if (jedis != null) { jedis.close(); } } } /** * 向列表尾部添加某个时间点删除的数据 * * @param key * @param time unix时间戳 * @param values * @return */ public long rpushObjectExAtTime(String key, Class clazz, long time, Object... values) { if (values.length == 0) { return 0; } Jedis jedis = null; try { jedis = jedisPool.getResource(); String[] jsonStrs = new String[values.length]; int index = 0; for (Object value : values) { jsonStrs[index] = JSON.toJSONString(value); ++index; } long res = jedis.rpush(key, jsonStrs); jedis.expireAt(key.getBytes(), time); // 手动设置过期时间 return res; } finally { if (jedis != null) { jedis.close(); } } } /** * 在列表尾部添加一个定期删除的数据 * * @param key * @param clazz * @param timeout * @param values * @return */ public long rpushObjectEx(String key, Class clazz, int timeout, Object... values) { if (values.length == 0) { return 0; } Jedis jedis = null; try { jedis = jedisPool.getResource(); String[] jsonStrs = new String[values.length]; int index = 0; for (Object value : values) { jsonStrs[index] = JSON.toJSONString(value); ++index; } long res = jedis.rpush(key, jsonStrs); jedis.expire(key, timeout); return res; } finally { if (jedis != null) { jedis.close(); } } } /** * 获取列表中所有数据,ruguo * * @param key * @return */ public List lall(String key, Class clazz) { Jedis jedis = null; try { jedis = jedisPool.getResource(); // 0表示第一个元素,-1表示最后一个元素 List list = jedis.lrange(key, 0, -1); List res = new ArrayList(); if (list == null || list.size() == 0) { return res; } for (String str : list) { res.add((T) JSON.parseObject(str, clazz)); } return res; } finally { if (jedis != null) { jedis.close(); } } } /** * spring注入之后会自动调用这个方法 * * @throws Exception */ public void afterPropertiesSet() throws Exception { jedisPool = new JedisPool(REDIS_URL); } } ================================================ FILE: src/main/java/cn/cie/utils/Result.java ================================================ package cn.cie.utils; /** * Created by RojerAlone on 2017/6/6. * 后台接口返回结果,标识了是否成功、消息以及返回的数据 */ public class Result { private boolean success; private String msg; private T data; private Result(boolean success, String msg) { this.success = success; this.msg = msg; } private Result(boolean success, String msg, T data) { this.success = success; this.msg = msg; this.data = data; } public static Result success() { return new Result(true, MsgCenter.OK); } public static Result success(Object data) { return new Result(true, MsgCenter.OK, data); } public static Result fail(String msg) { return new Result(false, msg); } public static Result fail(String msg, Object data) { return new Result(false, msg, data); } public boolean isSuccess() { return success; } public String getMsg() { return msg; } public T getData() { return data; } } ================================================ FILE: src/main/java/cn/cie/utils/UserHolder.java ================================================ package cn.cie.utils; import cn.cie.entity.User; import org.springframework.stereotype.Component; /** * Created by RojerAlone on 2017/6/11. * 每次请求时存放请求者的信息 */ @Component public class UserHolder { private static ThreadLocal users = new ThreadLocal(); public User getUser() { return users.get(); } public void setUser(User user) { users.set(user); } public void remove() { users.remove(); } } ================================================ FILE: src/main/resources/dbdata.sql ================================================ insert into `shop`.`game`(`creater`, `name`, `desc`, `systemcfg`, `price`) values ('Killerfish Games', 'Cold Waters', 'Spiritual Successor to the Microprose Classic “Red Storm Rising”.', '操作系统: XP 处理器: Intel Atom 内存: 2 GB RAM DirectX 版本: 9.0c 存储空间: 需要 2 GB 可用空间', 58), ('LR Studio', 'Confess My Love', '游戏发生在某一天的放学后,男生未宇打算向心仪的女生阑珊表明自己的心意,但又因为害怕被拒绝犹豫不决。', '操作系统: Windows XP/ Vista/7/10 处理器: Intel Core 2 1.06Ghz 内存: 1 GB RAM 存储空间: 需要 50 MB 可用空间', 0), ('Motion Twin', 'Dead Cells', '欢迎来到《死亡细胞》,这是一款将Roguelite与银河战士恶魔城类特点融为一炉的2D平台动作游戏。游戏中并无检查点,玩家将体验魂味战斗,一路挑战诸多守卫,在杀戮与死亡的反复轮回中探索一座房间不断变化的巨大城堡。”.', '操作系统: Windows 7+ 处理器: Intel i5+ 内存: 2 GB RAM 图形: Nvidia 450 GTS / Radeon HD 5750 or better 存储空间: 需要 500 MB 可用空间 附注事项: OpenGL 3.2+', 0), ('ROCKFISH Games', 'EVERSPACE', '《EVERSPACE™》是一款侧重于动作的单人太空射击游戏,结合了类Rogue元素和一流的视觉效果及引人入胜的故事。游戏将带领你在一个不断变化、制作精美且充满惊喜的宇宙中,展开一段富有挑战性的旅程。 你的技能、经验和随机应变的天赋都将持续受到考验;与此同时,通过遭遇其他有趣且各有奥秘的人物角色,你将了解自己的存在意义。每个回合都是激动人心的体验,每次航行都是全新的局势,让游戏的每一个部分都能长久地持续下去, 并从中创造大量独特而意味深长的体验时刻。然而,不管你的飞行技术多么高超,死亡都是不可避免的,而这只是一段更宏大旅程的开始。', '操作系统: 32/64-bit Windows 7 / 8.1 / 10 处理器: Intel CPU Core i3 内存: 4 GB RAM 图形: Nvidia GTX 480 / AMD Radeon HD 5870 DirectX 版本: 10 存储空间: 需要 8 GB 可用空间', 49.9), ('Modern Visual Arts Laboratory', 'Lucy -The Eternity She Wished For', '如果世界上有机器人能够像人一样微笑,一样哭泣,一样悲伤。', '操作系统: Microsoft Windows 2000/XP(SP3)/Vista 处理器: Intel Pentium 4 1.5Ghz/AMD Athlon 1800 内存: 128 MB RAM DirectX 版本: 9.0c 存储空间: 需要 1 GB 可用空间 附注事项: Microsoft .Net Framework', 124), ('Klei Entertainment', 'Mark of the Ninja', 'In Mark of the Ninja, you''ll know what it is to truly be a ninja. You must be silent, agile and clever to outwit your opponents in a world of gorgeous scenery and flowing animation. Marked with cursed tattoos giving you heightened senses, every situation presents you with options.', 'OS:Windows XP SP3, Windows Vista SP2, Windows 7 SP1 Processor:AMD Phenom 9750 or Pentium D 800+ Memory:2 GB RAM Graphics:NVIDIA® GeForce® 7800 GT or ATI Radeon™ HD 3000+ or better DirectX®:9.0c Hard Drive:2.5 GB HD space Sound:100% DirectX9.0c compatible sound card and drivers', 66), ('Klei Entertainment', 'Oxygen Not Included', 'Oxygen Not Included is a space-colony simulation game. Deep inside an alien space rock your industrious crew will need to master science, overcome strange new lifeforms, and harness incredible space tech to survive, and possibly, thrive.', '操作系统: Windows 7 (64 bit) 处理器: Dual Core 2 GHz 内存: 4 GB RAM 图形: Intel HD 4600 (AMD or NVIDIA equivalent) DirectX 版本: 11 存储空间: 需要 2 GB 可用空间', 76), ('ConcernedApe', 'Stardew Valley', '你继承了你爷爷在星露谷留下的老旧农场。带着爷爷留下的残旧工具和几枚硬币开始了你的新生活。你能适应这小镇上的生活并且将这个杂草丛生的老旧农场变成一个繁荣的家吗?', '操作系统: Windows Vista or greater 处理器: 2 Ghz 内存: 2 GB RAM 图形: 256 mb video memory, shader model 3.0+ DirectX 版本: 10 存储空间: 需要 500 MB 可用空间', 21), ('Thekla, Inc.', 'The Witness', '你孤身一人醒来。这是一座充满挑战和惊奇、遍地谜题的奇怪小岛。', '操作系统: Windows 7 处理器: 1.8GHz 内存: 4 GB RAM 图形: Intel HD 4000 series DirectX 版本: 10 存储空间: 需要 5 GB 可用空间', 21), ('Illusion Ranger', 'Aeon', '我们把所有精力都注入在打击感的挖掘上,创造出一款顶级打击感的VR射击游戏。你将体验大口径火枪爽快的爆裂射击,同时用你的武士刀随心所欲地斩杀胆敢靠近的敌人。', '操作系统: win7 处理器: intel i5 内存: 8000 MB RAM 图形: Nvidia 970 DirectX 版本: 11 存储空间: 需要 2000 MB 可用空间 附注事项: HTC vive only', 55), ('Reactive Drop Team', 'Alien Swarm Reactive Drop', 'Co-operative top-down shooter game available for free. An epic bug hunt featuring a unique blend of co-op play and squad-level tactics.', '操作系统: Windows® XP or above 处理器: Pentium 4 3.0GHz 内存: 2 GB RAM 图形: DirectX 9 compatible video card with 128 MB, Shader model 2.0. ATI X800, NVidia 6600 or better DirectX 版本: 9.0 存储空间: 需要 10 GB 可用空间 声卡: DirectX 9.0c compatible sound card', 76), ('Valve', 'Counter-Strike Global Offensive', '《反恐精英:全球攻势》(CS: GO)在团队竞技游戏模式的基础上加以开发,这一模式自 12 年前发布以来一直引领至今。 CS: GO 的特色是全新的地图、人物、武器以及最新版本的 CS 经典内容(de_dust 等)。此外,CS: GO 引入了全新的游戏模式、对战匹配、排行榜以及更多新的内容。', '操作系统: Windows® 7/Vista/XP 处理器: Intel® Core™ 2 Duo E6600 or AMD Phenom™ X3 8750 processor or better 内存: 2 GB RAM 图形: Video card must be 256 MB or more and should be a DirectX 9-compatible with support for Pixel Shader 3.0 DirectX 版本: 9.0c 存储空间: 需要 15 GB 可用空间', 58), ('Sports Interactive', 'Football Manager 2017', '作为迄今为止最真实的足球经理类游戏,Football Manager 2017 让你操控自己最喜欢的球队征战绿茵赛场。', '操作系统: Windows Vista (SP2), 7 (SP1), 8, 8.1, 10 (1607) – 64-bit or 32-bit 处理器: Intel Pentium 4, Intel Core or AMD Athlon – 2.2 GHz + 内存: 2 GB RAM 图形: Intel GMA X3100, NVIDIA GeForce 8600M GT or AMD/ATI Mobility Radeon HD 2400 – 256MB VRAM DirectX 版本: 9.0c 存储空间: 需要 3 GB 可用空间', 75), ('Telltale Games', 'Marvel''s Guardians of the Galaxy The Telltale Series', '从地球到米兰号再到不毛之地以及更远的地方,伴随着超棒的音乐节奏,这个分为五章节的系列游戏将带你进入穿着火箭靴的星爵的全新Guardians历险。游戏故事由曾获奖的Telltale独特风格讲述,你的选择和动作将决定你所体验的故事轨迹。 ', '操作系统: Windows 7 64Bit Service Pack 1 or higher 处理器: Intel Core 2 Duo 2.4GHz 内存: 3 GB RAM 图形: Nvidia GTS 450+ with 1024MB+ VRAM (excluding GT) DirectX 版本: 11 存储空间: 需要 15 GB 可用空间 声卡: Direct X 11 sound device', 198), ('Bluehole, Inc.', 'PLAYERUNKNOWN''S BATTLEGROUNDS', '绝地求生(PLAYERUNKNOWN’S BATTLEGROUNDS)是大逃杀类型的游戏,每一局游戏将有100名玩家参与,他们将被投放在绝地岛(battlegrounds)的上空,游戏开始跳伞时所有人都一无所有。', '操作系统: 64-bit Windows 7, Windows 8.1, Windows 10 处理器: Intel Core i3-4340 / AMD FX-6300 内存: 6 GB RAM 图形: nVidia GeForce GTX 660 2GB / AMD Radeon HD 7850 2GB DirectX 版本: 11 网络: 宽带互联网连接 存储空间: 需要 30 GB 可用空间', 200), ('Keen Games', 'Portal Knights', '将熟悉的世界抛在身后,踏入 Portal Knights 这个奇妙的未知世界!在由古代传送门连接的众多沙盒岛屿上,和你的好友一起展开这场惊险刺激的制作冒险。没有人记得自从和平的世界因为碎裂分崩离析、陷入黑暗之后已经过了多久。是否还有勇者敢于将这片破碎之地复原?打造你的冒险之旅。', '操作系统: 64bit Versions of Windows 7, Windows 8, Windows 10 处理器: AMD Phenom(tm) 8450 Triple-Core Processor (3 CPUs), ~2.1GHz or Intel Core 2 Duo E8400 @ 3.0 GHz 内存: 4 GB RAM 图形: Graphics: NVIDIA® GeForce GTX 470 (1Gb VRAM) / ATI Radeon TM HD 6870 (1Gb VRAM) DirectX 版本: 11 网络: 宽带互联网连接 存储空间: 需要 2 GB 可用空间 声卡: On Board', 98), ('Arkane Studios', 'Prey', 'In Prey, you awaken aboard Talos I, a space station orbiting the moon in the year 2032. You are the key subject of an experiment meant to alter humanity forever – but things have gone terribly wrong. The space station has been overrun by hostile aliens and you are now being hunted. ', '操作系统: Windows 7/8/10 (64-bit versions) 处理器: Intel i5-2400, AMD FX-8320 内存: 8 GB RAM 图形: GTX 660 2GB, AMD Radeon 7850 2GB 存储空间: 需要 20 GB 可用空间', 79), ('Eugen Systems', 'Steel Division Normandy 44', 'Steel Division: Normandy is a tactical real-time strategy (RTS) game that pits players against AI enemies in a single-player campaign -- or against several opponents in massive 10-on-10 multiplayer battles. ', '操作系统: 64-bit Windows 10 / 8.1 / 7 with Service Pack 1 处理器: Intel Core i3-2100 (3.1 GHz) or equivalent 内存: 3 GB RAM 图形: 1 GB AMD 5570 or nVidia 450 DirectX 版本: 11 网络: 宽带互联网连接 存储空间: 需要 32 GB 可用空间 声卡: DirectX Compatible Sound Card', 66), ('SNK Playmore', 'THE KING OF FIGHTERS XIII STEAM EDITION', '“THE KING OF FIGHTERS XIII”, SNK PLAYMORE’s flagship 2D versus fighting title returns in an ultimate version on Steam!!The many features exclusive to the console version of the game, such as the ONLINE Mode that allows you to enjoy smooth online versus matches with rivals from around the world', '操作系统: Windows XP 处理器: Intel Pentium4 2.0 GHz and up 内存: 1 GB RAM 图形: GeForce 9500 GT ,VRAM: 256MB and up DirectX 版本: 9.0c 存储空间: 需要 5 GB 可用空间 声卡: DirectSound, DirectX9.0c Compatible Audio', 50), ('Rockstar North', 'GTA Online: Shark Cash Cards', '该内容需要在 Steam 拥有基础游戏 Grand Theft Auto V 才能运行。', '操作系统: Windows 10 64 Bit, Windows 8.1 64 Bit, Windows 8 64 Bit, Windows 7 64 Bit Service Pack 1, Windows Vista 64 Bit Service Pack 2* (*NVIDIA video card recommended if running Vista OS) 处理器: Intel Core 2 Quad CPU Q6600 @ 2.40GHz (4 CPUs) / AMD Phenom 9850 Quad-Core Processor (4 CPUs) @ 2.5GHz 内存: 4 GB RAM 图形: NVIDIA 9800 GT 1GB / AMD HD 4870 1GB (DX 10, 10.1, 11) 存储空间: 需要 72 GB 可用空间 声卡: 100% DirectX 10 compatible', 148), ('Giant Squid', 'ABZU', '沿袭 Journey蕴含的艺术思想,ABZU 是一款能唤起潜水梦想的唯美海底冒险游戏。深入海洋中心,将自己沉浸在生机勃勃的隐秘世界中,这里色彩缤纷,生物繁多。但要注意,当你不断深入,危险就潜伏在深处。', '操作系统: Windows 7, 64-bit 处理器: 3.0GHz CPU Dual Core 内存: 4 GB RAM 图形: Geforce GTX 750 / Radeon R7 260X DirectX 版本: 11 存储空间: 需要 6 GB 可用空间 声卡: DirectX compatible sound card', 68), ('Rad Codex', 'Alvora Tactics', 'Alvora Tactics is an indie Tactics RPG that combines strategic combat with immersive exploration. Explore and conquer Great Serpent Alvora with your own customizable band of warriors!', '操作系统: Windows XP 内存: 1 GB RAM 图形: Must support Shader Model 2.0 DirectX 版本: 9.0c 存储空间: 需要 1000 MB 可用空间', 32), ('Codemasters', 'DiRT 4', '世界领先的越野赛系列游戏回归了!《DiRT 4》让你驾驶有史以来最强的赛车去面对这个星球的拉力赛、rallycross 和 landrush 中危险重重的赛道。游戏改变了“你的赛段”系统,只要轻轻触摸一个按钮,即可创建无数条赛道。', '操作系统: 64bit Versions of Windows 7, Windows 8, Windows 10 处理器: AMD FX Series or Intel Core i3 Series 内存: 4 GB RAM 图形: AMD HD5570 or NVIDIA GT440 with 1GB of VRAM (DirectX 11 graphics card required) 网络: 宽带互联网连接 存储空间: 需要 50 GB 可用空间 声卡: DirectX Compatible soundcard', 158), ('FromSoftware, Inc.', 'DARK SOULS III', 'Dark Souls即将推出极具话题性及代表性的系列新作。', '操作系统: Windows 7 SP1 64bit, Windows 8.1 64bit Windows 10 64bit 处理器: Intel Core i3-2100 / AMD® FX-6300 内存: 4 GB RAM 图形: NVIDIA® GeForce GTX 750 Ti / ATI Radeon HD 7950 DirectX 版本: 11 网络: 宽带互联网连接 存储空间: 需要 25 GB 可用空间 声卡: DirectX 11 sound device', 268), ('Laser Unicorns', 'Kung Fury', 'Miami Police Department detective and martial artist Kung Fury time travels from the 1980s to World War II to kill Adolf Hitler, a.k.a. "Kung Führer", and revenge his friend''s death at the hands of the Nazi leader. An error in the time machine sends him further back to the Viking Age.', '操作系统: Windows 7 处理器: 英特尔酷睿 2 处理器或相同性能的 AMD 处理器 内存: 1 GB RAM 网络: 宽带互联网连接 存储空间: 需要 200 MB 可用空间', 0), ('Rockstar North', 'Grand Theft Auto V', 'A young street hustler, a retired bank robber and a terrifying psychopath must pull off a series of dangerous heists to survive in a ruthless city in which they can trust nobody, least of all each other.', '操作系统: Windows 10 64 Bit, Windows 8.1 64 Bit, Windows 8 64 Bit, Windows 7 64 Bit Service Pack 1, Windows Vista 64 Bit Service Pack 2* (*NVIDIA video card recommended if running Vista OS) 处理器: Intel Core 2 Quad CPU Q6600 @ 2.40GHz (4 CPUs) / AMD Phenom 9850 Quad-Core Processor (4 CPUs) @ 2.5GHz 内存: 4 GB RAM 图形: NVIDIA 9800 GT 1GB / AMD HD 4870 1GB (DX 10, 10.1, 11) 存储空间: 需要 72 GB 可用空间 声卡: 100% DirectX 10 compatible', 198), ('IMCGAMES Co.,Ltd.', 'Tree of Savior (English Ver.)', 'Tree of Savior(abbreviated as TOS thereafter) is an MMORPG in which you embark on a journey to search for the goddesses in the world of chaos. Fairy-tale like colors accompanied with beautiful graphics in TOS will have you reminiscing about precious moments all throughout the game.', '操作系统: Windows XP 处理器: Intel Pentium Core 2 内存: 4 GB RAM 图形: NVIDIA Geforce 8600 DirectX 版本: 9.0c 网络: 宽带互联网连接 存储空间: 需要 4 GB 可用空间', 0), ('Daybreak Game Company', 'H1Z1 King of the Kill', '《杀戮之王》是一款单败淘汰制多人在线射击游戏,可容纳150名身经百战的玩家角逐于一个强大而复杂的世界。搜寻武器、弹药、盔甲、车辆和补给,在竞争中脱颖而出,并坚持到最后。', '操作系统: Windows 7, 8, 8.1, 10 (64 bit only) 处理器: Intel i5 Quad-Core 内存: 6 GB RAM 图形: nVidia GeForce GTX 280 series or higher DirectX 版本: 10 网络: 宽带互联网连接 存储空间: 需要 20 GB 可用空间 声卡: DirectX Compatible Sound Card', 68), ('Codemasters , Feral Interactive (Mac)', 'F1 2016', '在F1 2016中创造您自己的传奇。准备好全身心投入这场有史以来最著名的顶尖赛车赛事中。与您的代理人、工程师与团队共同合作,以十个赛季的丰富经验深度开发您的赛车。', '操作系统: 64bit Versions of Windows 7, Windows 8, Windows 10 处理器: Intel Core i3 530 or AMD FX 4100 内存: 8 GB RAM 图形: Nvidia GTX 460 or AMD HD 5870 DirectX 版本: 11 网络: 宽带互联网连接 存储空间: 需要 30 GB 可用空间 声卡: DirectX Compatible Soundcard', 158), ('Piranha Bytes', 'ELEX', 'ELEX is a handcrafted action role-playing experience from the award-winning creators of the Gothic series, set in a brand new post-apocalyptic Science Fantasy universe that puts players into a huge seamless game world full of original characters, mutated creatures, deep moral choices and powerful action.', '操作系统: Windows 7, 8, Windows 10 (64 bit) 处理器: Intel Core i5 at 2.5 GHz or better or AMD Phenom II x4 940 at 3.0 GHz 内存: 6 GB RAM 图形: NVIDIA GeForce GTX 570 or AMD Radeon HD 5870, 1 GB VRAM DirectX 版本: 11 存储空间: 需要 20 GB 可用空间 声卡: DirectX compatible Sound card', 44.1), ('IllFonic', 'Friday the 13th: The Game', 'Jason is back! Jason Voorhees is unleashed and stalking the grounds of Camp Crystal Lake! Friday the 13th: The Game is one of the most highly-anticipated horror titles of all time. You will finally be able to take on the role as Jason Voorhees and Camp Crystal Lake counselors.', '操作系统: Windows 7, Windows 8, Windows 10 处理器: Intel Core i3-530 (2 * 2930), AMD Athlon II X2 270 (2 * 3400) 内存: 4096 MB RAM 图形: GeForce GTX 650 Ti (1024 MB), Radeon HD 7770 (1024 MB) DirectX 版本: 11 网络: 宽带互联网连接 存储空间: 需要 4 GB 可用空间', 39); insert into `shop`.`kind`(name) values ('独立'), ('动作'), ('冒险'), ('休闲'), ('策略'), ('模拟'), ('角色扮演'), ('免费'), ('单人'), ('大型多人在线'), ('射击'), ('体育'), ('氛围'), ('暴力'); insert into `shop`.`kindmapper` values (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1), (9, 1), (10, 2), (11, 2), (12, 2), (13, 2), (14, 2), (15, 2), (16, 2), (17, 2), (18, 2), (19, 2), (20, 3), (21, 4), (22, 5), (23, 6), (24, 7), (25, 8), (26, 9), (27, 10), (28, 11), (29, 12), (30, 13), (31, 14); insert into `shop`.`tag`(`name`) values ('模拟'), ('独立'), ('海军'), ('策略'), ('冷战'), ('免费'), ('冒险'), ('角色扮演'), ('日本动画'), ('动作'), ('太空'), ('科幻'), ('单人'), ('剧情'), ('机器人'), ('潜行'), ('忍者'), ('多人'), ('二维'), ('建筑建造'), ('生存'), ('农业'), ('工业'), ('解密'), ('探索'), ('第一人称'), ('射击'), ('虚拟现实'), ('合作'), ('外星人'), ('体育'), ('足球'), ('恐怖'), ('即时战略'), ('街机'), ('格斗'), ('竞速'), ('困难'), ('女主人翁'), ('丧尸'), ('氛围'), ('暴力'), ('犯罪'), ('砍杀'), ('萝莉'), ('养成'), ('种植'); insert into `shop`.`tagmapper` values (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 6), (2, 2), (2, 7), (2, 8), (2, 9), (2, 45), (2, 46), (3, 10), (3, 2), (4, 11), (4, 10), (4, 2), (4, 12), (4, 13), (5, 9), (5, 14), (5, 1), (5, 15), (5, 45), (5, 46), (6, 16), (6, 17), (6, 13), (6, 19), (6, 10), (7, 20), (7, 21), (7, 1), (7, 13), (8, 8), (8, 1), (8, 22), (8, 23), (9, 24), (9, 25), (9, 26), (9, 13), (10, 10), (10, 26), (10, 27), (10, 2), (10, 28), (11, 29), (11, 18), (11, 10), (11, 30), (12, 26), (12, 27), (12, 18), (12, 10), (12, 29), (13, 31), (13, 1), (13, 32), (13, 4), (13, 34), (14, 7), (14, 14), (14, 10), (15, 21), (15, 27), (15, 18), (16, 7), (16, 18), (16, 8), (17, 12), (17, 10), (17, 11), (17, 26), (17, 27), (17, 33), (18, 4), (18, 34), (18, 1), (18, 10), (18, 18), (19, 35), (19, 36), (19, 10), (19, 9), (19, 37), (19, 41), (19, 44), (20, 10), (20, 7), (20, 18), (20, 27), (20, 42), (20, 43), (20, 44), (21, 41), (21, 24), (21, 25), (22, 2), (22, 4), (22, 8), (22, 47), (23, 37), (23, 1), (23, 31), (23, 18), (24, 41), (24, 38), (24, 8), (24, 25), (25, 10), (25, 35), (25, 36), (25, 12), (26, 18), (26, 27), (26, 37), (26, 42), (26, 43), (26, 44), (27, 1), (27, 7), (27, 8), (27, 47), (28, 18), (28, 21), (28, 27), (28, 44), (29, 41), (29, 37), (30, 8), (30, 7), (30, 12), (30, 10), (31, 40), (31, 18), (31, 33), (31, 42); insert into `shop`.`img` values (1, '/1/header.jpg'), (1, '/1/1.jpg'), (1, '/1/2.jpg'), (1, '/1/3.jpg'), (1, '/1/4.jpg'), (1, '/1/5.jpg'), (2, '/2/header.jpg'), (2, '/2/1.jpg'), (2, '/2/2.jpg'), (2, '/2/3.jpg'), (2, '/2/4.jpg'), (2, '/2/5.jpg'), (3, '/3/header.jpg'), (3, '/3/1.jpg'), (3, '/3/2.jpg'), (3, '/3/3.jpg'), (3, '/3/4.jpg'), (3, '/3/5.jpg'), (4, '/4/header.jpg'), (4, '/4/1.jpg'), (4, '/4/2.jpg'), (4, '/4/3.jpg'), (4, '/4/4.jpg'), (4, '/4/5.jpg'), (5, '/5/header.jpg'), (5, '/5/1.jpg'), (5, '/5/2.jpg'), (5, '/5/3.jpg'), (5, '/5/4.jpg'), (5, '/5/5.jpg'), (6, '/6/header.jpg'), (6, '/6/1.jpg'), (6, '/6/2.jpg'), (6, '/6/3.jpg'), (6, '/6/4.jpg'), (6, '/6/5.jpg'), (7, '/7/header.jpg'), (7, '/7/1.jpg'), (7, '/7/2.jpg'), (7, '/7/3.jpg'), (7, '/7/4.jpg'), (7, '/7/5.jpg'), (7, '/7/6.jpg'), (8, '/8/header.jpg'), (8, '/8/1.jpg'), (8, '/8/2.jpg'), (8, '/8/3.jpg'), (8, '/8/4.jpg'), (8, '/8/5.jpg'), (9, '/9/header.jpg'), (9, '/9/1.jpg'), (9, '/9/2.jpg'), (9, '/9/3.jpg'), (9, '/9/4.jpg'), (9, '/9/5.jpg'), (10, '/10/header.jpg'), (10, '/10/1.jpg'), (10, '/10/2.jpg'), (10, '/10/3.jpg'), (10, '/10/4.jpg'), (10, '/10/5.jpg'), (10, '/10/6.jpg'), (11, '/11/header.jpg'), (11, '/11/1.jpg'), (11, '/11/2.jpg'), (11, '/11/3.jpg'), (11, '/11/4.jpg'), (11, '/11/5.jpg'), (11, '/11/6.jpg'), (12, '/12/header.jpg'), (12, '/12/1.jpg'), (12, '/12/2.jpg'), (12, '/12/3.jpg'), (12, '/12/4.jpg'), (12, '/12/5.jpg'), (12, '/12/6.jpg'), (13, '/13/header.jpg'), (13, '/13/1.jpg'), (13, '/13/2.jpg'), (13, '/13/3.jpg'), (13, '/13/4.jpg'), (13, '/13/5.jpg'), (13, '/13/6.jpg'), (14, '/14/header.jpg'), (14, '/14/1.jpg'), (14, '/14/2.jpg'), (14, '/14/3.jpg'), (14, '/14/4.jpg'), (14, '/14/5.jpg'), (15, '/15/header.jpg'), (15, '/15/1.jpg'), (15, '/15/2.jpg'), (15, '/15/3.jpg'), (15, '/15/4.jpg'), (15, '/15/5.jpg'), (16, '/16/header.jpg'), (16, '/16/1.jpg'), (16, '/16/2.jpg'), (16, '/16/3.jpg'), (16, '/16/4.jpg'), (16, '/16/5.jpg'), (16, '/16/6.jpg'), (17, '/17/header.jpg'), (17, '/17/1.jpg'), (17, '/17/2.jpg'), (17, '/17/3.jpg'), (17, '/17/4.jpg'), (17, '/17/5.jpg'), (17, '/17/6.jpg'), (18, '/18/header.jpg'), (18, '/18/1.jpg'), (18, '/18/2.jpg'), (18, '/18/3.jpg'), (18, '/18/4.jpg'), (18, '/18/5.jpg'), (18, '/18/6.jpg'), (19, '/19/header.jpg'), (19, '/19/1.jpg'), (19, '/19/2.jpg'), (19, '/19/3.jpg'), (19, '/19/4.jpg'), (19, '/19/5.jpg'), (20, '/20/header.jpg'), (20, '/20/1.jpg'), (20, '/20/2.jpg'), (20, '/20/3.jpg'), (20, '/20/4.jpg'), (20, '/20/5.jpg'), (21, '/21/header.jpg'), (21, '/21/1.jpg'), (21, '/21/2.jpg'), (21, '/21/3.jpg'), (21, '/21/4.jpg'), (21, '/21/5.jpg'), (21, '/21/6.jpg'), (22, '/22/header.jpg'), (22, '/22/1.jpg'), (22, '/22/2.jpg'), (22, '/22/3.jpg'), (22, '/22/4.jpg'), (22, '/22/5.jpg'), (23, '/23/header.jpg'), (23, '/23/1.jpg'), (23, '/23/2.jpg'), (23, '/23/3.jpg'), (23, '/23/4.jpg'), (23, '/23/5.jpg'), (24, '/24/header.jpg'), (24, '/24/1.jpg'), (24, '/24/2.jpg'), (24, '/24/3.jpg'), (24, '/24/4.jpg'), (24, '/24/5.jpg'), (25, '/25/header.jpg'), (25, '/25/1.jpg'), (25, '/25/2.jpg'), (25, '/25/3.jpg'), (25, '/25/4.jpg'), (25, '/25/5.jpg'), (26, '/26/header.jpg'), (26, '/26/1.jpg'), (26, '/26/2.jpg'), (26, '/26/3.jpg'), (26, '/26/4.jpg'), (26, '/26/5.jpg'), (27, '/27/header.jpg'), (27, '/27/1.jpg'), (27, '/27/2.jpg'), (27, '/27/3.jpg'), (27, '/27/4.jpg'), (27, '/27/5.jpg'), (28, '/28/header.jpg'), (28, '/28/1.jpg'), (28, '/28/2.jpg'), (28, '/28/3.jpg'), (28, '/28/4.jpg'), (28, '/28/5.jpg'), (29, '/29/header.jpg'), (29, '/29/1.jpg'), (29, '/29/2.jpg'), (29, '/29/3.jpg'), (29, '/29/4.jpg'), (29, '/29/5.jpg'), (30, '/30/header.jpg'), (30, '/30/1.jpg'), (30, '/30/2.jpg'), (30, '/30/3.jpg'), (30, '/30/4.jpg'), (30, '/30/5.jpg'), (30, '/30/6.jpg'), (31, '/31/header.jpg'), (31, '/31/1.jpg'), (31, '/31/2.jpg'), (31, '/31/3.jpg'), (31, '/31/4.jpg'), (31, '/31/5.jpg'), (31, '/31/6.jpg'); ================================================ FILE: src/main/resources/generator/generatorConfig.xml ================================================ ================================================ FILE: src/main/resources/jdbc.properties ================================================ jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=123456 jdbc.initialSize=0 jdbc.maxActive=20 jdbc.maxIdle=20 jdbc.minIdle=1 jdbc.maxWait=60000 ================================================ FILE: src/main/resources/log4j-acc.properties ================================================ log4j.rootLogger=INFO,LOGFILE log4j.appender.LOGFILE = org.apache.log4j.RollingFileAppender log4j.appender.LOGFILE.File = /usr/local/log/acc.log log4j.appender.LOGFILE.MaxFileSize = 10MB log4j.appender.LOGFILE.MaxBackupIndex = 1000 log4j.appender.LOGFILE.layout = org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern = %d{yyyy-MM-dd HH\:mm\:ss} %m%n # %-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n ================================================ FILE: src/main/resources/log4j-error.properties ================================================ log4j.rootLogger=ERROR,LOGFILE log4j.appender.LOGFILE = org.apache.log4j.RollingFileAppender log4j.appender.LOGFILE.File = /usr/local/log/err.log log4j.appender.LOGFILE.MaxFileSize = 10MB #log4j.appender.LOGFILE.Threshold = ALL log4j.appender.LOGFILE.layout = org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern = %d{yyyy-MM-dd HH\:mm\:ss} %m%n ================================================ FILE: src/main/resources/mapper/CodeMapper.xml ================================================ id, item, uid, code, stat insert into code item, uid, code, #{item,jdbcType=INTEGER}, #{uid,jdbcType=INTEGER}, #{code,jdbcType=VARCHAR}, update code stat = #{stat,jdbcType=TINYINT}, where id = #{id,jdbcType=INTEGER} ================================================ FILE: src/main/resources/mapper/GameMapper.xml ================================================ id, creater, `name`, `desc`, systemcfg, price, discount, ctime, utime, stat insert into game creater, `name`, `desc`, systemcfg, price, discount, #{creater,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{desc,jdbcType=VARCHAR}, #{systemcfg,jdbcType=VARCHAR}, #{price,jdbcType=DOUBLE}, #{discount,jdbcType=DOUBLE}, update game creater = #{creater,jdbcType=VARCHAR}, `name` = #{name,jdbcType=VARCHAR}, `desc` = #{desc,jdbcType=VARCHAR}, systemcfg = #{systemcfg,jdbcType=VARCHAR}, price = #{price,jdbcType=DOUBLE}, discount = #{discount,jdbcType=DOUBLE}, stat = #{stat,jdbcType=TINYINT}, where id = #{id,jdbcType=INTEGER} ================================================ FILE: src/main/resources/mapper/ImgMapper.xml ================================================ insert into img game, img, #{game,jdbcType=INTEGER}, #{img,jdbcType=VARCHAR}, insert into img (game, img) values (#{game,jdbcType=INTEGER}, #{img}) ================================================ FILE: src/main/resources/mapper/KindMapper.xml ================================================ id, name delete from kind where id = #{id,jdbcType=INTEGER} insert into kind name, #{name,jdbcType=VARCHAR}, update kind set name = #{name,jdbcType=VARCHAR} where id = #{id,jdbcType=INTEGER} ================================================ FILE: src/main/resources/mapper/KindmapperMapper.xml ================================================ insert into kindmapper (game, kind) values (#{game,jdbcType=INTEGER}, #{kind,jdbcType=INTEGER}) insert into kindmapper (game, kind) values (#{game,jdbcType=INTEGER}, #{kind,jdbcType=INTEGER}) insert into kindmapper (kind, game) values (#{kind,jdbcType=INTEGER}, #{game,jdbcType=INTEGER}) delete from kindmapper where game = #{game,jdbcType=INTEGER} delete from kindmapper where kind = #{kind,jdbcType=INTEGER} ================================================ FILE: src/main/resources/mapper/OrderMapper.xml ================================================ id, uid, price, ctime, utime, stat insert into `order` uid, price, #{uid,jdbcType=INTEGER}, #{price,jdbcType=DOUBLE}, update `order` price = #{price,jdbcType=DOUBLE}, stat = #{stat,jdbcType=TINYINT}, where id = #{id,jdbcType=INTEGER} update `order` set stat = #{newstat,jdbcType=TINYINT} where stat = #{oldstat,jdbcType=TINYINT} and utime < #{date,jdbcType=TIMESTAMP} ================================================ FILE: src/main/resources/mapper/OrderitemMapper.xml ================================================ id, gid, price, code, ctime, utime insert into orderitem gid, price, code, #{gid,jdbcType=INTEGER}, #{price,jdbcType=DOUBLE}, #{code,jdbcType=INTEGER}, update orderitem price = #{price,jdbcType=DOUBLE}, code = #{code,jdbcType=INTEGER}, where id = #{id,jdbcType=INTEGER} ================================================ FILE: src/main/resources/mapper/OrdermapperMapper.xml ================================================ insert into ordermapper (`order`, item) values (#{order,jdbcType=INTEGER}, #{item,jdbcType=INTEGER}) ================================================ FILE: src/main/resources/mapper/TagMapper.xml ================================================ id, name insert into tag (id, name) values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}) update tag name = #{name,jdbcType=VARCHAR}, where id = #{id,jdbcType=INTEGER} ================================================ FILE: src/main/resources/mapper/TagmapperMapper.xml ================================================ insert into tagmapper (game, tag) values (#{game,jdbcType=INTEGER}, #{tag,jdbcType=INTEGER}) ================================================ FILE: src/main/resources/mapper/TokenMapper.xml ================================================ uid, token, expired_time, device, ctime, stat insert into token uid, token, expired_time, ip, device, #{uid,jdbcType=INTEGER}, #{token,jdbcType=VARCHAR}, #{expiredTime,jdbcType=TIMESTAMP}, #{ip,jdbcType=VARCHAR}, #{device,jdbcType=VARCHAR}, update token set stat = #{stat,jdbcType=TINYINT} where expired_time < #{date,jdbcType=TIMESTAMP} update token set stat = #{stat,jdbcType=TINYINT} where token = #{token,jdbcType=VARCHAR} ================================================ FILE: src/main/resources/mapper/UserMapper.xml ================================================ id, username, password, nickname, email, phone, ctime, utime, stat id, username, nickname, email, phone, ctime, utime, stat insert into user username, password, nickname, email, phone, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{nickname,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR}, #{phone,jdbcType=BIGINT}, update user password = #{password,jdbcType=VARCHAR}, nickname = #{nickname,jdbcType=VARCHAR}, email = #{email,jdbcType=VARCHAR}, phone = #{phone,jdbcType=BIGINT}, stat = #{stat,jdbcType=TINYINT}, where id = #{id,jdbcType=INTEGER} delete from user where id = #{id,jdbcType=INTEGER} ================================================ FILE: src/main/resources/mybatis-config.xml ================================================ ================================================ FILE: src/main/resources/schema.sql ================================================ CREATE DATABASE IF NOT EXISTS `shop` DEFAULT CHARACTER SET UTF8; CREATE TABLE IF NOT EXISTS `shop`.`user` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '用户ID' , `username` VARCHAR(50) NOT NULL COMMENT '用户名' , `password` VARCHAR(50) NOT NULL COMMENT '密码(加盐并加密)' , `nickname` VARCHAR(50) NOT NULL COMMENT '昵称' , `email` VARCHAR(50) NOT NULL COMMENT '注册邮箱' , `phone` BIGINT(11) DEFAULT NULL COMMENT '手机号码' , `ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , `utime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' , `stat` TINYINT NOT NULL DEFAULT 0 COMMENT '用户状态,0为正常,1为未验证,2为受限,3为删除' , PRIMARY KEY (`id`), INDEX `name`(`username`) ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '用户表'; CREATE TABLE IF NOT EXISTS `shop`.`token` ( `uid` INT NOT NULL COMMENT '用户ID' , `token` VARCHAR(36) NOT NULL COMMENT 'token' , `expired_time` TIMESTAMP NOT NULL COMMENT '过期时间' , `ip` VARCHAR(15) NOT NULL DEFAULT "" COMMENT '访问者IP' , `device` VARCHAR(150) NOT NULL DEFAULT "" COMMENT '登录的设备' , `ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '登录时间' , `stat` TINYINT NOT NULL DEFAULT 0 COMMENT '0表示正常,1表示已过期' , UNIQUE INDEX`token_index`(`token`) ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT 'token表'; CREATE TABLE IF NOT EXISTS `shop`.`game` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT 'ID' , `creater` VARCHAR(50) NOT NULL COMMENT '开发者', `name` VARCHAR(100) NOT NULL COMMENT '游戏名字' , `desc` VARCHAR(500) NOT NULL COMMENT '游戏描述' , `systemcfg` VARCHAR(500) NOT NULL COMMENT '系统配置要求', `price` DOUBLE NOT NULL COMMENT '正常价格', `discount` DOUBLE DEFAULT NULL COMMENT '打折后价格', `ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , `utime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上架时间' , `stat` TINYINT NOT NULL DEFAULT 0 COMMENT '状态,0为未上架,1为已上架,2为已下架' , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '游戏表'; CREATE TABLE IF NOT EXISTS `shop`.`img` ( `game` INT NOT NULL COMMENT '游戏ID', `img` VARCHAR(50) NOT NULL COMMENT '图片路径' ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '游戏图片映射表'; CREATE TABLE IF NOT EXISTS `shop`.`code` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT 'ID' , `item` INT NOT NULL COMMENT '订单项ID' , `uid` INT NOT NULL COMMENT '用户ID', `code` VARCHAR(50) NOT NULL COMMENT '激活码', `stat` TINYINT NOT NULL DEFAULT 0 COMMENT '激活码状态,0表示未使用,1表示已使用', PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '激活码'; CREATE TABLE IF NOT EXISTS `shop`.`order` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT 'ID' , `uid` INT NOT NULL COMMENT '购买者ID' , `price` DOUBLE NOT NULL DEFAULT 0 COMMENT '订单总价', `ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , `utime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' , `stat` TINYINT NOT NULL DEFAULT 0 COMMENT '订单状态,0为未支付,1为已支付,2为取消订单' , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '订单表'; CREATE TABLE IF NOT EXISTS `shop`.`orderitem` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT 'ID' , `gid` INT NOT NULL COMMENT '游戏id', `price` DOUBLE NOT NULL COMMENT '购买时价格', `code` INT DEFAULT NULL COMMENT '激活码' , `ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , `utime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' , PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '每个订单对应的订单详细内容'; CREATE TABLE IF NOT EXISTS `shop`.`ordermapper` ( `order` INT NOT NULL COMMENT '订单ID', `item` INT NOT NULL COMMENT '订单详情ID' ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '订单-订单详情项映射表'; CREATE TABLE IF NOT EXISTS `shop`.`kind` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '种类ID', `name` VARCHAR(10) NOT NULL COMMENT '种类名字', PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '游戏种类表'; CREATE TABLE IF NOT EXISTS `shop`.`kindmapper` ( `game` INT NOT NULL COMMENT '游戏ID', `kind` INT NOT NULL COMMENT '游戏种类ID' ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '游戏-种类详情项映射表'; CREATE TABLE IF NOT EXISTS `shop`.`tag` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '标签ID', `name` VARCHAR(10) NOT NULL COMMENT '标签名字', PRIMARY KEY (`id`) ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '游戏标签表'; CREATE TABLE IF NOT EXISTS `shop`.`tagmapper` ( `game` INT NOT NULL COMMENT '游戏ID', `tag` INT NOT NULL COMMENT '标签ID' ) ENGINE = InnoDB DEFAULT CHARSET = UTF8 COMMENT '游戏-标签映射表'; ================================================ FILE: src/main/resources/spring-dao.xml ================================================ ================================================ FILE: src/main/resources/spring-mvc.xml ================================================ ================================================ FILE: src/main/resources/spring-service.xml ================================================ ================================================ FILE: src/main/webapp/WEB-INF/css/adminlogin.css ================================================ html { font-family: sans-serif; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100% } body { margin: 0 } article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary { display: block } audio, canvas, progress, video { display: inline-block; vertical-align: baseline } audio:not([controls]) { display: none; height: 0 } [hidden], template { display: none } a { background-color: transparent } a:active, a:hover { outline: 0 } abbr[title] { border-bottom: 1px dotted } b, strong { font-weight: bold } dfn { font-style: italic } h1 { font-size: 2em; margin: 0.67em 0 } mark { background: #ff0; color: #000 } small { font-size: 80% } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline } sup { top: -0.5em } sub { bottom: -0.25em } img { border: 0 } svg:not(:root) { overflow: hidden } figure { margin: 1em 40px } hr { -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; height: 0 } pre { overflow: auto } code, kbd, pre, samp { font-family: monospace, monospace; font-size: 1em } button, input, optgroup, select, textarea { color: inherit; font: inherit; margin: 0 } button { overflow: visible } button, select { text-transform: none } button, html input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; cursor: pointer } button[disabled], html input[disabled] { cursor: default } button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0 } input { line-height: normal } input[type="checkbox"], input[type="radio"] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 0 } input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto } input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box } input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none } fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em } legend { border: 0; padding: 0 } textarea { overflow: auto } optgroup { font-weight: bold } table { border-collapse: collapse; border-spacing: 0 } td, th { padding: 0 } .btn { display: inline-block; *display: inline; *zoom: 1; padding: 4px 10px 4px; margin-bottom: 0; font-size: 13px; line-height: 18px; color: #333333; text-align: center; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); vertical-align: middle; background-color: #f5f5f5; background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(top, #ffffff, #e6e6e6); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#ffffff, endColorstr=#e6e6e6, GradientType=0); border-color: #e6e6e6 #e6e6e6 #e6e6e6; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border: 1px solid #e6e6e6; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); cursor: pointer; *margin-left: .3em; } .btn:hover, .btn:active, .btn.active, .btn.disabled, .btn[disabled] { background-color: #e6e6e6; } .btn-large { padding: 9px 14px; font-size: 15px; line-height: normal; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .btn:hover { color: #333333; text-decoration: none; background-color: #e6e6e6; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -ms-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; } .btn-primary, .btn-primary:hover { text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); color: #ffffff; } .btn-primary.active { color: rgba(255, 255, 255, 0.75); } .btn-primary { background-color: #4a77d4; background-image: -moz-linear-gradient(top, #6eb6de, #4a77d4); background-image: -ms-linear-gradient(top, #6eb6de, #4a77d4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#6eb6de), to(#4a77d4)); background-image: -webkit-linear-gradient(top, #6eb6de, #4a77d4); background-image: -o-linear-gradient(top, #6eb6de, #4a77d4); background-image: linear-gradient(top, #6eb6de, #4a77d4); background-repeat: repeat-x; filter: progid:dximagetransform.microsoft.gradient(startColorstr=#6eb6de, endColorstr=#4a77d4, GradientType=0); border: 1px solid #3762bc; text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.5); } .btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { filter: none; background-color: #4a77d4; } .btn-block { width: 100%; display: block; } * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; -o-box-sizing: border-box; box-sizing: border-box; } html { width: 100%; height: 100%; overflow: hidden; } body { width: 100%; height: 100%; font-family: 'Open Sans', sans-serif; background: #092756; background: -moz-radial-gradient(0% 100%, ellipse cover, rgba(104, 128, 138, .4) 10%, rgba(138, 114, 76, 0) 40%), -moz-linear-gradient(top, rgba(57, 173, 219, .25) 0%, rgba(42, 60, 87, .4) 100%), -moz-linear-gradient(-45deg, #670d10 0%, #092756 100%); background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104, 128, 138, .4) 10%, rgba(138, 114, 76, 0) 40%), -webkit-linear-gradient(top, rgba(57, 173, 219, .25) 0%, rgba(42, 60, 87, .4) 100%), -webkit-linear-gradient(-45deg, #670d10 0%, #092756 100%); background: -o-radial-gradient(0% 100%, ellipse cover, rgba(104, 128, 138, .4) 10%, rgba(138, 114, 76, 0) 40%), -o-linear-gradient(top, rgba(57, 173, 219, .25) 0%, rgba(42, 60, 87, .4) 100%), -o-linear-gradient(-45deg, #670d10 0%, #092756 100%); background: -ms-radial-gradient(0% 100%, ellipse cover, rgba(104, 128, 138, .4) 10%, rgba(138, 114, 76, 0) 40%), -ms-linear-gradient(top, rgba(57, 173, 219, .25) 0%, rgba(42, 60, 87, .4) 100%), -ms-linear-gradient(-45deg, #670d10 0%, #092756 100%); background: -webkit-radial-gradient(0% 100%, ellipse cover, rgba(104, 128, 138, .4) 10%, rgba(138, 114, 76, 0) 40%), linear-gradient(to bottom, rgba(57, 173, 219, .25) 0%, rgba(42, 60, 87, .4) 100%), linear-gradient(135deg, #670d10 0%, #092756 100%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3E1D6D', endColorstr='#092756', GradientType=1); } .login { position: absolute; top: 50%; left: 50%; margin: -150px 0 0 -150px; width: 300px; height: 300px; } .login h1 { color: #fff; text-shadow: 0 0 10px rgba(0, 0, 0, 0.3); letter-spacing: 1px; text-align: center; } input { width: 100%; margin-bottom: 10px; background: rgba(0, 0, 0, 0.3); border: none; outline: none; padding: 10px; font-size: 13px; color: #fff; text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); border: 1px solid rgba(0, 0, 0, 0.3); border-radius: 4px; box-shadow: inset 0 -5px 45px rgba(100, 100, 100, 0.2), 0 1px 1px rgba(255, 255, 255, 0.2); -webkit-transition: box-shadow .5s ease; -moz-transition: box-shadow .5s ease; -o-transition: box-shadow .5s ease; -ms-transition: box-shadow .5s ease; transition: box-shadow .5s ease; } input:focus { box-shadow: inset 0 -5px 45px rgba(100, 100, 100, 0.4), 0 1px 1px rgba(255, 255, 255, 0.2); } ================================================ FILE: src/main/webapp/WEB-INF/css/adminpage.css ================================================ @charset "utf-8"; /* CSS Document */ html, body, div, p, form, label, ul, li, dl, dt, dd, ol, img, button, h1, h2, h3, h4, h5, h6, b, em, strong, small { margin: 0; padding: 0; border: 0; list-style: none; font-style: normal; font-weight: normal; } dl, dt, dd { display: block; margin: 0; } a { text-decoration: none; } body { font-family: Microsoft YaHei, Verdana, Arial, SimSun; color: #666; font-size: 14px; background: #f6f6f6; overflow: hidden } .block, #block { display: block; } .none, #none { display: none; } /*****头部和尾部******/ .top { height: 5px; line-height: 5px; background: #f6f6f6; width: 100%; position: fixed; z-index: 255; top: 79px; text-align: center; } .bottom { height: 5px; line-height: 5px; background: #f6f6f6; width: 100%; position: fixed; z-index: 255; bottom: 50px; text-align: center; } #header { height: 80px; line-height: 80px; background: #00a5a5; width: 100%; position: absolute; z-index: 5; top: 0; text-align: center; } .logo { line-height: 80px; font-size: 30px; color: #fff; letter-spacing: 3px; margin-left: 50px; float: left; } .navigation { float: right; margin: 5px 50px 0 0; color: #fff; font-size: 14px; } .navigation ul li { height: 30px; line-height: 30px; text-align: center; float: left; margin-left: 15px; } .navigation ul li a { color: #fff; } .navigation ul li a:hover { color: #32323a; } #footer { height: 50px; line-height: 50px; background: #5e5e5e; width: 100%; position: absolute; z-index: 200; bottom: 0; text-align: center; } #footer p { text-align: center; line-height: 50px; color: #fbfbfb; } /*****主体部分******/ #content { width: 100%; top: 80px; position: absolute; z-index: 10; bottom: 50px; overflow-y: auto; } /**左侧菜单***/ .left_menu { float: left; width: 300px; background: #32323a; height: 120%; position: absolute; top: 0; left: 0; overflow: auto; border-left: 5px solid #f6f6f6; } .left_menu ul li { width: 300px; display: inline; } .left_menu ul li .list-item a { width: 230px; padding-left: 110px; text-decoration: none; font-size: 14px; color: #f5f5f5; line-height: 30px; display: block; } .left_menu ul li a.noline { border-bottom: none; } .left_menu ul li a:hover { color: #fff; } .left_menu ul li a.selected:hover { color: #fff; } .left_menu ul li h4 { cursor: pointer; background: url(/img/static/bg1.png) no-repeat 270px 18px; padding-left: 60px; text-decoration: none; font-size: 16px; color: #f5f5f5; display: block; line-height: 48px; font-weight: normal; } .left_menu ul li.noline { border-bottom: none; } .left_menu ul li.selected h4 { background-position: 270px -45px; background-color: #00a5a5; } .left_menu li .list-item { padding: 5px 0; position: relative; zoom: 1; background: #11b6b6; overflow: hidden; } .left_menu h4 span { display: block; float: left; width: 20px; height: 26px; margin-right: 10px; padding-right: 10px; background-repeat: no-repeat; margin-top: 12px; } .M1 span { background: url(/img/static/ioc.png) 0 -6px; } .M2 span { background: url(/img/static/ioc.png) -36px -6px; } .M3 span { background: url(/img/static/ioc.png) -72px -6px; } .M4 span { background: url(/img/static/ioc.png) -36px -40px; } .M5 span { background: url(/img/static/ioc.png) -72px -40px; } .M6 span { background: url(/img/static/ioc.png) -1px -40px; } .M7 span { background: url(/img/static/ioc.png) -1px -70px; } .M8 span { background: url(/img/static/ioc.png) -36px -70px; } .M9 span { background: url(/img/static/ioc.png) -72px -70px; } .M10 span { background: url(/img/static/ioc.png) -3px -105px; } /***右侧内容****/ .m-right { margin-left: 300px; height: 100%; } .right-nav { height: 50px; border-bottom: 1px solid #d1d1d1; background: #f6f6f6; } .right-nav li { float: left; margin-left: 5px; line-height: 50px; color: #464646; font-size: 14px; } .right-nav li img { position: relative; top: 17px; left: 15px; } .right-nav li a { color: #464646; } .right-nav li a:hover { color: #00a5a5; text-decoration: underline; } main { width: 100%; height: 100%; background: #f6f6f6; overflow: auto; } .yema li { display: inline; } .btn { margin-left: 5px; background: #00a5a5; } tr td { text-align: center; } tr th { text-align: center; } .divsetcenter { margin-left: 30%; } .setmargin { margin-left: 1%; margin-top: 1%; } .setmargin_0 { margin-top: 200px; } #right_0 { display: none; } #right_1 { display: none; } #right_2 { display: none; } #right_3 { display: none; } .modal-backdrop { position: static; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000; } .inputmargin_1 { margin-left: 10px; } .inputmargin_2 { margin-left: 20px; } input, textarea { display: inline-block; margin-right: 3px; vertical-align: middle; } #kindgame { height: 200px; overflow-y: scroll; } ================================================ FILE: src/main/webapp/WEB-INF/css/base.css ================================================ @charset "utf-8"; /* CSS Document */ body { background-color: #183F59; } .headheight { padding-top: 20px; padding-bottom: 10px; } .headmid { margin-left: 500px; margin-top: 100px; } .nav navbar-nav navbar-right { padding: 0px; margin: 0px; font-size: 30px; } .form-control { background-color: #316282; border: 0px; color: #FFF; } .btn { background-color: #316282; border: 0px; padding: 9px 12px; } .daohangyanse { background-color: #356F95; border: none; } .navbar-default .navbar-nav > li > a { color: #FFF; font-family: "Motiva Sans", Sans-serif; } .inputmargin { margin-left: 230px; } .gutter_header { color: #66c0f4; } .list-group-item { background-color: #183F59; color: #66c0f4; font-size: 13px; font-family: "Motiva Sans", Sans-serif; border: 0px; } .bs:hover { color: #FFF; } .dibu { height: 120px; background-color: #101822; color: #8F98A0; text-align: center; padding-top: 50px; padding-left: 150px; padding-right: 150px; } ul li { list-style-type: none; } .yingcang { display: none; } ================================================ FILE: src/main/webapp/WEB-INF/css/fenleixiangqing.css ================================================ .clx { color: #FFF; font-size: 34px; font-family: "Motiva Sans", Sans-serif; } #fenleixiangqing { padding: 0px; } .imgdx { width: 221px; height: 83px; } .fenleizitiyanse { color: #FFF; } .jutiyouxi { background-color: #16202D; margin-top: 10px; } .youximingzi { margin-top: 10px; } .tags { padding: 2px; background-color: #424242; color: #EEE0E5; margin-right: 4px; font-size: 13px; font-family: "Motiva Sans", Sans-serif; } ul, li { list-style: none; margin: 0px; padding: 0px; } .row { margin-left: 0px; } .youxitupian { display: none; position: absolute; height: 150px; width: 300px; margin-left: 5px; background-color: #EEE0E5; } .imgdx_1 { height: 69px;; width: 184px; } .imgdx { height: 150px; width: 260px; } .font { background-color: #A2B5CD; padding-bottom: 5px; padding-top: 5px; } .font_2 { font-size: 15px; } .font_1 { font-size: 20px; text-align: center; } .deletepadding { padding-right: 0px; } .dibu { margin-top: 160px; } .yingcang { display: none; } .pagination { position: relative; left: 120px; bottom: 0px; } ================================================ FILE: src/main/webapp/WEB-INF/css/login.css ================================================ @charset "utf-8"; /* CSS Document */ .logowz { margin-right: 100px; margin-left: 350px; } .logoztdx { font-size: 25px; } .bjys { background-color: rgba(0, 0, 0, 0.2); } .ztys { color: #c6d4df; } .btys { color: #67c1f5; } .btnys { background: rgba(103, 193, 245, 0.2); color: #c6d4df; border: none; padding: 5px 15px 0px; } .container { height: 650px; } .dlkwz { margin-top: 90px; } .imgdx { max-height: 100%;; max-width: 100%; } ================================================ FILE: src/main/webapp/WEB-INF/css/order.css ================================================ @charset "utf-8"; /* CSS Document */ .container { width: 970px !important } body { background-color: #183F59; } .mar { margin-top: 50px; } td { color: white; width: 100px; } .smargin { color: white; margin-left: 15px; } .td_1 { color: white; width: 250px; } .btn { background-color: #1E6E93; } .setright { float: right; } .setleft { float: left; } .divwidth { width: 300px; } .divsetcenter { margin-left: 45%; } ================================================ FILE: src/main/webapp/WEB-INF/css/personal.css ================================================ body { background-color: #1B2839; } .divcolor { background-image: url(/img/static/personalbackground_1.jpg); color: #FFF; } .divcolor_1 { background-color: #192533; } .ziti { color: #8F98A0; } .ziti_1 { color: #FFF; } .setmargin { margin-top: 20px; } .setmargin_1 { margin-left: 10px; border: none; } .setmargin_2 { margin-top: 100px; } .setpadding { background-color: #103651; padding: 5px, 15px, 5px, 5px; } .setbtnpadding { background-color: #103651; font-size: 16px; border: none; color: #FFF; } .dibu { margin-top: 390px; height: 120px; background-color: #101822; color: #8F98A0; text-align: center; padding-top: 50px; padding-left: 150px; padding-right: 150px; } .fenleizitiyanse { color: #FFF; } .jutiyouxi { background-color: #16202D; margin-top: 10px; } .imgdx_1 { height: 69px;; width: 184px; } .youximingzi { margin-top: 10px; } ul { padding: 0px; } ================================================ FILE: src/main/webapp/WEB-INF/css/regist.css ================================================ @charset "utf-8"; /* CSS Document */ .zczt { color: #c6d4df; margin-bottom: 20px; } .inputcolor { background: #0E2A3A; border: none; } .btnsz { border-color: #67c1f5; } #regist_2 { display: block; } #regist_3 { display: none; } ================================================ FILE: src/main/webapp/WEB-INF/css/sanji.css ================================================ @charset "utf-8"; /* CSS Document */ body { background-color: #183F59; } .headheight { padding-top: 20px; padding-bottom: 10px; } .headmid { margin-left: 500px; margin-top: 100px; } .nav navbar-nav navbar-right { padding: 0px; margin: 0px; } .form-control { background-color: #316282; border: 0px; color: #FFF; } .btn { background-color: #316282; border: 0px; } .daohangyanse { background-color: #356F95; border: none; } .navbar-default .navbar-nav > li > a { color: #FFF; font-family: "Motiva Sans", Sans-serif; } .inputmargin { margin-left: 230px; } .gutter_header { color: #66c0f4; } .list-group-item { background-color: #183F59; color: #66c0f4; font-size: 13px; font-family: "Motiva Sans", Sans-serif; border: 0px; } .dibu { height: 120px; background-color: #101822; color: #8F98A0; text-align: center; padding-top: 50px; padding-left: 150px; padding-right: 150px; } .table_color { color: red; } .bs:hover { color: #FFF; } ul { list-style-type: none; margin: 0; padding: 0; } .deletecolpadding { padding-left: 0px; } .tags { margin-right: 10px; } #carousel_3 { width: 500px; height: 75px; /* 定义显示窗口的大小 */ border: 1px solid #000; overflow: hidden; } #carousel_3 ul { width: 1000px; } /* 定义全部图片的宽度和 */ #carousel_3 li { width: 126px; height: 65px; float: left; } /* 单张图片的所在位置的大小,宽度就是图片宽度加左右边距 */ #carousel_3 img { width: 116px; height: 65px; margin: 5px; } /* 单张图片的尺寸,及外边距 */ .btn_1 { background-color: #316282; border: 0px; width: 15px; padding-left: 5px; padding-top: 28px;; padding-bottom: 28px; margin-top: 2px; } .deletelrpadding { padding-left: 0px; padding-right: 0px; } .addmargin { margin-left: 10px; margin-top: 10px; } .yingcang { display: none; } .carousel-inner>.item>img{ height:337px; } ================================================ FILE: src/main/webapp/WEB-INF/css/self.css ================================================ @charset "utf-8"; /* CSS Document */ body { background-color: #183F59; } .headheight { padding-top: 20px; padding-bottom: 10px; } .headmid { margin-left: 500px; margin-top: 100px; } .nav navbar-nav navbar-right { padding: 0px; margin: 0px; } .form-control { background-color: #316282; border: 0px; color: #FFF; } .btn { background-color: #316282; border: 0px; padding: 9px 12px; } .daohangyanse { background-color: #356F95; border: none; } .navbar-default .navbar-nav > li > a { color: #FFF; font-family: "Motiva Sans", Sans-serif; } .inputmargin { margin-left: 230px; } .carousel img { width: 100%; } .gutter_header { color: #66c0f4; } .list-group-item { background-color: #183F59; color: #66c0f4; font-size: 13px; font-family: "Motiva Sans", Sans-serif; border: 0px; } .tit { color: #fff; font-size: 17px; font-family: "Motiva Sans", Sans-serif; } .tit_0 { margin-bottom: 10px; } .tit_1 { margin-top: 30px; margin-bottom: 10px; } .carousel .item_0 { background-color: #183F59; width: 616px; height: 353px; float: left; } .carousel .item_1 { background-color: #171a21; width: 306px; height: 353px; float: left; font-size: 24px; color: #fff; font-family: "Motiva Sans", Sans-serif; text-align: center; line-height: 390px; } .carousel-inner { height: 392px; } .carousel .item_1_1 { background-color: #183F59; width: 306px; height: 203px; float: left; } #carousel-example-generic { width: 925px; } #carousel_1 { width: 920px; } .tit span { font-size: 12px; float: right; color: #fff; border-style: solid; border-width: 1px; border-color: #FFF; padding: 4px; } .zhekou { position: relative; bottom: 50px; left: 1px; width: 35px; height: 15px; background-color: #090; font-size: 12px; font-family: Arial, Helvetica, sans-serif; color: #FFF; line-height: 15px; } .shoujia { position: relative; bottom: 65px; left: 36px; width: 100px; height: 15px; font-size: 12px; font-family: Arial, Helvetica, sans-serif; color: #FFF; line-height: 15px; } .shoujia_1 { position: relative; bottom: 50px; left: 1px; } .zhichi { position: relative; bottom: 95px; left: 250px; width: 35px; height: 15px; line-height: 15px; } .zhichi_1 { position: relative; bottom: 80px; left: 250px; } .zhichi_2 { position: relative; bottom: 115px; left: 215px; } .liulan { width: 226px; height: 58px; background-color: #1E6E93; text-align: center; line-height: 58px; color: #66c0f4; } .bs:hover { color: #FFF; } .zx { margin-top: 90px; background-color: #183F59; } .rowpy { margin-left: 0px; } .nav-tabs { border: none; } .dibu { height: 120px; background-color: #101822; color: #8F98A0; text-align: center; padding-top: 50px; padding-left: 150px; padding-right: 150px; } .yingcang { display: none; } ul li { list-style-type: none; } .nav nav-tabs { width: 590px; } .imgwh { height: 353px; } .zximgwh { height: 140px; width: 300px; } .zximgwh_1 { height: 140px; width: 295px; margin-top: 2px; text-align: center; } .rowpy { margin-bottom: 2px; background-color: #1D3041; color: white; } .cancelpadding { padding: 0px; } .smargin { margin-top: 15px; } .smargin_1 { float: right; margin-right: 20px; margin-top: 25px; } .smargin_2 { margin-top: 70px; } .smargin_3 { font-size: 20px; color: #183F59; } .smargin_4 { margin-top: 5px; margin-bottom: 5px; font-size: 8px; color: #c6d4df; } .smargin_5 { margin-bottom: 10px; } .spadding { padding-top: 10px; padding-bottom: 10px; background-color: #356F95; margin-top: 40px; } .divHover { color: white; } .all_bg { width: 800px; height: 600px; margin: 0px auto; } #allcanvas { position: relative; width: 800px; height: 600px; margin: 0px; } #canvas1 { position: absolute; bottom: 0; left: 0; z-index: 1; } #canvas2 { position: absolute; bottom: 0; left: 0; z-index: 0; } #playbtn { position: absolute; bottom: 0; left: 0; z-index: 2; } ================================================ FILE: src/main/webapp/WEB-INF/css/shoppingcart.css ================================================ @charset "utf-8"; /* CSS Document */ body { background-color: #1B2839; } .headheight { padding-top: 20px; } .headmid { margin-left: 500px; margin-top: 100px; } .nav navbar-nav navbar-right { padding: 0px; margin: 0px; } .form-control { background-color: #316282; border: 0px; color: #FFF; } .btn { background-color: #316282; border: 0px; } .daohangyanse { background-color: #356F95; border: none; } .navbar-default .navbar-nav > li > a { color: #FFF; font-family: "Motiva Sans", Sans-serif; } .inputmargin { margin-left: 230px; } .gutter_header { color: #66c0f4; } .list-group-item { background-color: #183F59; color: #66c0f4; font-size: 13px; font-family: "Motiva Sans", Sans-serif; border: 0px; } .dibu { height: 120px; background-color: #101822; color: #8F98A0; text-align: center; padding-top: 50px; padding-left: 150px; padding-right: 150px; } .the0 { font-size: larger; margin-left: 200px; } tr { font-size: 22px; border-bottom-style: solid; border-bottom-width: 20px; height: 60px; border: 20px; border-bottom-color: #FFC; } .yingcang { display: none; } ================================================ FILE: src/main/webapp/WEB-INF/js/adminlogin.js ================================================ function login() { var username = document.getElementById("username").value; var password = document.getElementById("password").value; $.post("/admin/login", {username: username, password: password}, function (result) { if (result.success) { window.location.href = "/admin/home" } else { alert(result.msg); } }) } ================================================ FILE: src/main/webapp/WEB-INF/js/adminpage.js ================================================ // JavaScript Document $( function () { // 获取用户信息 var userInfo = document.getElementById("userInfo"); $.post("/admin/getuser", function (result) { for (i = 0; i < 10; i++) { if (result.data.user[i]) { var tr = document.createElement("tr"); var j = i + 1; var uid = result.data.user[i].id; var stat = result.data.user[i].stat; var time = new Date(result.data.user[i].ctime).toLocaleString(); if (stat == '0') { stat = "未激活"; } if (stat == '1') { stat = "正常"; } if (stat == '2') { stat = '限制登录'; } if (stat == '3') { stat = '删除'; } tr.innerHTML = "" + j + "" + result.data.user[i].username + "" + result.data.user[i].nickname + "" + result.data.user[i].email + "" + result.data.user[i].phone + "" + time + "" + stat + ""; userInfo.appendChild(tr); } } // 用户信息的分页 var ul = document.getElementById("paging_0"); ul.className = "pagination"; var pages = result.data.page.pages; var li_first = document.createElement("li"); li_first.innerHTML = "«"; ul.appendChild(li_first); for (i = 0; i < pages; i++) { var li = document.createElement("li"); var j = i + 1; li.innerHTML = "" + j + ""; ul.appendChild(li); } var li_last = document.createElement("li"); li_last.innerHTML = "»"; ul.appendChild(li_last); }) // 获取游戏信息 var gameInfo = document.getElementById("gameInfo"); $.post("/admin/getgames", function (result) { for (i = 0; i < 10; i++) { if (result.data.game[i]) { var tr = document.createElement("tr"); var j = i + 1; var gid = result.data.game[i].id; var stat = result.data.game[i].stat; if (stat == "1") { stat = "已上架"; } if (stat == "2") { stat = "已下架"; } if (stat == "0") { stat = "未上架"; } tr.innerHTML = "" + j + "" + result.data.game[i].name + "" + result.data.game[i].price + "" + stat + "" + text_1 + "

编号" + "


" + "

种类" + "


" + "" + "" + "" + "" + "" + "" + text + "

编号" + "


" + "

游戏" + "


" + "

价格" + "


" + "

开发商" + "


" + "

描述" + "


" + "

配置" + "


" + "" + "" + "" + "" + "" + ""; gameInfo.appendChild(tr); } } // 游戏信息的分页 var ul = document.getElementById("paging_1"); ul.className = "pagination"; var pages = result.data.page.pages; var current = result.data.page.current; var last = current - 1; var next = current + 1; if (last < 1) { last = 1 } if (next > pages) { next = pages } var li_first = document.createElement("li"); li_first.id = "li_first"; li_first.innerHTML = "«"; ul.appendChild(li_first); document.getElementById("li_first").className = "disabled"; for (i = 0; i < pages; i++) { var j = i + 1; var li = document.createElement("li"); li.id = "li_" + j; li.innerHTML = "" + j + ""; ul.appendChild(li); } document.getElementById("li_" + current).className = "active"; var li_last = document.createElement("li"); li_last.innerHTML = "»"; ul.appendChild(li_last); }) //种类管理 var kind_all = document.getElementById("kind_all"); $.post("/kind/all", function (result) { var i = 0; while (result.data[i]) { j = i + 1; var tr = document.createElement("tr"); var kid = result.data[i].id; tr.innerHTML = "" + result.data[i].id + "" + result.data[i].name + "" + text_2 + "

种类编号" + "


" + "

游戏" + "


" + "" + "" + "" + "" + "" + ""; i++; kind_all.appendChild(tr); } }) } ) //游戏信息分页的函数 function getgeame(pagenum) { var gameInfo = document.getElementById("gameInfo"); gameInfo.innerHTML = ""; $.post("/admin/getgames", {page: pagenum}, function (result) { for (i = 0; i < 10; i++) { if (result.data.game[i]) { var tr = document.createElement("tr"); var j = 10 * (pagenum - 1) + i + 1; var gid = result.data.game[i].id; var stat = result.data.game[i].stat; if (stat == "1") { stat = "已上架"; } if (stat == "2") { stat = "已下架"; } if (stat == "0") { stat = "未上架"; } tr.innerHTML = "" + j + "" + result.data.game[i].name + "" + result.data.game[i].price + "" + stat + "" + text_1 + "

编号" + "


" + "

种类" + "


" + "" + "" + "" + "" + "" + "" + text + "

编号" + "


" + "

游戏" + "


" + "

价格" + "


" + "

开发商" + "


" + "

描述" + "


" + "

配置" + "


" + "" + "" + "" + "" + "" + ""; gameInfo.appendChild(tr); } } var ul = document.getElementById("paging_1"); ul.className = "pagination"; ul.innerHTML = ""; var pages = result.data.page.pages; var current = result.data.page.current; var last = current - 1; var next = current + 1; if (last < 1) { last = 1 } if (next > pages) { next = pages } var li_first = document.createElement("li"); li_first.id = "li_first"; li_first.innerHTML = "«"; ul.appendChild(li_first); for (i = 0; i < pages; i++) { var j = i + 1; var li = document.createElement("li"); li.id = "li_" + j; li.innerHTML = "" + j + ""; ul.appendChild(li); } document.getElementById("li_" + pagenum).className = "active"; if (current <= "1") { document.getElementById("li_first").className = "disabled"; } var li_last = document.createElement("li"); li_last.id = "li_next"; li_last.innerHTML = "»"; ul.appendChild(li_last); if (current >= i) { document.getElementById("li_next").className = "disabled"; } }) } //限制用户登录 function restrict(uid, j) { $.post("/admin/restrictuser", {uid: uid}, function (result) { if (result.success) { alert("该用户已被限制登录!"); document.getElementById("ustat_" + j).innerHTML = "限制登录"; } else { alert(result.msg); } }) } //恢复用户 function relieve(uid, j) { $.post("/admin/relieveuser", {uid: uid}, function (result) { if (result.success) { alert("该用户已被恢复登录!"); document.getElementById("ustat_" + j).innerHTML = "正常"; } else { alert(result.msg); } }) } //删除用户 function del(uid, j) { $.post("/admin/deluser", {uid: uid}, function (result) { if (result.success) { alert("该用户已被删除!"); document.getElementById("ustat_" + j).innerHTML = "删除"; } else { alert(result.msg); } }) } //上架游戏 function upgame(gid, j) { $.post("/admin/upgame", {game: gid}, function (result) { if (result.success) { alert("游戏已上架!") document.getElementById("gstat_" + j).innerHTML = "已上架"; } else { alert(result.msg); } }) } //下架游戏 function downgame(gid, j) { $.post("/admin/downgame", {game: gid}, function (result) { if (result.success) { alert("游戏已下架!") document.getElementById("gstat_" + j).innerHTML = "已下架"; } else { alert(result.msg); } }) } //获取游戏种类 function getgamekind(gid) { document.getElementById("gamekindid").value = gid; var kinds = new Array(); $.post("/kind/all", function (result) { var i = 0; document.getElementById("gamekind").innerHTML = "种类"; while (result.data[i]) { document.getElementById("gamekind").innerHTML += "
" + "" + result.data[i].name; kinds[i] = result.data[i].name; i++; } }) $.post("/admin/getgamekind", {game: gid}, function (result) { var i = 0; var j = 0; while (result.data[i]) { while (kinds[j]) { if (result.data[i].name == kinds[j]) { document.getElementById("kindbox_" + gid + "_" + j).checked = "true"; } j++; } i++; j = 0; } i = 0; }) } //保存游戏种类 function savekinds() { var i = 0; var j = 0; var kid = document.getElementById("gamekindid").value; var check = document.getElementById("kindbox_" + kid + "_" + i); var kinds = new Array(); while (check) { if (check.checked) { kinds[j] = parseInt(i + 1); j++; } i++; check = document.getElementById("kindbox_" + kid + "_" + i); } $.ajax({ type: "post", url: "/admin/updategamekind", traditional: true, data: {game: kid, kinds: kinds}, success: function (result) { if (result.success) { alert("修改成功!"); } else alert(result.msg); } }) $('#myModal_1').modal('hide'); } function managekind(kid) { // var kidpages=2; // var currentpage = 1; document.getElementById("kindgameid").value = kid; var i = 0; $.post("/admin/getallgames", function (result) { document.getElementById("kindgame").innerHTML = "游戏"; while (result.data[i]) { var j = result.data[i].id; document.getElementById("kindgame").innerHTML += "
" + "" + result.data[i].name; i++; } var j = 0; i = 0; while (result.data[i]) { if (result.data[i].kinds) { while (result.data[i].kinds[j]) { if (result.data[i].kinds[j].id == kid) { var gid = result.data[i].id; document.getElementById("kind_" + kid + "_" + gid).checked = true; } j++; } } i++; j = 0; } }) } function savekindsgames() { var kid = document.getElementById("kindgameid").value; var i = 0; var games = new Array(); var num = 0; var gamebox = document.getElementsByClassName("gamebox"); while (gamebox[i]) { if (gamebox[i].checked) { games[num] = (gamebox[i].id).split('_')[2]; num++; } i++; } i = 0; $.ajax({ type: "post", url: "/admin/managerkind", traditional: true, data: {kind: kid, games: games}, success: function (result) { if (result.success) { alert("修改成功!"); } else alert(result.msg); } }) $('#myModal_2').modal('hide'); } function showright_0() { document.getElementById("right_0").style.display = "block"; document.getElementById("right_1").style.display = "none"; document.getElementById("right_2").style.display = "none"; document.getElementById("right_3").style.display = "none"; } function showright_1() { document.getElementById("right_0").style.display = "none"; document.getElementById("right_1").style.display = "block"; document.getElementById("right_2").style.display = "none"; document.getElementById("right_3").style.display = "none"; } function showright_2() { document.getElementById("right_0").style.display = "none"; document.getElementById("right_1").style.display = "none"; document.getElementById("right_2").style.display = "block"; document.getElementById("right_3").style.display = "none"; } function showright_3() { document.getElementById("right_0").style.display = "none"; document.getElementById("right_1").style.display = "none"; document.getElementById("right_2").style.display = "none"; document.getElementById("right_3").style.display = "block"; } //导航菜单 function navList(id) { var $obj = $("#nav_dot"), $item = $("#J_nav_" + id); $item.addClass("on").parent().removeClass("none").parent().addClass("selected"); $obj.find("h4").hover(function () { $(this).addClass("hover"); }, function () { $(this).removeClass("hover"); }); $obj.find("p").hover(function () { if ($(this).hasClass("on")) { return; } $(this).addClass("hover"); }, function () { if ($(this).hasClass("on")) { return; } $(this).removeClass("hover"); }); $obj.find("h4").click(function () { var $div = $(this).siblings(".list-item"); if ($(this).parent().hasClass("selected")) { $div.slideUp(600); $(this).parent().removeClass("selected"); } if ($div.is(":hidden")) { $("#nav_dot li").find(".list-item").slideUp(600); $("#nav_dot li").removeClass("selected"); $(this).parent().addClass("selected"); $div.slideDown(600); } else { $div.slideUp(600); } }); } /****表格隔行高亮显示*****/ window.onload = function () { oTable = document.getElementById("tab");//找表格 aTr = document.getElementsByTagName("tr");//找所有的行 for (i = 0; i < aTr.length; i++) { if (i % 2 == 0) { aTr[i].style.background = "#fff"; } else { aTr[i].style.background = "#ccc"; } ; } ; }; var text = "