Commit 43cdaff0 authored by R10's avatar R10

project init

parents
/log/
/.idea/
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are 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.
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.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
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 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 work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
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 AGPL, see
<http://www.gnu.org/licenses/>.
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" dumb="true">
<sourceFolder url="file://$MODULE_DIR$/src/main/test" isTestSource="true" />
</content>
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tools</groupId>
<artifactId>hxyj-api</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.8.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--打成War包,排除内置Tomcat容器-->
<!-- <scope>provided</scope>-->
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.shiro</groupId>-->
<!-- <artifactId>shiro-spring-boot-web-starter</artifactId>-->
<!-- <version>1.4.1</version>-->
<!-- </dependency>-->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</dependency>
<!-- 邮件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.14</version>
</dependency>
<!-- 阿里云存储SDK -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.6.0</version>
</dependency>
<!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.28.0</version>
</dependency>
<!-- Sa-Token 整合jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
<version>1.28.0</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用jdk默认序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>1.28.0</version>
</dependency>
<!-- 提供Redis连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.1-jre</version>
</dependency>
<!-- fastdfs SDK -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.6</version>
</dependency>
<!--爬虫-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<!--小程序工具包-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>5.1.1</version>
</dependency>
<!--分布式-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.11.5</version>
</dependency>
<!--图片处理-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.11</version>
</dependency>
<!--定时任务-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!--分布式文件服务SDK-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.0.2</version>
</dependency>
<!--百度人工智能SDK-->
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.12.0</version>
</dependency>
<!-- swagger2 文档 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
</dependencies>
<build>
<finalName>picture-bed</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.7.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableScheduling;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 启动类
*/
@EnableCaching
@EnableScheduling
@EnableSwagger2
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
logger.info("这个是航行印记项目");
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}
package com.tools.common.aop;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.RateLimiter;
import com.tools.common.exception.RrException;
import com.tools.common.util.IPUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
/**
* 限流 AOP
*
*
*/
@Aspect
@Configuration
public class LimitAspect {
/**
* 根据IP分不同的令牌桶, 每天自动清理缓存 每秒只发出6个令牌
*/
private static final LoadingCache<String, RateLimiter> caches = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(1, TimeUnit.DAYS)
.build(new CacheLoader<String, RateLimiter>() {
@Override
public RateLimiter load(String key) {
return RateLimiter.create(6);
}
});
/**
* Service层切点 限流
*/
@Pointcut("@annotation(com.tools.common.aop.ServiceLimit)")
public void ServiceAspect() {
}
@Around("ServiceAspect()")
public Object around(ProceedingJoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
ServiceLimit limitAnnotation = method.getAnnotation(ServiceLimit.class);
ServiceLimit.LimitType limitType = limitAnnotation.limitType();
String key = limitAnnotation.key();
Object obj;
try {
if(limitType.equals(ServiceLimit.LimitType.IP)){
key = IPUtils.getIpAddr();
}
RateLimiter rateLimiter = caches.get(key);
Boolean flag = rateLimiter.tryAcquire();
if(flag){
obj = joinPoint.proceed();
}else{
throw new RrException("小同志,你访问的太频繁了");
}
} catch (Throwable e) {
e.printStackTrace();
throw new RrException("系统异常,请联系管理员同志");
}
return obj;
}
}
\ No newline at end of file
package com.tools.common.aop;
import java.lang.annotation.*;
/**
* 自定义注解 限流
*
*
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ServiceLimit {
/**
* 描述
*/
String description() default "";
/**
* key
*/
String key() default "";
/**
* 类型
*/
LimitType limitType() default LimitType.CUSTOMER;
enum LimitType {
/**
* 自定义key
*/
CUSTOMER,
/**
* 根据请求者IP
*/
IP
}
}
\ No newline at end of file
package com.tools.common.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
/**
* 通用Controller
*
*
*/
@RestController
public class AbstractController {
protected Logger logger = LoggerFactory.getLogger(getClass());
}
\ No newline at end of file
package com.tools.common.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@Configuration
@EnableJpaAuditing(auditorAwareRef="saAuditorAware")
public class EnableJpaAuditingConfig {
}
\ No newline at end of file
package com.tools.common.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* file映射项目外文件夹
*
*
*/
@Configuration
public class FileConfig implements WebMvcConfigurer {
@Value("${file.path}")
private String filePath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/file/**").addResourceLocations("file:" + filePath+"/");
}
}
package com.tools.common.config;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* 通用访问拦截匹配
*
*
*/
@Controller
public class IndexController {
@GetMapping("login.html")
public String login() { return "login"; }
@GetMapping("index.html")
public String index() { return "index"; }
@GetMapping("console.html")
public String console() { return "console"; }
@GetMapping("{module}/{url}.html")
public String page(@PathVariable("module") String module,@PathVariable("url") String url) {
return module + "/" + url;
}
@GetMapping("{module}/{sub}/{url}.html")
public String page(@PathVariable("module") String module,
@PathVariable("url") String url,
@PathVariable("sub") String sub) {
return module + "/" + sub + "/" + url;
}
@GetMapping("{module}/{sub}/{smallSub}/{url}.html")
public String page(@PathVariable("module") String module,
@PathVariable("url") String url,
@PathVariable("sub") String sub,
@PathVariable("smallSub") String smallSub) {
return module + "/" + sub + "/" + smallSub + "/" + url;
}
}
\ No newline at end of file
package com.tools.common.config;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* redis配置类
*
*
*/
@Configuration
@EnableCaching
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(60))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware()
.build();
}
/**
* retemplate相关配置
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}
package com.tools.common.config;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class SaAuditorAware implements AuditorAware<Long> {
@Override
public Optional<Long> getCurrentAuditor() {
//return Optional.of((String) SecurityUtils.getSubject().getPrincipal());
Long userId = StpUtil.getLoginIdAsLong();
return Optional.of(userId);
}
}
\ No newline at end of file
package com.tools.common.config;
import cn.dev33.satoken.jwt.StpLogicJwtForStyle;
import cn.dev33.satoken.stp.StpLogic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
/**
* 注册Sa-Token的拦截器
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册路由拦截器,自定义认证规则
// registry.addInterceptor(new SaRouteInterceptor((req, res, handler) ->
// {
// // 登录认证 -- 拦截所有路由,并排除/login 用于开放登录
// SaRouter.match("/**", "/user/login", r -> StpUtil.checkLogin());
// SaRouter.match("/systemConfig/**", () -> StpUtil.checkRoleOr("admin", "salesman"));
// SaRouter.match("/customer/addCustomer", () -> StpUtil.checkRoleOr("admin", "salesman"));
// SaRouter.match("/sales-man/**", () -> StpUtil.checkRoleOr("admin", "salesman"));
// // 权限认证:匹配restful风格路由、多个条件一起使用
// SaRouter.match(SaHttpMethod.GET).match("/admins").check(r ->StpUtil.checkPermission("admin:list"));
// SaRouter.match(SaHttpMethod.POST).match("/admin").check(r ->StpUtil.checkPermission("admin:add"));
// SaRouter.match(SaHttpMethod.PUT).match("/admin").check(r ->StpUtil.checkPermission("admin:edit"));
// SaRouter.match(SaHttpMethod.GET).match("/admin/{id}").check(r ->StpUtil.checkPermission("admin:query"));
// SaRouter.match(SaHttpMethod.DELETE).match("/admin/{id}").check(r ->StpUtil.checkPermission("admin:del"));
//
// SaRouter.match(SaHttpMethod.GET).match("/roles").check(r ->StpUtil.checkPermission("role:list"));
// SaRouter.match(SaHttpMethod.POST).match("/role").check(r ->StpUtil.checkPermission("role:add"));
// SaRouter.match(SaHttpMethod.PUT).match("/role").check(r ->StpUtil.checkPermission("role:edit"));
// SaRouter.match(SaHttpMethod.GET).match("/role/{id}").check(r ->StpUtil.checkPermission("role:query"));
// SaRouter.match(SaHttpMethod.DELETE).match("/role/{id}").check(r ->StpUtil.checkPermission("role:del"));
//
// SaRouter.match(SaHttpMethod.GET).match("/menus").check(r ->StpUtil.checkPermission("menu:list"));
// SaRouter.match(SaHttpMethod.POST).match("/menu").check(r ->StpUtil.checkPermission("menu:add"));
// SaRouter.match(SaHttpMethod.PUT).match("/menu").check(r ->StpUtil.checkPermission("menu:edit"));
// SaRouter.match(SaHttpMethod.GET).match("/menu/{id}").check(r ->StpUtil.checkPermission("menu:query"));
// SaRouter.match(SaHttpMethod.DELETE).match("/menu/{id}").check(r ->StpUtil.checkPermission("menu:del"));
// })).addPathPatterns("/**").excludePathPatterns("/price/**");
}
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForStyle();
}
}
package com.tools.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
/**
* API 配置
*
*/
@Configuration
public class SwaggerConfig {
@Bean
public Docket appApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("系统应用API接口文档")
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.tools.module.app"))
.paths(PathSelectors.any()).build();
}
@Bean
public Docket sysApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("系统配置API接口文档")
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.tools.module.sys"))
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("炒鸡工具箱")
.description("一个能够让程序猿快速开发的炒鸡工具箱")
.termsOfServiceUrl("http://blog.52itstyle.vip")
.contact(new Contact("爪哇笔记 ", "http://blog.52itstyle.vip", "345849402@qq.com"))
.version("1.0").build();
}
}
package com.tools.common.constant;
/**
* 系统提示静态变量
*
*
*/
public class MsgConstant {
/**
* 操作成功
*/
public static final String MSG_OPERATION_SUCCESS = "操作成功!";
/**
* 操作失败
*/
public static final String MSG_OPERATION_FAILED = "操作失败!";
/**
* 删除时,提示有子节点无法删除
*/
public static final String MSG_HAS_CHILD = "操作失败,当前所选数据有子节点数据!";
/**
* 加载表单数据错误提示
*/
public static final String MSG_INIT_FORM = "初始化表单数据失败,请重试!";
}
package com.tools.common.constant;
/**
* 系统级静态变量
*
*/
public class SystemConstant {
public class IsDeleted{
public static final String Y = "Y";
public static final String N = "N";
}
/**
* 文件分隔符
*/
public static final String SF_FILE_SEPARATOR = System.getProperty("file.separator");
/**
* 菜单类型
*/
public enum MenuType {
/**
* 目录
*/
CATALOG(0),
/**
* 菜单
*/
MENU(1),
/**
* 按钮
*/
BUTTON(2);
private final int value;
MenuType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* 通用字典
*/
public enum MacroType {
/**
* 类型
*/
TYPE(0),
/**
* 参数
*/
PARAM(1);
private final int value;
MacroType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
/**
* 通用变量,表示可用、禁用、显示、隐藏、是、否
*/
public enum StatusType {
/**
* 禁用,隐藏
*/
DISABLE(0),
/**
* 可用,显示
*/
ENABLE(1),
/**
* 显示
*/
SHOW(1),
/**
* 隐藏
*/
HIDDEN(0),
/**
* 是
*/
YES(1),
/**
* 否
*/
NO(0);
private final int value;
StatusType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
}
package com.tools.common.dynamicquery;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.List;
/**
* 扩展SpringDataJpa, 支持动态jpql/nativesql查询并支持分页查询
*
*/
public interface DynamicQuery {
/**
* 保存
* @param entity
*/
void save(Object entity);
/**
* 更新
* @param entity
*/
void update(Object entity);
/**
* 执行nativeSql的update,delete操作
* @param nativeSql
* @param params
* @return
*/
int nativeExecuteUpdate(String nativeSql, Object... params);
/**
* 执行nativeSql统计查询
* @param nativeSql
* @param params 占位符参数(例如?1)绑定的参数值
* @return 统计条数
*/
Long nativeQueryCount(String nativeSql, Object... params);
/**
* 执行nativeSql查询一行
* @param resultClass 查询结果类型
* @param nativeSql
* @param params 占位符参数(例如?1)绑定的参数值
* @return
*/
<T> T nativeQuerySingleResult(Class<T> resultClass, String nativeSql, Object... params);
/**
* 执行nativeSql查询 List<Object[]>
* @param nativeSql
* @param params 占位符参数(例如?1)绑定的参数值
* @return
*/
<T> List<T> query(String nativeSql, Object... params);
/**
* 执行nativeSql查询
* @param resultClass
* @param nativeSql
* @param params 占位符参数(例如?1)绑定的参数值
* @return
*/
<T> List<T> query(Class<T> resultClass, String nativeSql, Object... params);
Long nativeQueryGetCount(String nativeSql, Object... params);
/**
* 执行nativeSql分页查询
* @param resultClass 查询结果类型
* @param pageable 分页数据
* @param nativeSql
* @param params 占位符参数(例如?1)绑定的参数值
* @return 分页对象
*/
<T> Page<T> nativeQuery(Class<T> resultClass, Pageable pageable, String nativeSql, Object... params);
/**
* 执行nativeSql分页查询
* @param resultClass
* @param pageable
* @param nativeSql
* @param params
* @param List<T>
* @return
*/
<T> List<T> nativeQueryPagingList(Class<T> resultClass, Pageable pageable, String nativeSql, Object... params);
<T> Page<T> nativeQueryPageList(Class<T> resultClass, Pageable pageable, String nativeSql,
Object... params);
/**
* 查询对象列表,返回List<Map<key,value>>
* @param nativeSql
* @param params
* @return T
*/
<T> T nativeQueryMap(String nativeSql, Object... params);
/**
* 查询对象列表,返回List<组合对象>
* @param resultClass
* @param nativeSql
* @param params
* @return
*/
<T> T nativeQueryModel(Class<T> resultClass, String nativeSql, Object... params);
/**
* 查询对象列表,返回List<Map<key,value>>
* @param nativeSql
* @param params
* @return List<T>
*/
<T> List<T> nativeQueryListMap(String nativeSql, Object... params);
/**
* 查询对象列表,返回List<组合对象>
* @param resultClass
* @param nativeSql
* @param params
* @return List<T>
*/
<T> List<T> nativeQueryListModel(Class<T> resultClass, String nativeSql, Object... params);
/**
* 查询对象列表,返回List<组合对象>
* @param resultClass
* @param nativeSql
* @param params
* @return List<T>
*/
<T> List<T> nativeQueryPagingListModel(Class<T> resultClass, Pageable pageable, String nativeSql, Object... params);
}
package com.tools.common.dynamicquery;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.List;
/**
* 查询的实现类
*
*
*/
@Repository
public class DynamicQueryImpl implements DynamicQuery {
/**
* @PersistenceContext(type = PersistenceContextType.EXTENDED)
* 默认是 PersistenceContextType.TRANSACTION 开启只读事物
*/
@PersistenceContext
private EntityManager em;
public EntityManager getEntityManager() {
return em;
}
@Override
public void save(Object entity) {
em.persist(entity);
}
@Override
public void update(Object entity) {
em.merge(entity);
}
private Query createNativeQuery(String sql, Object... params) {
Query q = em.createNativeQuery(sql);
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
q.setParameter(i + 1, params[i]);
}
}
return q;
}
@Override
public int nativeExecuteUpdate(String nativeSql, Object... params) {
return createNativeQuery(nativeSql, params).executeUpdate();
}
@Override
public <T> T nativeQuerySingleResult(Class<T> resultClass, String nativeSql, Object... params) {
Query q = createNativeQuery(resultClass, nativeSql, params);
List<T> list = q.getResultList();
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
private <T> Query createNativeQuery(Class<T> resultClass, String sql, Object... params) {
Query q;
if (resultClass == null) {
q = em.createNativeQuery(sql);
} else {
q = em.createNativeQuery(sql, resultClass);
}
if(params!=null){
for (int i = 0; i < params.length; i++) {
q.setParameter(i + 1, params[i]);
}
}
return q;
}
@Override
public <T> List<T> query(String nativeSql, Object... params) {
Query q = createNativeQuery(null, nativeSql, params);
return q.getResultList();
}
@Override
public <T> List<T> query(Class<T> resultClass, String nativeSql, Object... params) {
Query q = createNativeQuery(resultClass, nativeSql, params);
return q.getResultList();
}
@Override
public Long nativeQueryCount(String nativeSql, Object... params) {
nativeSql = StringUtils.substringBefore(nativeSql, "order by");
Object count = createNativeQuery(nativeSql, params).getSingleResult();
return ((Number) count).longValue();
}
@Override
public Long nativeQueryGetCount(String nativeSql, Object... params) {
nativeSql = StringUtils.substringBefore(nativeSql, "order by");
List count = createNativeQuery(nativeSql, params).getResultList();
return ((Number) count.size()).longValue();
}
@Override
public <T> Page<T> nativeQuery(Class<T> resultClass, Pageable pageable, String nativeSql, Object... params) {
List<T> rows = nativeQueryPagingList(resultClass, pageable, nativeSql, params);
Long total = nativeQueryCount(nativeSql, params);
return new PageImpl<>(rows, pageable, total);
}
@Override
public <T> List<T> nativeQueryPagingList(Class<T> resultClass, Pageable pageable, String nativeSql,
Object... params) {
Integer pageNumber = pageable.getPageNumber();
Integer pageSize = pageable.getPageSize();
Integer startPosition = pageNumber * pageSize;
return createNativeQuery(resultClass, nativeSql, params)
.setFirstResult(startPosition).setMaxResults(pageSize)
.getResultList();
}
@Override
public <T> Page<T> nativeQueryPageList(Class<T> resultClass, Pageable pageable, String nativeSql,
Object... params) {
Integer pageNumber = pageable.getPageNumber();
Integer pageSize = pageable.getPageSize();
Integer startPosition = pageNumber * pageSize;
Long total = nativeQueryGetCount(nativeSql, params);
return new PageImpl<>(createNativeQuery(resultClass, nativeSql, params)
.setFirstResult(startPosition).setMaxResults(pageSize)
.getResultList(), pageable, total);
}
@Override
public <T> T nativeQueryMap(String nativeSql, Object... params) {
Query q = createNativeQuery(nativeSql, params);
q.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
List<T> list = q.getResultList();
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
@Override
public <T> T nativeQueryModel(Class<T> resultClass, String nativeSql, Object... params) {
Query q = createNativeQuery(nativeSql, params);
q.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(resultClass));
List<T> list = q.getResultList();
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
@Override
public <T> List<T> nativeQueryListModel(Class<T> resultClass,
String nativeSql, Object... params) {
Query q = createNativeQuery(nativeSql, params);
q.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(resultClass));
return q.getResultList();
}
@Override
public <T> List<T> nativeQueryPagingListModel(Class<T> resultClass, Pageable pageable, String nativeSql, Object... params) {
Integer pageNumber = pageable.getPageNumber();
Integer pageSize = pageable.getPageSize();
Integer startPosition = pageNumber * pageSize;
Query q = createNativeQuery(nativeSql, params)
.setFirstResult(startPosition).setMaxResults(pageSize);
q.unwrap(NativeQueryImpl.class)
.setResultTransformer(Transformers.aliasToBean(resultClass));
return q.getResultList();
}
@Override
public <T> List<T> nativeQueryListMap(String nativeSql, Object... params) {
Query q = createNativeQuery(nativeSql, params);
q.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return q.getResultList();
}
}
package com.tools.common.excel;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
/**
* Excel 工具类
*
*/
public class ExcelUtil {
/**
* 导出 Excel :一个 sheet,带表头.
* @param response HttpServletResponse
* @param data 数据 list,每个元素为一个 BaseRowModel
* @param fileName 导出的文件名
* @param sheetName 导入文件的 sheet 名
* @param model 映射实体类,Excel 模型
* @throws Exception 异常
*/
public static void writeExcel(HttpServletResponse response, List<? extends Object> data,
String fileName, String sheetName, Class model) throws Exception {
/**
* 头的策略 设置表头居中对齐
*/
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
/**
* 内容的策略 设置内容靠左对齐
*/
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
HorizontalCellStyleStrategy horizontalCellStyleStrategy =
new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
EasyExcel.write(getOutputStream(fileName, response), model)
.excelType(ExcelTypeEnum.XLSX)
.sheet(sheetName)
.registerWriteHandler(horizontalCellStyleStrategy)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.doWrite(data);
}
/**
* 导出文件时为Writer生成OutputStream.
* @param fileName 文件名
* @param response response
* @return ""
*/
private static OutputStream getOutputStream(String fileName,
HttpServletResponse response) throws Exception {
try {
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
response.setHeader("Pragma", "public");
response.setHeader("Cache-Control", "no-store");
response.addHeader("Cache-Control", "max-age=0");
return response.getOutputStream();
} catch (IOException e) {
throw new Exception("导出excel表格失败!", e);
}
}
}
\ No newline at end of file
package com.tools.common.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import lombok.Data;
import java.io.Serializable;
/**
* 简单的用户封装
*
*/
@Data
@ColumnWidth(22)
@ContentRowHeight(15)
public class User implements Serializable {
/**
* value: 表头名称
* index: 列的号, 0表示第一列
*
*/
/**
* 入库时间
*/
@ExcelProperty(value = "姓名", index = 0)
private String name;
/**
* 供应商
*/
@ExcelProperty(value = "年龄", index = 1)
private String age;
/**
* 纸筒编号
*/
@ExcelProperty(value = "性别", index = 2)
private String sex;
}
package com.tools.common.exception;
import java.io.Serializable;
public class BusinessException extends RuntimeException implements ErrorCoded {
private static final long serialVersionUID = 2332608236621015980L;
private Serializable errorCode = -1;
public BusinessException() {
}
public BusinessException(String message) {
super(message);
}
public BusinessException(Serializable code, String message) {
super(message);
this.errorCode = code;
}
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Serializable code, String message, Throwable cause) {
super(message, cause);
this.errorCode = code;
}
public String toString() {
return "{code=" + this.errorCode + ",errors=" + super.toString() + "}";
}
public Serializable getErrorCode() {
return this.errorCode;
}
}
package com.tools.common.exception;
import java.io.Serializable;
public interface ErrorCoded {
Serializable getErrorCode();
}
package com.tools.common.exception;
/**
* 自定义异常
*
*
*/
public class RrException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
private int code = 500;
public RrException(String msg) {
super(msg);
this.msg = msg;
}
public RrException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public RrException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public RrException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
package com.tools.common.exception;
import com.tools.common.model.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 异常处理器
*
*
*/
@RestControllerAdvice
public class RrExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 自定义异常
*/
@ExceptionHandler(RrException.class)
public Result handleRRException(RrException e){
Result r = new Result();
r.put("code", e.getCode());
r.put("msg", e.getMessage());
return r;
}
/**
* 自定义异常
*/
@ExceptionHandler(BusinessException.class)
public Result handleBusinessException(BusinessException e){
Result r = new Result();
r.put("code", e.getErrorCode());
r.put("msg", e.getMessage());
return r;
}
/**
* 自定义异常
*/
@ExceptionHandler(IllegalArgumentException.class)
public Result handleIllegalArgumentException(IllegalArgumentException e){
Result r = new Result();
r.put("code", "-1");
r.put("msg", e.getMessage());
return r;
}
@ExceptionHandler(DuplicateKeyException.class)
public Result handleDuplicateKeyException(DuplicateKeyException e){
logger.error(e.getMessage(), e);
return Result.error("数据库中已存在该记录");
}
@ExceptionHandler(InvalidDataAccessResourceUsageException.class)
public Result handleDuplicateKeyException(InvalidDataAccessResourceUsageException e){
logger.error(e.getMessage(), e);
return Result.error("演示环境禁止插插插");
}
@ExceptionHandler(Exception.class)
public Result handleException(Exception e){
logger.error(e.getMessage(), e);
return Result.error();
}
/**
* 异常处理参数
*/
@ExceptionHandler(value = {BindException.class})
public Result bindException(BindException e) {
return Result.error(e.getAllErrors().toString());
}
}
package com.tools.common.model;
import java.util.ArrayList;
import java.util.List;
/**
* 分页模板
*
*
*/
public class PageBean<T> {
private List<T> pageData = new ArrayList<>();
private Integer pageSize = Integer.valueOf(10);
private Integer pageNo = Integer.valueOf(1);
private Long totalCount = 0L;
private String description;
public PageBean(List<T> pageData, Long totalCount) {
this.pageData = pageData;
this.totalCount = totalCount;
}
public PageBean() {
}
public List<T> getPageData() {
return this.pageData;
}
public void setPageData(List<T> pageData) {
this.pageData = pageData;
}
public Integer getPageSize() {
return this.pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Long getTotalCount() {
return this.totalCount;
}
public void setTotalCount(Long totalCount) {
this.totalCount = totalCount;
}
public Integer getPageNo() {
return this.pageNo - 1;
}
public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
\ No newline at end of file
package com.tools.common.model;
import java.util.HashMap;
import java.util.Map;
/**
* 页面响应
*
*
*/
public class Result extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public Result() {
put("code", 0);
}
public static Result error() {
return error(-1, "未知异常,请联系管理员");
}
public static Result error(String msg) {
return error(-1, msg);
}
public static Result error(int code, String msg) {
Result r = new Result();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static Result ok(Object msg) {
Result r = new Result();
r.put("msg", msg);
return r;
}
public static Result ok(Map<String, Object> map) {
Result r = new Result();
r.putAll(map);
return r;
}
public static Result ok() {
Result r = new Result();
r.put("msg", "操作成功");
return r;
}
@Override
public Result put(String key, Object value) {
super.put(key, value);
return this;
}
}
\ No newline at end of file
package com.tools.common.redis;
import org.redisson.api.RLock;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
/**
* redis分布式锁
*
*
*/
public class RedissLockUtil {
private static RedissonClient redissonClient;
public void setRedissonClient(RedissonClient locker) {
redissonClient = locker;
}
/**
* 加锁
* @param lockKey
* @return
*/
public static RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
/**
* 释放锁
* @param lockKey
*/
public static void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
/**
* 释放锁
* @param lock
*/
public static void unlock(RLock lock) {
lock.unlock();
}
/**
* 带超时的锁
* @param lockKey
* @param timeout 超时时间 单位:秒
*/
public static RLock lock(String lockKey, int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
/**
* 带超时的锁
* @param lockKey
* @param unit 时间单位
* @param timeout 超时时间
*/
public static RLock lock(String lockKey, TimeUnit unit ,int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
/**
* 尝试获取锁
* @param lockKey
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @return
*/
public static boolean tryLock(String lockKey, int waitTime, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
/**
* 尝试获取锁
* @param lockKey
* @param unit 时间单位
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @return
*/
public static boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
}
/**
* 初始红包数量
* @param key
* @param count
*/
public void initCount(String key,int count) {
RMapCache<String, Integer> mapCache = redissonClient.getMapCache("skill");
mapCache.putIfAbsent(key,count,3,TimeUnit.DAYS);
}
/**
* 递增
* @param key
* @param delta 要增加几(大于0)
* @return
*/
public int incr(String key, int delta) {
RMapCache<String, Integer> mapCache = redissonClient.getMapCache("skill");
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return mapCache.addAndGet(key, 1);//加1并获取计算后的值
}
/**
* 递减
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public int decr(String key, int delta) {
RMapCache<String, Integer> mapCache = redissonClient.getMapCache("skill");
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return mapCache.addAndGet(key, -delta);//加1并获取计算后的值
}
public static RedissonClient getRedissonClient() {
return redissonClient;
}
}
\ No newline at end of file
package com.tools.common.redis;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自动装配
*
*/
@Configuration
@ConditionalOnClass(Config.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {
@Autowired
private RedissonProperties redssionProperties;
/**
* 单机模式自动装配
* @return
*/
@Bean
RedissonClient redissonSingle() {
Config config = new Config();
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress("redis://"+redssionProperties.getHost()+":"+redssionProperties.getPort())
.setTimeout(redssionProperties.getTimeout())
.setConnectionPoolSize(redssionProperties.getConnectionPoolSize())
.setConnectionMinimumIdleSize(redssionProperties.getConnectionMinimumIdleSize());
if(StringUtils.isNotBlank(redssionProperties.getPassword())) {
serverConfig.setPassword(redssionProperties.getPassword());
}
return Redisson.create(config);
}
/**
* 装配locker类,并将实例注入到RedissLockUtil中
* @return
*/
@Bean
RedissLockUtil redissLockUtil(RedissonClient redissonClient) {
RedissLockUtil redissLockUtil = new RedissLockUtil();
redissLockUtil.setRedissonClient(redissonClient);
return redissLockUtil;
}
}
package com.tools.common.redis;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 参数配置
*
*/
@Data
@ConfigurationProperties(prefix = "spring.redis")
public class RedissonProperties {
private int timeout = 3000;
private String host;
private String port;
private String password;
private int connectionPoolSize = 64;
private int connectionMinimumIdleSize=10;
private int slaveConnectionPoolSize = 250;
private int masterConnectionPoolSize = 250;
private String[] sentinelAddresses;
private String masterName;
}
package com.tools.common.util;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期处理
*
*/
public class DateUtils {
/** 时间格式(yyyy-MM-dd) */
public final static String DATE_PATTERN = "yyyy-MM-dd";
/** 时间格式(yyyy-MM-dd HH:mm:ss) */
public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
public static String format(Date date) {
return format(date, DATE_PATTERN);
}
public static String format(Date date, String pattern) {
if (date != null) {
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(date);
}
return null;
}
public static String format(Timestamp date, String pattern) {
if (date != null) {
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(date);
}
return null;
}
public static Date format(String str, String pattern) {
if (str != null) {
SimpleDateFormat df = new SimpleDateFormat(pattern);
try {
return df.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 获取当前日期
*/
public static Timestamp getTimestamp() {
return new Timestamp(System.currentTimeMillis());
}
public static String getTime() {
return format(new Timestamp(System.currentTimeMillis()),DATE_TIME_PATTERN);
}
public static void main(String[] args) {
System.out.println(DateUtils.getTime());
}
}
package com.tools.common.util;
import java.security.MessageDigest;
public class EncriptUtil {
/**
* 十六进制下数字到字符的映射数组
*/
private final static String[] hexDigits = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
/**把inputString加密*/
public static String md5(String inputStr){
return encodeByMD5(inputStr);
}
/**对字符串进行MD5编码*/
private static String encodeByMD5(String originString){
if (originString!=null) {
try {
//创建具有指定算法名称的信息摘要
MessageDigest md5 = MessageDigest.getInstance("MD5");
//使用指定的字节数组对摘要进行最后更新,然后完毕摘要计算
byte[] results = md5.digest(originString.getBytes());
//将得到的字节数组变成字符串返回
String result = byteArrayToHexString(results);
return result;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 轮换字节数组为十六进制字符串
* @param b 字节数组
* @return 十六进制字符串
*/
private static String byteArrayToHexString(byte[] b){
StringBuffer resultSb = new StringBuffer();
for(int i=0;i<b.length;i++){
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
//将一个字节转化成十六进制形式的字符串
private static String byteToHexString(byte b){
int n = b;
if(n<0) {
n=256+n;
}
int d1 = n/16;
int d2 = n%16;
return hexDigits[d1] + hexDigits[d2];
}
}
package com.tools.common.util;
import cn.hutool.core.date.DateUtil;
import com.tools.common.constant.SystemConstant;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
/**
* 文件工具
*
*/
@Component
public class FileUtils {
/**
* 判断文件大小
* @param len 文件长度
* @param size 限制大小
* @param unit 限制单位(B,K,M,G)
* @return
*/
public static boolean checkFileSize(Long len, int size, String unit) {
double fileSize = 0;
if ("B".equalsIgnoreCase(unit)) {
fileSize = (double) len;
} else if ("K".equalsIgnoreCase(unit)) {
fileSize = (double) len / 1024;
} else if ("M".equalsIgnoreCase(unit)) {
fileSize = (double) len / 1048576;
} else if ("G".equalsIgnoreCase(unit)) {
fileSize = (double) len / 1073741824;
}
return !(fileSize > size);
}
/**
* 获取上传文件的MD5值
* @param file
* @return
* @throws IOException
*/
public static String getMd5(MultipartFile file) {
try {
return DigestUtils.md5Hex(file.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
/**
* 创建多级文件夹
* @return
*/
public static File createByDay(String filePath){
File parentFile = new File(filePath+ SystemConstant.SF_FILE_SEPARATOR+ DateUtil.thisYear());
if (!parentFile.exists()) {
parentFile.mkdirs();
}
parentFile = new File(parentFile,(DateUtil.thisMonth()+1)+"");
if (!parentFile.exists()) {
parentFile.mkdirs();
}
parentFile = new File(parentFile,DateUtil.thisDayOfMonth()+"");
if (!parentFile.exists()) {
parentFile.mkdirs();
}
return parentFile;
}
}
package com.tools.common.util;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 由数据库表生成jpa实体工具
* @author 匿名
*/
public class GenEntityMysql {
private static final String URL = "jdbc:mysql://localhost:3306/picture?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC";
private static final String NAME = "root";
private static final String PASS = "123456";
/**
* //指定实体生成所在包的路径
*/
private final String entityPackage = "com.tools.module.app.entity";
/**
* 指定实体仓库接口生成所在包的路径
*/
private final String repositoryPackage = "com.tools.module.app.repository.ftl";
/**
* 作者名字
*/
private final String authorName = "小柒2012";
/**
* 根据表明创建entity实例类,每次一个
*/
private final String tableName = "app_short_url";
/**
* 列名数组
*/
private final List<String> colNames = new ArrayList<>();
/**
* 列名类型数组
*/
private final List<String> colTypes = new ArrayList<>();
/**
* 列名大小数组
*/
private final List<Integer> colSizes = new ArrayList<>();
/**
* 列补充说明
*/
private final List<String> colExtras = new ArrayList<>();
/**
* 列注释
*/
private final List<String> colComment = new ArrayList<>();
private final List<String> colNulls = new ArrayList<>();
/**
* 是否需要导入包java.util.*
*/
private boolean f_util = false;
/**
* 是否需要导入包java.sql.*
*/
private boolean f_sql = false;
/**
* 是否需要导入包java.math.BigDecimal
*/
private boolean f_bigDecimal = false;
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String AUTO = "auto_increment";
private static final String NO = "NO";
/**
* 构造函数
*/
public GenEntityMysql() {
}
/**
* 执行
*/
public static void main(String[] args) {
GenEntityMysql genEntityMysql = new GenEntityMysql();
genEntityMysql.generateEntry();
}
/**
* 功能:生成实体类主体代码
* @return
*/
private String parseEntity() {
StringBuffer sb = new StringBuffer();
sb.append("package " + this.entityPackage + ";\r\n\r\n");
sb.append("import javax.persistence.Entity;" + "\r\n");
sb.append("import javax.persistence.Table;" + "\r\n");
sb.append("import javax.persistence.Column;" + "\r\n");
sb.append("import javax.persistence.Id;" + "\r\n");
sb.append("import javax.persistence.GeneratedValue;" + "\r\n");
sb.append("import javax.persistence.GenerationType;" + "\r\n");
sb.append("import java.io.Serializable;" + "\r\n");
//判断是否导入工具包
if (f_util) {
sb.append("import java.sql.Timestamp;\r\n");
}
if (f_sql) {
sb.append("import java.sql.*;\r\n");
}
if (f_bigDecimal) {
sb.append("import java.math.BigDecimal;\r\n");
}
sb.append("\r\n");
//注释部分
sb.append("/**\r\n");
sb.append(" * " + tableName + " 实体类\r\n");
sb.append(" * Created by " + this.authorName + "\r\n");
sb.append(" * " + new Date() + "\r\n");
sb.append(" */ \r\n");
//实体部分
sb.append("@Entity " + "\r\n");
sb.append("@Table(name = \"" + tableName + "\")" + "\r\n");
sb.append("public class " + this.allInitialCapital(tableName) + " implements Serializable{\r\n");
processAllAttrs(sb);//属性
processAllMethod(sb);//get set方法
sb.append("}\r\n");
return sb.toString();
}
/**
* 功能:生成repository代码
*
* @return
*/
private String parseRepository() {
String sb = "package " + this.repositoryPackage + ";\r\n\r\n" +
"import org.springframework.data.jpa.repository.ftl.JpaRepository;" + "\r\n" +
"import org.springframework.stereotype.Repository;" + "\r\n" +
"import " + this.entityPackage + "." + this.allInitialCapital(tableName) + ";" + "\r\n" +
"\r\n" +
//注释部分
"/**\r\n" +
" * " + tableName + " Repository\r\n" +
" * Created by " + this.authorName + "\r\n" +
" * " + new Date() + "\r\n" +
"*/ \r\n" +
//实体部分
"@Repository " + "\r\n" +
"public interface " + this.allInitialCapital(tableName) + "Repository extends JpaRepository<" + this.allInitialCapital(tableName) + ", Integer> {\r\n" +
"}\r\n";
return sb;
}
/**
* 功能:生成所有属性
*
* @param sb
*/
private void processAllAttrs(StringBuffer sb) {
for (int i = 0; i < colNames.size(); i++) {
//注释部分
sb.append(" /**\r\n");
sb.append(" * " + colComment.get(i) + " \r\n");
sb.append(" */ \r\n");
if (AUTO.equalsIgnoreCase(colExtras.get(i))) {
sb.append("\t@Id" + "\r\n");
sb.append("\t@GeneratedValue(strategy = GenerationType.IDENTITY)" + "\r\n");
}
sb.append("\t@Column(name = \"" + colNames.get(i) + "\"");
if (NO.equalsIgnoreCase(colNulls.get(i))) {
sb.append(", nullable = false");
}
if (colSizes.get(i) > 0) {
sb.append(", length = " + colSizes.get(i));
}
sb.append(")" + "\r\n");
sb.append("\tprivate " + sqlType2JavaType(colTypes.get(i)) + " " + this.secInitialCapital(colNames.get(i)) + ";\r\n\r\n");
}
}
/**
* 功能:生成所有方法
*
* @param sb
*/
private void processAllMethod(StringBuffer sb) {
for (int i = 0; i < colNames.size(); i++) {
sb.append("\tpublic " + sqlType2JavaType(colTypes.get(i)) + " get" + this.allInitialCapital(colNames.get(i)) + "(){\r\n");
sb.append("\t\treturn " + this.secInitialCapital(colNames.get(i)) + ";\r\n");
sb.append("\t}\r\n");
sb.append("\tpublic void set" + this.allInitialCapital(colNames.get(i)) + "(" + sqlType2JavaType(colTypes.get(i)) + " " +
this.secInitialCapital(colNames.get(i)) + "){\r\n");
sb.append("\tthis." + this.secInitialCapital(colNames.get(i)) + "=" + this.secInitialCapital(colNames.get(i)) + ";\r\n");
sb.append("\t}\r\n");
}
}
/**
* 功能:将输入字符串的首字母改成大写
*
* @param str
* @return
*/
private String initialCapital(String str) {
char[] ch = str.toCharArray();
if (ch[0] >= 'a' && ch[0] <= 'z') {
ch[0] = (char) (ch[0] - 32);
}
return new String(ch);
}
/**
* 所有字母转成小写
*
* @return
*/
private String allLowerCase(String str) {
if (StringUtils.isEmpty(str)) {
return str;
}
return str.toLowerCase();
}
/**
* 分解名称
*
* @param str
* @return
*/
private String[] splitName(String str) {
if (StringUtils.isEmpty(str)) {
return null;
}
return str.split("_");
}
/**
* 由数据库表名生成实体类名
*
* @param tableName
* @return
*/
private String allInitialCapital(String tableName) {
if (StringUtils.isEmpty(tableName)) {
return null;
}
tableName = this.allLowerCase(tableName);
String[] tableNameArray = this.splitName(tableName);
StringBuffer entryName = new StringBuffer();
for (String part : tableNameArray) {
entryName.append(this.initialCapital(part));
}
return entryName.toString();
}
/**
* 由数据库列名生成实体类属性名
*
* @param columnName
* @return
*/
private String secInitialCapital(String columnName) {
if (StringUtils.isEmpty(columnName)) {
return null;
}
columnName = this.allLowerCase(columnName);
String[] columnNameArray = this.splitName(columnName);
StringBuffer fieldName = new StringBuffer();
for (int i = 0; i < columnNameArray.length; i++) {
String part = columnNameArray[i];
if (0 == i) {
fieldName.append(part);
} else {
fieldName.append(this.initialCapital(part));
}
}
return fieldName.toString();
}
/**
* 功能:获得列的数据类型
*
* @param sqlType
* @return
*/
private String sqlType2JavaType(String sqlType) {
if (sqlType.equalsIgnoreCase("bit")) {
return "Boolean";
} else if (sqlType.equalsIgnoreCase("tinyint")) {
return "Short";
} else if (sqlType.equalsIgnoreCase("smallint")) {
return "Short";
} else if (sqlType.equalsIgnoreCase("int")) {
return "Integer";
} else if (sqlType.equalsIgnoreCase("bigint")) {
return "Long";
} else if (sqlType.equalsIgnoreCase("float")) {
return "Float";
} else if (sqlType.equalsIgnoreCase("decimal")) {
return "BigDecimal";
} else if (sqlType.equalsIgnoreCase("numeric")
|| sqlType.equalsIgnoreCase("real") || sqlType.equalsIgnoreCase("money")
|| sqlType.equalsIgnoreCase("smallmoney")) {
return "Double";
} else if (sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char")
|| sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nchar")
|| sqlType.equalsIgnoreCase("text")) {
return "String";
} else if (sqlType.equalsIgnoreCase("datetime")) {
return "Date";
}else if (sqlType.equalsIgnoreCase("timestamp")) {
return "Timestamp";
} else if (sqlType.equalsIgnoreCase("image")) {
return "Blod";
}
return null;
}
/**
* 生成实体
*/
public void generateEntry() {
//
this.getTableAttribute();
String entityContent = this.parseEntity();
this.writerEntityToFile(entityContent);
String repositoryContent = this.parseRepository();
this.writerRepositoryToFile(repositoryContent);
}
/**
* 写入文件
*
* @param content
*/
private void writerRepositoryToFile(String content) {
try {
String absolutePath = this.getClass().getResource("").getPath();
absolutePath = absolutePath.substring(0, absolutePath.indexOf("target"));
String outputPath = absolutePath + "src/main/java/" + this.repositoryPackage.replace(".", "/") + "/"
+ this.allInitialCapital(tableName) + "Repository" + ".java";
File file = new File(outputPath);
if(file.exists()){
file.delete();
}
System.out.println("Repository路径:" + outputPath);
FileWriter fw = new FileWriter(outputPath);
PrintWriter pw = new PrintWriter(fw);
pw.println(content);
pw.flush();
pw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 写入文件
*
* @param content
*/
private void writerEntityToFile(String content) {
try {
String absolutePath = this.getClass().getResource("").getPath();
absolutePath = absolutePath.substring(0, absolutePath.indexOf("target"));
String outputPath = absolutePath + "src/main/java/" + this.entityPackage.replace(".", "/") + "/"
+ allInitialCapital(tableName) + ".java";
System.out.println("Entity路径:" + outputPath);
FileWriter fw = new FileWriter(outputPath);
PrintWriter pw = new PrintWriter(fw);
pw.println(content);
pw.flush();
pw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取数据库信息
*/
private void getTableAttribute() {
//创建连接
Connection con = null;
//查要生成实体类的表
String sql = "show full columns from " + tableName;
Statement state = null;
try {
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
con = DriverManager.getConnection(URL, NAME, PASS);
state = con.createStatement();
ResultSet rs = state.executeQuery(sql);
// ResultSetMetaData metaData = rs.getMetaData();
while (rs.next()) {
colNames.add(rs.getString("Field"));
String type = rs.getString("Type");
String comment = rs.getString("Comment");
String extra = rs.getString("Extra");
String colNull = rs.getString("Null");
int colSize = 0;
if (type.contains("(")) {
String colSizeStr = type.substring(type.indexOf("(") + 1, type.indexOf(")"));
type = type.substring(0, type.indexOf("("));
try {
colSize = Integer.valueOf(colSizeStr);
} catch (NumberFormatException e) {
}
}
colTypes.add(type);
colSizes.add(colSize);
colComment.add(comment);
colExtras.add(extra);
colNulls.add(colNull);
if (type.equalsIgnoreCase("datetime")||type.equalsIgnoreCase("timestamp")) {
f_util = true;
}
if (type.equalsIgnoreCase("image") || type.equalsIgnoreCase("text")) {
f_sql = true;
}
if (type.equalsIgnoreCase("decimal")) {
f_bigDecimal = true;
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != con) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
\ No newline at end of file
package com.tools.common.util;
/**
* 代码生成工具类
*
*/
public class GenUtils {
/**
* 由数据库表名生成实体类名
* @param tableName
* @return
*/
public static String allInitialCapital(String tableName) {
if (org.springframework.util.StringUtils.isEmpty(tableName)) {
return null;
}
tableName = allLowerCase(tableName);
String[] tableNameArray = splitName(tableName);
StringBuffer entryName = new StringBuffer();
for (String part : tableNameArray) {
entryName.append(initialCapital(part));
}
return entryName.toString();
}
/**
* 由数据库列名生成实体类属性名
* @param columnName
* @return
*/
public static String secInitialCapital(String columnName) {
if (org.springframework.util.StringUtils.isEmpty(columnName)) {
return null;
}
columnName = allLowerCase(columnName);
String[] columnNameArray = splitName(columnName);
StringBuffer fieldName = new StringBuffer();
for (int i = 0; i < columnNameArray.length; i++) {
String part = columnNameArray[i];
if (0 == i) {
fieldName.append(part);
} else {
fieldName.append(initialCapital(part));
}
}
return fieldName.toString();
}
/**
* 所有字母转成小写
* @return
*/
public static String allLowerCase(String str) {
if (org.springframework.util.StringUtils.isEmpty(str)) {
return str;
}
return str.toLowerCase();
}
/**
* 功能:将输入字符串的首字母改成大写
* @param str
* @return
*/
public static String initialCapital(String str) {
char[] ch = str.toCharArray();
if (ch[0] >= 'a' && ch[0] <= 'z') {
ch[0] = (char) (ch[0] - 32);
}
return new String(ch);
}
/**
* 分解名称
* @param str
* @return
*/
public static String[] splitName(String str) {
if (org.springframework.util.StringUtils.isEmpty(str)) {
return null;
}
return str.split("_");
}
/**
* 首字母转小写
* @param s
* @return
*/
public static String toLowerCaseFirstOne(String s){
if(Character.isLowerCase(s.charAt(0))){
return s;
} else{
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}
}
}
\ No newline at end of file
package com.tools.common.util;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@Service
public class HttpClient {
/**
* 校验网址正确性
* @param url
* @return
*/
public static Integer client(String url){
try{
HttpHeaders headers = new HttpHeaders();
headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
HttpEntity<Resource> httpEntity = new HttpEntity<>(headers);
RestTemplate client = new RestTemplate();
ResponseEntity<String> response = client.exchange(url, HttpMethod.GET, httpEntity , String.class);
return response.getStatusCode().value();
}catch (Exception e){
e.printStackTrace();
}
return 0;
}
}
package com.tools.common.util;
import org.springframework.util.StringUtils;
import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Map.Entry;
/**
* http、https 请求工具类
*
* @author jiaxiaoxian
*/
public class HttpUtils {
private static final String DEFAULT_CHARSET = "UTF-8";
private static final String _GET = "GET"; // GET
private static final String _POST = "POST";// POST
public static final int DEF_CONN_TIMEOUT = 30000;
public static final int DEF_READ_TIMEOUT = 30000;
/**
* 初始化http请求参数
*
* @param url
* @param method
* @param headers
* @return
* @throws Exception
*/
private static HttpURLConnection initHttp(String url, String method,
Map<String, String> headers) throws Exception {
URL _url = new URL(url);
HttpURLConnection http = (HttpURLConnection) _url.openConnection();
// 连接超时
http.setConnectTimeout(DEF_CONN_TIMEOUT);
// 读取超时 --服务器响应比较慢,增大时间
http.setReadTimeout(DEF_READ_TIMEOUT);
http.setUseCaches(false);
http.setRequestMethod(method);
http.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
http.setRequestProperty(
"User-Agent",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
if (null != headers && !headers.isEmpty()) {
for (Entry<String, String> entry : headers.entrySet()) {
http.setRequestProperty(entry.getKey(), entry.getValue());
}
}
http.setDoOutput(true);
http.setDoInput(true);
http.connect();
return http;
}
/**
* 初始化http请求参数
*
* @param url
* @param method
* @return
* @throws Exception
*/
private static HttpsURLConnection initHttps(String url, String method,
Map<String, String> headers) throws Exception {
TrustManager[] tm = {new MyX509TrustManager()};
System.setProperty("https.protocols", "TLSv1");
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL _url = new URL(url);
HttpsURLConnection http = (HttpsURLConnection) _url.openConnection();
// 设置域名校验
http.setHostnameVerifier(new HttpUtils().new TrustAnyHostnameVerifier());
// 连接超时
http.setConnectTimeout(DEF_CONN_TIMEOUT);
// 读取超时 --服务器响应比较慢,增大时间
http.setReadTimeout(DEF_READ_TIMEOUT);
http.setUseCaches(false);
http.setRequestMethod(method);
http.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
http.setRequestProperty(
"User-Agent",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
if (null != headers && !headers.isEmpty()) {
for (Entry<String, String> entry : headers.entrySet()) {
http.setRequestProperty(entry.getKey(), entry.getValue());
}
}
http.setSSLSocketFactory(ssf);
http.setDoOutput(true);
http.setDoInput(true);
http.connect();
return http;
}
/**
* @return 返回类型:
* @throws Exception
* @description 功能描述: get 请求
*/
public static String get(String url, Map<String, String> params,
Map<String, String> headers) throws Exception {
HttpURLConnection http = null;
if (isHttps(url)) {
http = initHttps(initParams(url, params), _GET, headers);
} else {
http = initHttp(initParams(url, params), _GET, headers);
}
InputStream in = http.getInputStream();
BufferedReader read = new BufferedReader(new InputStreamReader(in,
DEFAULT_CHARSET));
String valueString = null;
StringBuffer bufferRes = new StringBuffer();
// 优化,不能光使用!=null做判断。有为""的情况,防止多次空循环
while (!StringUtils.isEmpty(valueString = read.readLine())) {
bufferRes.append(valueString);
}
in.close();
if (http != null) {
http.disconnect();// 关闭连接
}
return bufferRes.toString();
}
public static String get(String url) throws Exception {
return get(url, null);
}
public static String get(String url, Map<String, String> params)
throws Exception {
return get(url, params, null);
}
public static String post(String url, String params) throws Exception {
HttpURLConnection http = null;
if (isHttps(url)) {
http = initHttps(url, _POST, null);
} else {
http = initHttp(url, _POST, null);
}
OutputStream out = http.getOutputStream();
out.write(params.getBytes(DEFAULT_CHARSET));
out.flush();
out.close();
InputStream in = http.getInputStream();
BufferedReader read = new BufferedReader(new InputStreamReader(in,
DEFAULT_CHARSET));
String valueString = null;
StringBuffer bufferRes = new StringBuffer();
while ((valueString = read.readLine()) != null) {
bufferRes.append(valueString);
}
in.close();
if (http != null) {
http.disconnect();// 关闭连接
}
return bufferRes.toString();
}
public static String post(String url, String params, Map<String, String> headers) throws Exception {
HttpURLConnection http = null;
if (isHttps(url)) {
http = initHttps(url, _POST, headers);
} else {
http = initHttp(url, _POST, headers);
}
OutputStream out = http.getOutputStream();
out.write(params.getBytes(DEFAULT_CHARSET));
out.flush();
out.close();
InputStream in = http.getInputStream();
BufferedReader read = new BufferedReader(new InputStreamReader(in,
DEFAULT_CHARSET));
String valueString = null;
StringBuffer bufferRes = new StringBuffer();
while ((valueString = read.readLine()) != null) {
bufferRes.append(valueString);
}
in.close();
if (http != null) {
http.disconnect();// 关闭连接
}
return bufferRes.toString();
}
/**
* 功能描述: 构造请求参数
*
* @return 返回类型:
* @throws Exception
*/
public static String initParams(String url, Map<String, String> params)
throws Exception {
if (null == params || params.isEmpty()) {
return url;
}
StringBuilder sb = new StringBuilder(url);
if (url.indexOf("?") == -1) {
sb.append("?");
}
sb.append(map2Url(params));
return sb.toString();
}
/**
* map构造url
*
* @return 返回类型:
* @throws Exception
*/
public static String map2Url(Map<String, String> paramToMap)
throws Exception {
if (null == paramToMap || paramToMap.isEmpty()) {
return null;
}
StringBuffer url = new StringBuffer();
boolean isfist = true;
for (Entry<String, String> entry : paramToMap.entrySet()) {
if (isfist) {
isfist = false;
} else {
url.append("&");
}
url.append(entry.getKey()).append("=");
String value = entry.getValue();
if (!StringUtils.isEmpty(value)) {
url.append(URLEncoder.encode(value, DEFAULT_CHARSET));
}
}
return url.toString();
}
/**
* 检测是否https
*
* @param url
*/
private static boolean isHttps(String url) {
return url.startsWith("https");
}
/**
* https 域名校验
* @return
*/
public class TrustAnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;// 直接返回true
}
}
private static class MyX509TrustManager implements X509TrustManager {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
}
public static void main(String[] args) {
String str = "";
try {
str = get("https://www.baidu.com");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(str);
}
}
\ No newline at end of file
package com.tools.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* IP地址
*
*/
public class IPUtils {
private static final Logger logger = LoggerFactory.getLogger(IPUtils.class);
/**
* 获取IP地址
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public static String getIpAddr() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
// 使用代理,则获取第一个IP地址
if (!StringUtils.isEmpty(ip) && ip.length() > 15) {
if (ip.indexOf(",") > 0) {
ip = ip.substring(0, ip.indexOf(","));
}
}
return ip;
}
}
\ No newline at end of file
package com.tools.common.util;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 图片处理
*
*/
@Component
public class ImageUtils {
@Value("${file.path}")
private String filePath;
private static File watermark;
static {
try {
watermark = ResourceUtils.getFile("classpath:static/images/watermark.png");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 原图片地址
String imageUrl = "F:\\111.gif";
// 水印图片 相对于resource目录
String watermark = "F:\\watermark.png";
// 输出到文件
String outputFile = "F:\\222.gif";
// 不透明度
float opacity = 0.7f;
try {
// 获取原图文件
File file = new File(imageUrl);
// ImageIO读取图片
BufferedImage image = ImageIO.read(file);
System.out.println(image.getWidth());
Thumbnails.of(image)
// 设置图片大小
.size(image.getWidth(), image.getHeight())
// 加水印 参数:1.水印位置 2.水印图片 3.不透明度0.0-1.0
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(watermark)), opacity)
// 输出到文件
.outputQuality(1)
.toFile(outputFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.tools.common.util;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
/**
*/
public class PasswordEncoder {
private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
"e", "f" };
private final static String MD5 = "MD5";
private final static String SHA = "SHA";
private final Object salt;
private final String algorithm;
public PasswordEncoder(Object salt) {
this(salt, MD5);
}
public PasswordEncoder(Object salt, String algorithm) {
this.salt = salt;
this.algorithm = algorithm;
}
/**
* 密码加密
* @param rawPass
* @return
*/
public String encode(String rawPass) {
String result = null;
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
// 加密后的字符串
result = byteArrayToHexString(md.digest(mergePasswordAndSalt(rawPass).getBytes(StandardCharsets.UTF_8)));
} catch (Exception ex) {
}
return result;
}
/**
* 密码匹配验证
* @param encPass 密文
* @param rawPass 明文
* @return
*/
public boolean matches(String encPass, String rawPass) {
String pass1 = encPass;
String pass2 = encode(rawPass);
return pass1.equals(pass2);
}
private String mergePasswordAndSalt(String password) {
if (password == null) {
password = "";
}
if ((salt == null) || "".equals(salt)) {
return password;
} else {
return password + "{" + salt + "}";
}
}
/**
* 转换字节数组为16进制字串
*
* @param b
* 字节数组
* @return 16进制字串
*/
private String byteArrayToHexString(byte[] b) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
/**
* 将字节转换为16进制
* @param b
* @return
*/
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n = 256 + n;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static void main(String[] args) {
}
}
package com.tools.common.util;
import org.springframework.beans.factory.annotation.Value;
import java.util.UUID;
/**
*/
public class PasswordUtils {
@Value("${pwd.decrypt.key}")
public String key;
@Value("${pwd.decrypt.iv}")
private String iv;
/**
* 匹配密码
* @param salt 盐
* @param rawPass 明文
* @param encPass 密文
* @return
*/
public static boolean matches(String salt, String rawPass, String encPass) {
return new PasswordEncoder(salt).matches(encPass, rawPass);
}
/**
* 明文密码加密
* @param rawPass 明文
* @param salt
* @return
*/
public static String encode(String rawPass, String salt) {
return new PasswordEncoder(salt).encode(rawPass);
}
/**
* 获取加密盐
* @return
*/
public static String getSalt() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 20);
}
}
package com.tools.common.util;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* @Author:Roger Wu
* @name:pwdUtils
* @Date:2025-06-10 0:27
*/
@Component
public class PwdUtils {
@Value("${pwd.decrypt.key}")
public String key;
@Value("${pwd.decrypt.iv}")
private String iv;
// 后端使用AES算法对密码进行解密
public String decryptPassword(String encryptedPassword) {
Assert.notNull(key);
Assert.notNull(iv);
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] original = cipher.doFinal(Base64.getDecoder().decode(encryptedPassword));
return new String(original);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// public static void main(String[] args) {
// System.out.println(decryptPassword("QPpW6DeIaufxGD4+HLcArg=="));
// }
}
package com.tools.common.util;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* redisTemplate封装
*
*/
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public static String PREFIX = "cloud:bed:";
/**
* 指定缓存失效时间
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key,long time){
try {
if(time>0){
redisTemplate.expire(PREFIX+key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key){
return redisTemplate.getExpire(PREFIX+key,TimeUnit.SECONDS);
}
/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key){
try {
return redisTemplate.hasKey(PREFIX+key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String ... key){
if(key!=null&&key.length>0){
if(key.length==1){
redisTemplate.delete(PREFIX+key[0]);
}else{
redisTemplate.delete(CollectionUtils.arrayToList(PREFIX+key));
}
}
}
/**
* 普通缓存获取
* @param key 键
* @return 值
*/
public Object get(String key){
return PREFIX+key==null?null:redisTemplate.opsForValue().get(PREFIX+key);
}
/**
* 普通缓存放入
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key,Object value) {
try {
redisTemplate.opsForValue().set(PREFIX+key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key,Object value,long time){
try {
if(time>0){
redisTemplate.opsForValue().set(PREFIX+key, value, time, TimeUnit.SECONDS);
}else{
set(PREFIX+key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta){
if(delta<0){
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(PREFIX+key, delta);
}
/**
* 递减
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta){
if(delta<0){
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(PREFIX+key, -delta);
}
/**
* HashGet
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key,String item){
return redisTemplate.opsForHash().get(PREFIX+key, item);
}
/**
* 获取hashKey对应的所有键值
* @param key 键
* @return 对应的多个键值
*/
public Map<Object,Object> hmget(String key){
return redisTemplate.opsForHash().entries(PREFIX+key);
}
/**
* HashSet
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String,Object> map){
try {
redisTemplate.opsForHash().putAll(PREFIX+key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String,Object> map, long time){
try {
redisTemplate.opsForHash().putAll(PREFIX+key, map);
if(time>0){
expire(PREFIX+key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key,String item,Object value) {
try {
redisTemplate.opsForHash().put(PREFIX+key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key,String item,Object value,long time) {
try {
redisTemplate.opsForHash().put(PREFIX+key, item, value);
if(time>0){
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item){
redisTemplate.opsForHash().delete(PREFIX+key,item);
}
/**
* 判断hash表中是否有该项的值
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item){
return redisTemplate.opsForHash().hasKey(PREFIX+key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public double hincr(String key, String item,double by){
return redisTemplate.opsForHash().increment(PREFIX+key, item, by);
}
/**
* hash递减
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item,double by){
return redisTemplate.opsForHash().increment(PREFIX+key, item,-by);
}
/**
* 根据key获取Set中的所有值
* @param key 键
* @return
*/
public Set<Object> sGet(String key){
try {
return redisTemplate.opsForSet().members(PREFIX+key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key,Object value){
try {
return redisTemplate.opsForSet().isMember(PREFIX+key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object...values) {
try {
return redisTemplate.opsForSet().add(PREFIX+key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key,long time,Object...values) {
try {
Long count = redisTemplate.opsForSet().add(PREFIX+key, values);
if(time>0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
* @param key 键
* @return
*/
public long sGetSetSize(String key){
try {
return redisTemplate.opsForSet().size(PREFIX+key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object ...values) {
try {
Long count = redisTemplate.opsForSet().remove(PREFIX+key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============================list=================================
/**
* 获取list缓存的内容
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end){
try {
return redisTemplate.opsForList().range(PREFIX+key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
* @param key 键
* @return
*/
public long lGetListSize(String key){
try {
return redisTemplate.opsForList().size(PREFIX+key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object lGetIndex(String key,long index){
try {
return redisTemplate.opsForList().index(PREFIX+key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(PREFIX+key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(PREFIX+key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(PREFIX+key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(PREFIX+key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index,Object value) {
try {
redisTemplate.opsForList().set(PREFIX+key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key,long count,Object value) {
try {
Long remove = redisTemplate.opsForList().remove(PREFIX+key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 模糊查询获取key值
* @param pattern
* @return
*/
public Set keys(String pattern){
return redisTemplate.keys(pattern);
}
/**
* 使用Redis的消息队列
* @param channel
* @param message 消息内容
*/
public void convertAndSend(String channel, Object message){
redisTemplate.convertAndSend(channel,message);
}
/**
*将数据添加到Redis的list中(从右边添加)
* @param listKey
* @param time 有效期
* @param values 待添加的数据
*/
public void addToListRight(String listKey, long time, TimeUnit timeUnit, Object... values) {
//绑定操作
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
//插入数据
boundValueOperations.rightPushAll(values);
//设置过期时间
boundValueOperations.expire(time,timeUnit);
}
/**
* 根据起始结束序号遍历Redis中的list
* @param listKey
* @param start 起始序号
* @param end 结束序号
* @return
*/
public List<Object> rangeList(String listKey, long start, long end) {
//绑定操作
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
//查询数据
return boundValueOperations.range(start, end);
}
/**
* 弹出右边的值 --- 并且移除这个值
* @param listKey
*/
public Object rifhtPop(String listKey){
//绑定操作
BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
return boundValueOperations.rightPop();
}
public static void main(String[] args) throws IOException {
String fromPic = "D:\\1239d1b727874bf09f3127d2ed498f0e.png";
File file = new File(fromPic);
File toPic = new File("D:\\1239d1b727874bf09f3127d2ed498f0e_1.png");
Thumbnails.of(file).scale(0.5f).outputQuality(1f).toFile(toPic);
}
}
package com.tools.common.util;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* 工具类
*
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor {
/**
* Spring应用上下文环境
*/
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T) beanFactory.getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException {
@SuppressWarnings("unchecked")
T result = beanFactory.getBean(clz);
return result;
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name) {
return beanFactory.containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
* 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return beanFactory.isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名,则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return beanFactory.getAliases(name);
}
}
package com.tools.common.util;
import org.springframework.stereotype.Component;
/**
* 1)将长网址用md5算法生成32位签名串,分为4段,,每段8个字符;
*
* 2)对这4段循环处理,取每段的8个字符, 将他看成16进制字符串与0x3fffffff(30位1)的位与操作。超过30位的忽略处理。
*
* 3)将每段得到的这30位又分成6段,每5位的数字作为字母表的索引取得特定字符,依次进行获得6位字符串;
*
* 4)这样一个md5字符串能够获得4个6位串。取里面的随意一个就可作为这个长url的短url地址。
*/
@Component
public class TinyUrlUtil {
public String[] ShortText(String string){
String key = "qwe20190909";//自己定义生成MD5加密字符串前的混合KEY
String[] chars = new String[]{//要使用生成URL的字符
"a","b","c","d","e","f","g","h",
"i","j","k","l","m","n","o","p",
"q","r","s","t","u","v","w","x",
"y","z","0","1","2","3","4","5",
"6","7","8","9","A","B","C","D",
"E","F","G","H","I","J","K","L",
"M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z"
};
String hex = EncriptUtil.md5(key + string);
int hexLen = hex.length();
int subHexLen = hexLen / 8;
String[] ShortStr = new String[4];
for (int i = 0; i < subHexLen; i++) {
String outChars = "";
int j = i + 1;
String subHex = hex.substring(i * 8, j * 8);
long idx = Long.valueOf("3FFFFFFF", 16) & Long.valueOf(subHex, 16);
for (int k = 0; k < 6; k++) {
int index = (int) (Long.valueOf("0000003D", 16) & idx);
outChars += chars[index];
idx = idx >> 5;
}
ShortStr[i] = outChars;
}
return ShortStr;
}
}
package com.tools.module.business.constants;
/**
* @Author:Roger Wu
* @name:SysUserConstants
* @Date:2025-06-09 22:32
*/
public interface SysCityConstants {
interface Status {
/**
* 正常
*/
String NORMAL ="NORMAL";
/**
* 禁用
*/
String DISABLED ="DISABLED";
}
}
package com.tools.module.business.constants;
/**
* @Author:Roger Wu
* @name:SysUserConstants
* @Date:2025-06-09 22:32
*/
public interface SysUserConstants {
interface Status {
/**
* 正常
*/
String NORMAL ="NORMAL";
/**
* 禁用
*/
String DISABLED ="DISABLED";
}
}
package com.tools.module.business.controller;
import com.tools.common.config.AbstractController;
import com.tools.common.model.Result;
import com.tools.module.business.convert.SysCityConvert;
import com.tools.module.business.dto.CityDto;
import com.tools.module.business.entity.SysCityEntity;
import com.tools.module.business.service.SysCityService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "城市管理")
@RestController
@RequestMapping("/cityRest")
public class CityController extends AbstractController {
@Autowired
private SysCityService sysCityService;
@PostMapping("/createCity")
public Result createCity(@RequestBody CityDto cityDto) throws Exception {
SysCityEntity sysCityEntity = SysCityConvert.convertDto2Entity(cityDto);
return sysCityService.save(sysCityEntity);
}
@PostMapping("/updateCity")
public Result updateCity(@RequestBody CityDto cityDto) throws Exception {
SysCityEntity sysCityEntity = SysCityConvert.convertDto2Entity(cityDto);
return sysCityService.update(sysCityEntity);
}
@PostMapping("/list")
public Result list(@RequestBody CityDto cityDto) throws Exception {
SysCityEntity sysCityEntity = SysCityConvert.convertDto2Entity(cityDto);
Pageable pageable = PageRequest.of(cityDto.getPageNo(), cityDto.getPageSize());
return sysCityService.list(sysCityEntity, pageable);
}
@PostMapping("/delete")
public Result delete(Long cityId) throws Exception {
return sysCityService.delete(cityId);
}
}
package com.tools.module.business.convert;
import com.tools.module.business.dto.CityDto;
import com.tools.module.business.entity.SysCityEntity;
import com.tools.module.business.model.SysCityModel;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author:Roger Wu
* @name:SysCityConvert
* @Date:2025-06-12 0:13
*/
public class SysCityConvert {
public static SysCityModel convertEntity2Model(SysCityEntity sysCityEntity) {
SysCityModel sysCityModel = new SysCityModel();
sysCityModel.setCityId(sysCityEntity.getCityId());
sysCityModel.setCityName(sysCityEntity.getCityName());
sysCityModel.setCityShortName(sysCityEntity.getCityShortName());
sysCityModel.setCityStatus(sysCityEntity.getCityStatus());
sysCityModel.setCityRemark(sysCityEntity.getCityRemark());
sysCityModel.setCityTop(sysCityEntity.getCityTop());
sysCityModel.setCityTopTime(sysCityEntity.getCityTopTime());
sysCityModel.setIsDeleted(sysCityEntity.getIsDeleted());
sysCityModel.setCreatedBy(sysCityEntity.getCreatedBy());
sysCityModel.setCreatedTime(sysCityEntity.getCreatedTime());
sysCityModel.setUpdatedBy(sysCityEntity.getUpdatedBy());
sysCityModel.setUpdatedTime(sysCityEntity.getUpdatedTime());
sysCityModel.setVersion(sysCityEntity.getVersion());
return sysCityModel;
}
public static SysCityEntity convertModel2Entity(SysCityModel sysCityModel) {
SysCityEntity sysCityEntity = new SysCityEntity();
sysCityEntity.setCityId(sysCityModel.getCityId());
sysCityEntity.setCityName(sysCityModel.getCityName());
sysCityEntity.setCityShortName(sysCityModel.getCityShortName());
sysCityEntity.setCityStatus(sysCityModel.getCityStatus());
sysCityEntity.setCityRemark(sysCityModel.getCityRemark());
sysCityEntity.setCityTop(sysCityModel.getCityTop());
sysCityEntity.setCityTopTime(sysCityModel.getCityTopTime());
sysCityEntity.setIsDeleted(sysCityModel.getIsDeleted());
sysCityEntity.setCreatedBy(sysCityModel.getCreatedBy());
sysCityEntity.setCreatedTime(sysCityModel.getCreatedTime());
sysCityEntity.setUpdatedBy(sysCityModel.getUpdatedBy());
sysCityEntity.setUpdatedTime(sysCityModel.getUpdatedTime());
sysCityEntity.setVersion(sysCityModel.getVersion());
return sysCityEntity;
}
public static CityDto convertEntity2Dto(SysCityEntity sysCityEntity) {
CityDto cityDto = new CityDto();
cityDto.setCityId(sysCityEntity.getCityId());
cityDto.setCityName(sysCityEntity.getCityName());
cityDto.setCityShortName(sysCityEntity.getCityShortName());
cityDto.setCityStatus(sysCityEntity.getCityStatus());
cityDto.setCityRemark(sysCityEntity.getCityRemark());
cityDto.setCityTop(sysCityEntity.getCityTop());
cityDto.setCityTopTime(sysCityEntity.getCityTopTime());
cityDto.setCreatedBy(sysCityEntity.getCreatedBy());
cityDto.setCreatedTime(sysCityEntity.getCreatedTime());
cityDto.setUpdatedBy(sysCityEntity.getUpdatedBy());
cityDto.setUpdatedTime(sysCityEntity.getUpdatedTime());
return cityDto;
}
public static SysCityEntity convertDto2Entity(CityDto cityDto) {
SysCityEntity sysCityEntity = new SysCityEntity();
sysCityEntity.setCityId(cityDto.getCityId());
sysCityEntity.setCityName(cityDto.getCityName());
sysCityEntity.setCityShortName(cityDto.getCityShortName());
sysCityEntity.setCityStatus(cityDto.getCityStatus());
sysCityEntity.setCityRemark(cityDto.getCityRemark());
sysCityEntity.setCityTop(cityDto.getCityTop());
sysCityEntity.setCityTopTime(cityDto.getCityTopTime());
sysCityEntity.setCreatedBy(cityDto.getCreatedBy());
sysCityEntity.setCreatedTime(cityDto.getCreatedTime());
sysCityEntity.setUpdatedBy(cityDto.getUpdatedBy());
sysCityEntity.setUpdatedTime(cityDto.getUpdatedTime());
return sysCityEntity;
}
public static Page<SysCityEntity> convertPageModel2Entity(Page<SysCityModel> sysCityModelPage) {
Pageable pageable = sysCityModelPage.getPageable();
List<SysCityEntity> sysCityEntityList = sysCityModelPage.get().map(item -> convertModel2Entity(item)).collect(Collectors.toList());
return new PageImpl(sysCityEntityList, pageable, sysCityModelPage.getTotalPages());
}
}
\ No newline at end of file
package com.tools.module.business.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.tools.common.model.PageBean;
import lombok.Data;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.util.Date;
@Data
@MappedSuperclass
public abstract class BaseDto extends PageBean implements Serializable {
private static final long serialVersionUID = 1L;
@JsonIgnore
private Long createdBy;
@JsonIgnore
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createdTime;
@JsonIgnore
private Long updatedBy;
@JsonIgnore
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updatedTime;
}
\ No newline at end of file
package com.tools.module.business.dto;
import lombok.Data;
import java.util.Date;
/**
* @Author:Roger Wu
* @name:dto
* @Date:2025-06-11 23:36
*/
@Data
public class CityDto extends BaseDto {
private Long cityId;
private String cityName;
private String cityShortName;
private String cityStatus;
private String cityRemark;
private String cityTop;
private Date cityTopTime;
public Long getCityId() {
return cityId;
}
public void setCityId(Long cityId) {
this.cityId = cityId;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getCityShortName() {
return cityShortName;
}
public void setCityShortName(String cityShortName) {
this.cityShortName = cityShortName;
}
public String getCityStatus() {
return cityStatus;
}
public void setCityStatus(String cityStatus) {
this.cityStatus = cityStatus;
}
public String getCityRemark() {
return cityRemark;
}
public void setCityRemark(String cityRemark) {
this.cityRemark = cityRemark;
}
public String getCityTop() {
return cityTop;
}
public void setCityTop(String cityTop) {
this.cityTop = cityTop;
}
public Date getCityTopTime() {
return cityTopTime;
}
public void setCityTopTime(Date cityTopTime) {
this.cityTopTime = cityTopTime;
}
}
package com.tools.module.business.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import java.io.Serializable;
import java.util.Date;
@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 是否删除
*/
@Column(name = "is_deleted", length = 2,columnDefinition = "varchar(2) NOT NULL DEFAULT 'N' COMMENT '是否删除 N:否 Y:是'", insertable = false)
private String isDeleted;
@CreatedBy
@Column(name = "created_by", nullable = false, updatable = false)
@JsonIgnore
private Long createdBy;
@CreatedDate
@Column(name = "created_time", nullable = false, updatable = false)
@JsonIgnore
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createdTime;
@LastModifiedBy
@Column(name = "updated_by", nullable = false)
@JsonIgnore
private Long updatedBy;
@LastModifiedDate
@Column(name = "updated_time", nullable = false)
@JsonIgnore
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updatedTime;
@Version
@Column(name = "version", length = 20)
private Long version;
}
\ No newline at end of file
package com.tools.module.business.entity;
import com.tools.module.business.model.SysCityModel;
import lombok.Data;
import java.io.Serializable;
/**
*
*/
@Data
public class SysCityEntity extends SysCityModel implements Serializable{
}
package com.tools.module.business.entity;
import com.tools.module.business.model.SysCruisesProjectModel;
import lombok.Data;
import java.io.Serializable;
@Data
public class SysCruisesProjectEntity extends SysCruisesProjectModel implements Serializable {
}
package com.tools.module.business.model;
import com.tools.module.business.entity.BaseEntity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* sys_city 实体类
* Sun Oct 27 13:03:00 CST 2019
*/
@Data
@Entity
@Table(name = "sys_city")
public class SysCityModel extends BaseEntity implements Serializable {
/**
* 城市id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "city_id", nullable = false, length = 20)
private Long cityId;
/**
* 城市名
*/
@Column(name = "city_name", nullable = false, length = 50)
private String cityName;
/**
* 城市简写
*/
@Column(name = "city_short_name", nullable = false, length = 50)
private String cityShortName;
/**
* 城市状态
*/
@Column(name = "city_status", nullable = false, length = 50)
private String cityStatus;
/**
* 城市简介
*/
@Column(name = "city_remark", length = 6)
private String cityRemark;
/**
* 是否置顶
*/
@Column(name = "city_top", nullable = false, length = 20, columnDefinition = "VARCHAR(20) COMMENT '是否置顶'")
private String cityTop;
/**
* 置顶时间
*/
@Column(name = "city_top_time", length = 500)
private Date cityTopTime;
}
package com.tools.module.business.model;
import com.tools.module.business.entity.BaseEntity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* sys_cruises_project 实体类
* Sun Oct 27 13:03:00 CST 2019
*/
@Data
@Entity
@Table(name = "sys_cruises_project")
public class SysCruisesProjectModel extends BaseEntity implements Serializable {
/**
* 游船id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cruises_project_id", nullable = false, length = 20)
private Long cruisesProjectId;
/**
* 游船名称
*/
@Column(name = "cruises_project_name", nullable = false, length = 50)
private String cruisesProjectName;
/**
* 城市id
*/
@Column(name = "city_id", nullable = false, length = 20)
private Long cityId;
/**
* 游船封面图
*/
@Column(name = "cruises_project_cover_url", nullable = false, length = 50)
private String cruisesProjectCoverUrl;
/**
* 游船简介
*/
@Column(name = "cruises_project_synopsis", length = 6)
private String cruisesProjectSynopsis;
/**
* 游船详情
*/
@Column(name = "cruises_project_particulars", length = 6)
private String cruisesProjectParticulars;
/**
* 是否置顶
*/
@Column(name = "cruises_project_top", nullable = false, length = 20, columnDefinition = "VARCHAR(20) COMMENT '是否置顶'")
private String cruisesProjectTop;
/**
* 置顶时间
*/
@Column(name = "cruises_project_top_time", length = 500)
private Date cruisesProjectTopTime;
}
package com.tools.module.business.repository;
import com.tools.module.business.model.SysCityModel;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* Oct 27 12:56:55 CST 2019
*/
@Repository
public interface SysCityRepository extends JpaRepository<SysCityModel, Long> {
List<SysCityModel> findByCityNameContaining(String cityName);
Page<SysCityModel> findByCityNameContainingOrCityTopAndIsDeleted(String cityName, String cityTop, String isDeleted, Pageable pageable);
}
package com.tools.module.business.service;
import com.tools.common.model.Result;
import com.tools.module.business.entity.SysCityEntity;
import org.springframework.data.domain.Pageable;
public interface SysCityService {
Result save(SysCityEntity sysCityEntity);
Result update(SysCityEntity sysCityEntity);
Result list(SysCityEntity sysCityEntity, Pageable pageable);
Result delete(Long cityId);
}
package com.tools.module.business.service;
import com.tools.common.model.Result;
import com.tools.module.business.entity.SysCruisesProjectEntity;
import org.springframework.data.domain.Pageable;
public interface SysCruisesProjectService {
Result save(SysCruisesProjectEntity sysCruisesProjectEntity);
Result update(SysCruisesProjectEntity sysCruisesProjectEntity);
Result list(SysCruisesProjectEntity sysCruisesProjectEntity, Pageable pageable);
Result delete(Long cityId);
}
package com.tools.module.business.service.impl;
import com.tools.common.constant.SystemConstant;
import com.tools.common.dynamicquery.DynamicQuery;
import com.tools.common.exception.BusinessException;
import com.tools.common.model.Result;
import com.tools.module.business.constants.SysCityConstants;
import com.tools.module.business.convert.SysCityConvert;
import com.tools.module.business.entity.SysCityEntity;
import com.tools.module.business.model.SysCityModel;
import com.tools.module.business.repository.SysCityRepository;
import com.tools.module.business.service.SysCityService;
import com.tools.module.business.utils.AssertUtils;
import com.tools.module.business.utils.ChineseCharacterUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import static com.tools.module.business.convert.SysCityConvert.convertPageModel2Entity;
@Service
public class SysCityServiceImpl implements SysCityService {
@Autowired
private DynamicQuery dynamicQuery;
@Autowired
private SysCityRepository sysCityRepository;
@Override
@Transactional(rollbackFor = Exception.class)
// @CacheEvict(cacheNames = {"sys:city:tree"})
public Result save(SysCityEntity sysCityEntity) {
AssertUtils.notBlank(sysCityEntity.getCityName());
AssertUtils.notBlank(sysCityEntity.getCityTop());
SysCityModel sysCityModel = SysCityConvert.convertEntity2Model(sysCityEntity);
if (StringUtils.isBlank(sysCityModel.getCityName())) {
throw new BusinessException("城市名不能为空");
} else {
SysCityModel example = new SysCityModel();
example.setCityName(sysCityModel.getCityName());
example.setIsDeleted(SystemConstant.IsDeleted.N);
List<SysCityModel> sysCityModelList = sysCityRepository.findAll(Example.of(example));
if (CollectionUtils.isNotEmpty(sysCityModelList)) {
throw new BusinessException("城市名已存在,请重新输入");
}
}
sysCityModel.setCityStatus(SysCityConstants.Status.DISABLED);
sysCityModel.setCityShortName(ChineseCharacterUtil.convertHanzi2Pinyin(sysCityEntity.getCityName(), false).toUpperCase().substring(0, 1));
if (StringUtils.isNotBlank(sysCityModel.getCityTop()) && "Y".equals(sysCityModel.getCityTop())) {
sysCityModel.setCityTopTime(new Date());
}
sysCityRepository.saveAndFlush(sysCityModel);
return Result.ok("保存成功");
}
@Override
@Transactional(rollbackFor = Exception.class)
// @CacheEvict(cacheNames = {"sys:city:tree"})
public Result update(SysCityEntity sysCityEntity) {
AssertUtils.notNull(sysCityEntity.getCityId());
AssertUtils.notBlank(sysCityEntity.getCityName());
AssertUtils.notBlank(sysCityEntity.getCityTop());
SysCityModel oldSysCityModel = sysCityRepository.getOne(sysCityEntity.getCityId());
if (oldSysCityModel == null || SystemConstant.IsDeleted.Y.equals(oldSysCityModel.getIsDeleted())) {
throw new BusinessException("找不到该城市信息");
}
//检查名字更改
if ( !oldSysCityModel.getCityName().equals(sysCityEntity.getCityName())) {
SysCityModel example = new SysCityModel();
example.setCityName(sysCityEntity.getCityName());
example.setIsDeleted(SystemConstant.IsDeleted.N);
List<SysCityModel> sysCityModelList = sysCityRepository.findAll(Example.of(example));
if (CollectionUtils.isNotEmpty(sysCityModelList)) {
throw new BusinessException("城市名已存在,请重新输入");
}
oldSysCityModel.setCityName(sysCityEntity.getCityName());
oldSysCityModel.setCityShortName(ChineseCharacterUtil.convertHanzi2Pinyin(sysCityEntity.getCityName(), false).toUpperCase().substring(0, 1));
}
if ("Y".equals(sysCityEntity.getCityTop()) && "N".equals(oldSysCityModel.getCityTop())) {
oldSysCityModel.setCityTopTime(new Date());
} else if ("N".equals(sysCityEntity.getCityTop())) {
oldSysCityModel.setCityTopTime(null);
}
//更新
oldSysCityModel.setCityTop(sysCityEntity.getCityTop());
oldSysCityModel.setCityRemark(sysCityEntity.getCityRemark());
return Result.ok("保存成功");
}
@Override
public Result list(SysCityEntity sysCityEntity, Pageable pageable) {
String nativeSql = "SELECT * FROM sys_city WHERE ( city_name = ? or city_top = ? ) and is_deleted = 'N' order by city_top_time desc , created_time desc ";
Page<SysCityModel> sysCityModelList = dynamicQuery.nativeQueryPageList(SysCityModel.class, pageable, nativeSql, sysCityEntity.getCityName(), sysCityEntity.getCityTop());
return Result.ok(convertPageModel2Entity(sysCityModelList));
}
@Override
@Transactional(rollbackFor = Exception.class)
// @CacheEvict(cacheNames = {"sys:area:tree"})
public Result delete(Long cityId) {
AssertUtils.notNull(cityId);
SysCityModel oldSysCityModel = sysCityRepository.getOne(cityId);
if (oldSysCityModel == null || SystemConstant.IsDeleted.Y.equals(oldSysCityModel.getIsDeleted())) {
throw new BusinessException("找不到该城市信息");
}
oldSysCityModel.setIsDeleted(SystemConstant.IsDeleted.Y);
sysCityRepository.saveAndFlush(oldSysCityModel);
return Result.ok("删除成功");
}
}
package com.tools.module.business.service.impl;
import com.tools.common.model.Result;
import com.tools.module.business.entity.SysCruisesProjectEntity;
import com.tools.module.business.service.SysCruisesProjectService;
import com.tools.module.business.utils.AssertUtils;
import org.springframework.data.domain.Pageable;
/**
* @Author:Roger Wu
* @name:SysCruisesProjectServiceImpl
* @Date:2025-06-12 23:00
*/
public class SysCruisesProjectServiceImpl implements SysCruisesProjectService {
@Override
public Result save(SysCruisesProjectEntity sysCruisesProjectEntity) {
AssertUtils.notBlank(sysCruisesProjectEntity.getCruisesProjectName());
AssertUtils.notNull(sysCruisesProjectEntity.getCityId());
return Result.ok("保存成功");
}
@Override
public Result update(SysCruisesProjectEntity sysCruisesProjectEntity) {
return null;
}
@Override
public Result list(SysCruisesProjectEntity sysCruisesProjectEntity, Pageable pageable) {
return null;
}
@Override
public Result delete(Long cityId) {
return null;
}
}
package com.tools.module.business.utils;
import org.apache.commons.lang3.StringUtils;
/**
* @Author:Roger Wu
* @name:AssertUtils
* @Date:2025-06-12 11:27
*/
public class AssertUtils {
public static void notBlank(String text) {
if (StringUtils.isBlank(text)) {
throw new IllegalArgumentException("缺少必要参数");
}
}
public static void notBlank(String text, String message) {
if (StringUtils.isBlank(text)) {
throw new IllegalArgumentException("缺少必要参数-[" + message + "]");
}
}
public static void notNull(Object text, String message) {
if (text == null) {
throw new IllegalArgumentException("缺少必要参数-[" + message + "]");
}
}
public static void notNull(Object text) {
if (text == null) {
throw new IllegalArgumentException("缺少必要参数");
}
}
}
package com.tools.module.business.utils;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import org.apache.commons.lang3.StringUtils;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ChineseCharacterUtil {
/**
* 获取汉字首字母或全拼大写字母
*
* @param chinese 汉字
* @param isFull 是否全拼 true:表示全拼 false表示:首字母
*
* @return 全拼或者首字母大写字符窜
*/
public static String getUpperCase(String chinese,boolean isFull){
return convertHanzi2Pinyin(chinese,isFull).toUpperCase();
}
/**
* 获取汉字首字母或全拼小写字母
*
* @param chinese 汉字
* @param isFull 是否全拼 true:表示全拼 false表示:首字母
*
* @return 全拼或者首字母小写字符窜
*/
public static String getLowerCase(String chinese,boolean isFull){
return convertHanzi2Pinyin(chinese,isFull).toLowerCase();
}
/**
* 将汉字转成拼音
* <P>
* 取首字母或全拼
*
* @param hanzi 汉字字符串
* @param isFull 是否全拼 true:表示全拼 false表示:首字母
*
* @return 拼音
*/
public static String convertHanzi2Pinyin(String hanzi, boolean isFull){
/***
* ^[\u2E80-\u9FFF]+$ 匹配所有东亚区的语言
* ^[\u4E00-\u9FFF]+$ 匹配简体和繁体
* ^[\u4E00-\u9FA5]+$ 匹配简体
*/
String regExp="^[\u4E00-\u9FFF]+$";
StringBuffer sb=new StringBuffer();
if(hanzi==null||"".equals(hanzi.trim())){
return "";
}
String pinyin="";
for(int i=0;i<hanzi.length();i++){
char unit=hanzi.charAt(i);
//是汉字,则转拼音
if(match(String.valueOf(unit),regExp)){
pinyin=convertSingleHanzi2Pinyin(unit);
if(isFull){
sb.append(pinyin);
} else if(StringUtils.isNoneBlank(pinyin)){
sb.append(pinyin.charAt(0));
}
}else{
sb.append(unit);
}
}
return sb.toString();
}
/**
* 将单个汉字转成拼音
*
* @param hanzi 汉字字符
*
* @return 拼音
*/
private static String convertSingleHanzi2Pinyin(char hanzi){
HanyuPinyinOutputFormat outputFormat = new HanyuPinyinOutputFormat();
outputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
String[] res;
StringBuffer sb=new StringBuffer();
try {
res = PinyinHelper.toHanyuPinyinStringArray(hanzi,outputFormat);
if(res!=null){
sb.append(res[0]);//对于多音字,只用第一个拼音
}
} catch (Exception e) {
e.printStackTrace();
return "";
}
return sb.toString();
}
/***
* 匹配
* <P>
* 根据字符和正则表达式进行匹配
*
* @param str 源字符串
* @param regex 正则表达式
*
* @return true:匹配成功 false:匹配失败
*/
private static boolean match(String str,String regex){
Pattern pattern= Pattern.compile(regex);
Matcher matcher=pattern.matcher(str);
return matcher.find();
}
public static boolean isChineseChar(char c) {
return String.valueOf(c).getBytes(StandardCharsets.UTF_8).length > 1;
}
}
package com.tools.module.sys.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tools.common.model.PageBean;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* sys_config 实体类
*
* Sun Oct 27 13:01:25 CST 2019
*/
@Data
@Entity
@Table(name = "sys_config")
public class SysConfig extends PageBean implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, length = 20)
private Long id;
/**
* 键
*/
@Column(name = "config_key", length = 50)
private String key;
/**
* 值
*/
@Column(name = "config_value", length = 2000)
private String value;
/**
* 状态,0:隐藏 1:显示
*/
@Column(name = "status", length = 4)
private Short status;
/**
* 备注
*/
@Column(name = "config_remark", length = 500)
private String remark;
/**
* 创建时间
*/
@Column(name = "gmt_create")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp gmtCreate;
/**
* 修改时间
*/
@Column(name = "gmt_modified")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp gmtModified;
/**
* 创建用户id
*/
@Column(name = "user_id_create")
private Long userIdCreate;
}
package com.tools.module.sys.entity;
import lombok.Data;
@Data
public class SysFile {
private Integer fileId;
private String name;
private Integer parentId;
private String parentPath;
private boolean directory;
}
package com.tools.module.sys.entity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* sys_macro 实体类
*
* Sun Oct 27 13:01:25 CST 2019
*/
@Data
@Entity
@Table(name = "sys_macro")
public class SysMacro implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "macro_id", nullable = false, length = 20)
private Long macroId;
/**
* 父级id
*/
@Column(name = "type_id", length = 255)
private Long typeId;
/**
* 名称
*/
@Column(name = "name", length = 50)
private String name;
/**
* 值
*/
@Column(name = "value", length = 2000)
private String value;
/**
* 状态,0:隐藏 1:显示
*/
@Column(name = "status", length = 4)
private Short status;
/**
* 类型,0:目录,1:参数配置
*/
@Column(name = "type", length = 20)
private Short type;
/**
* 排序
*/
@Column(name = "order_num", length = 11)
private Integer orderNum;
/**
* 备注
*/
@Column(name = "remark", length = 500)
private String remark;
/**
* 创建时间
*/
@Column(name = "gmt_create")
private Timestamp gmtCreate;
/**
* 修改时间
*/
@Column(name = "gmt_modified")
private Timestamp gmtModified;
}
package com.tools.module.sys.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tools.common.model.PageBean;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
/**
* sys_menu 实体类
*
* Sun Oct 27 13:02:31 CST 2019
*/
@Data
@Entity
@Table(name = "sys_menu")
public class SysMenu extends PageBean implements Serializable{
/**
* 菜单id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "menu_id", nullable = false, length = 20)
private Long menuId;
/**
* 父菜单ID,一级菜单为0
*/
@Column(name = "parent_id", length = 20)
private Long parentId;
/**
* 菜单名称
*/
@Column(name = "name", length = 50)
private String name;
/**
* 菜单URL
*/
@Column(name = "url", length = 200)
private String url;
/**
* 授权(多个用逗号分隔,如:user:list,user:create)
*/
@Column(name = "perms", length = 500)
private String perms;
/**
* 类型 0:目录 1:菜单 2:按钮
*/
@Column(name = "type", length = 11)
private Integer type;
/**
* 菜单图标
*/
@Column(name = "icon", length = 50)
private String icon;
/**
* 排序
*/
@Column(name = "order_num", length = 11)
private Integer orderNum;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Column(name = "gmt_create")
private Timestamp gmtCreate;
/**
* 修改时间
*/
@Column(name = "gmt_modified")
private Timestamp gmtModified;
@Transient
private Boolean spread = false;
@Transient
private String parentName;
@Transient
private Boolean isParent;
@Transient
private List<SysMenu> list;
}
package com.tools.module.sys.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tools.common.model.PageBean;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* sys_org 实体类
*
* Sun Oct 27 13:02:24 CST 2019
*/
@Data
@Entity
@Table(name = "sys_org")
public class SysOrg extends PageBean implements Serializable{
/**
* 机构id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "org_id", nullable = false, length = 20)
private Long orgId;
/**
* 上级机构ID,一级机构为0
*/
@Column(name = "parent_id", length = 20)
private Long parentId;
/**
* 机构编码
*/
@Column(name = "code", length = 100)
private String code;
/**
* 机构名称
*/
@Column(name = "name", length = 100)
private String name;
/**
* 机构名称(全称)
*/
@Column(name = "full_name", length = 100)
private String fullName;
/**
* 机构负责人
*/
@Column(name = "director", length = 100)
private String director;
/**
* 联系邮箱
*/
@Column(name = "email", length = 100)
private String email;
/**
* 联系电话
*/
@Column(name = "phone", length = 100)
private String phone;
/**
* 地址
*/
@Column(name = "address", length = 200)
private String address;
/**
* 排序
*/
@Column(name = "order_num", length = 11)
private Integer orderNum;
/**
* 可用标识 1:可用 0:不可用
*/
@Column(name = "status", length = 4)
private Short status;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Column(name = "gmt_create")
private Timestamp gmtCreate;
/**
* 修改时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Column(name = "gmt_modified")
private Timestamp gmtModified;
@Transient
private String parentName;
}
package com.tools.module.sys.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tools.common.model.PageBean;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
/**
* sys_role 实体类
*
* Sun Oct 27 13:02:41 CST 2019
*/
@Data
@Entity
@Table(name = "sys_role")
public class SysRole extends PageBean implements Serializable{
/**
* 角色id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "role_id", nullable = false, length = 20)
private Long roleId;
/**
* 所属机构
*/
@Column(name = "org_id")
private Long orgId;
/**
* 角色名称
*/
@Column(name = "role_name", length = 100)
private String roleName;
/**
* 角色标识
*/
@Column(name = "role_sign", length = 100)
private String roleSign;
/**
* 备注
*/
@Column(name = "remark", length = 100)
private String remark;
/**
* 创建用户id
*/
@Column(name = "user_id_create")
private Long userIdCreate;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Column(name = "gmt_create")
private Timestamp gmtCreate;
/**
* 修改时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Column(name = "gmt_modified")
private Timestamp gmtModified;
@Transient
private List<Long> menuIdList;
@Transient
private List<Long> orgIdList;
}
package com.tools.module.sys.entity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
/**
* sys_role_menu 实体类
*
* Sun Oct 27 13:02:47 CST 2019
*/
@Data
@Entity
@Table(name = "sys_role_menu")
public class SysRoleMenu implements Serializable{
/**
* 记录id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, length = 20)
private Long id;
/**
* 角色ID
*/
@Column(name = "role_id", length = 20)
private Long roleId;
/**
* 菜单ID
*/
@Column(name = "menu_id", length = 20)
private Long menuId;
}
package com.tools.module.sys.entity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
/**
* sys_role_org 实体类
*
* Sun Oct 27 13:02:54 CST 2019
*/
@Data
@Entity
@Table(name = "sys_role_org")
public class SysRoleOrg implements Serializable{
/**
* 记录id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, length = 20)
private Long id;
/**
* 角色ID
*/
@Column(name = "role_id", length = 20)
private Long roleId;
/**
* 机构ID
*/
@Column(name = "org_id", length = 20)
private Long orgId;
}
package com.tools.module.sys.entity;
import com.tools.module.business.entity.BaseEntity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
/**
* sys_user 实体类
*
* Sun Oct 27 13:03:00 CST 2019
*/
@Data
@Entity
@Table(name = "sys_user")
public class SysUser extends BaseEntity implements Serializable{
/**
* 用户id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id", nullable = false, length = 20)
private Long userId;
/**
* 登录账号
*/
@Column(name = "login_account", nullable = false, length = 50)
private String loginAccount;
/**
* 用户名
*/
@Column(name = "username", nullable = false, length = 50)
private String username;
/**
* 密码
*/
@Column(name = "password", nullable = false, length = 50)
private String password;
/**
* 状态 0:禁用,1:正常
*/
@Column(name = "status", length = 6)
private String status;
/**
* 所属机构
*/
@Column(name = "org_id", nullable = false, length = 20)
private Long orgId;
/**
* 备注
*/
@Column(name = "remark", length = 500)
private String remark;
/**
* 角色ID
*/
@Transient
private List<Object> roleIdList;
/**
* 角色名称
*/
@Transient
private List<Object> roleNameList;
}
package com.tools.module.sys.entity;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
/**
* sys_user_role 实体类
*
* Sun Oct 27 13:03:06 CST 2019
*/
@Data
@Entity
@Table(name = "sys_user_role")
public class SysUserRole implements Serializable{
/**
* 记录id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, length = 20)
private Long id;
/**
* 用户ID
*/
@Column(name = "user_id", length = 20)
private Long userId;
/**
* 角色ID
*/
@Column(name = "role_id", length = 20)
private Long roleId;
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_user Repository
*
* Sun Oct 27 13:03:00 CST 2019
*/
@Repository
public interface SysConfigRepository extends JpaRepository<SysConfig, Long> {
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysMacro;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_macro Repository
*
* Sun Oct 27 13:01:25 CST 2019
*/
@Repository
public interface SysMacroRepository extends JpaRepository<SysMacro, Long> {
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysMenu;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_menu Repository
*
* Sun Oct 27 13:02:31 CST 2019
*/
@Repository
public interface SysMenuRepository extends JpaRepository<SysMenu, Long> {
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysOrg;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_org Repository
*
* Sun Oct 27 13:02:24 CST 2019
*/
@Repository
public interface SysOrgRepository extends JpaRepository<SysOrg, Long> {
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysRoleMenu;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_role_menu Repository
*
* Sun Oct 27 13:02:47 CST 2019
*/
@Repository
public interface SysRoleMenuRepository extends JpaRepository<SysRoleMenu, Long> {
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysRoleOrg;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_role_org Repository
*
* Sun Oct 27 13:02:54 CST 2019
*/
@Repository
public interface SysRoleOrgRepository extends JpaRepository<SysRoleOrg, Long> {
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysRole;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_role Repository
*
* Sun Oct 27 13:02:41 CST 2019
*/
@Repository
public interface SysRoleRepository extends JpaRepository<SysRole, Long> {
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_user Repository
*
* Sun Oct 27 13:03:00 CST 2019
*/
@Repository
public interface SysUserRepository extends JpaRepository<SysUser, Long> {
}
package com.tools.module.sys.repository;
import com.tools.module.sys.entity.SysUserRole;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* sys_user_role Repository
*
* Sun Oct 27 13:03:06 CST 2019
*/
@Repository
public interface SysUserRoleRepository extends JpaRepository<SysUserRole, Long> {
}
package com.tools.module.sys.service;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysConfig;
public interface SysConfigService {
Result save(SysConfig config);
Result get(Long id);
Result delete(Long id);
Result list(SysConfig config);
}
package com.tools.module.sys.service;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysMenu;
import java.util.List;
public interface SysMenuService {
Result list(SysMenu menu);
List<SysMenu> select(Long parentId);
Result delete(Long menuId);
List<SysMenu> getByUserId(Long userId);
Result drop(Long parentId, Long menuId);
}
package com.tools.module.sys.service;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysOrg;
public interface SysOrgService {
Result list(SysOrg org);
Result select(Long parentId);
Result save(SysOrg org);
Result delete(Long orgId);
}
package com.tools.module.sys.service;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysRole;
public interface SysRoleService {
Result list(SysRole role);
Result select();
Result save(SysRole role);
Result delete(Long roleId);
Result getMenu(Long roleId);
Result saveMenu(SysRole role);
Result getOrg(Long roleId);
Result saveOrg(SysRole role);
}
package com.tools.module.sys.service;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysUser;
import java.util.List;
/**
* 用户管理
*
*/
public interface SysUserService {
/**
* 保存用户
* @param user
* @return
*/
Result save(SysUser user);
/**
* 根据用户ID获取用户
* @param userId
* @return
*/
Result get(Long userId);
/**
* 根据用户ID删除用户
* @param userId
* @return
*/
Result delete(Long userId);
/**
* 根据登录账号获取用户
* @param loginAccount
* @return
*/
SysUser getUser(String loginAccount);
/**
* 用户列表
* @param user
* @return
*/
Result list(SysUser user);
/**
* 根据用户ID获取用户角色
* @param userId
* @return
*/
List<String> listUserRoles(Long userId);
/**
* 根据用户ID获取用户权限
* @param userId
* @return
*/
List<String> listUserPerms(Long userId);
/**
* 更新用户密码
* @param user
* @return
*/
Result updatePwd(SysUser user);
}
package com.tools.module.sys.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import com.tools.common.dynamicquery.DynamicQuery;
import com.tools.common.model.PageBean;
import com.tools.common.model.Result;
import com.tools.common.util.DateUtils;
import com.tools.module.sys.entity.SysConfig;
import com.tools.module.sys.repository.SysConfigRepository;
import com.tools.module.sys.service.SysConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class SysConfigServiceImpl implements SysConfigService {
@Autowired
private DynamicQuery dynamicQuery;
@Autowired
private SysConfigRepository sysConfigRepository;
@Override
@Transactional(rollbackFor = Exception.class)
public Result save(SysConfig config) {
String nativeSql = "SELECT * FROM sys_config WHERE config_key=?";
SysConfig sysConfig = dynamicQuery.nativeQuerySingleResult(
SysConfig.class,nativeSql, config.getKey());
if(sysConfig!=null){
if(!config.getId().equals(sysConfig.getId())){
return Result.error("配置键重复");
}
}else{
config.setGmtCreate(DateUtils.getTimestamp());
}
config.setUserIdCreate(StpUtil.getLoginIdAsLong());
sysConfigRepository.saveAndFlush(config);
return Result.ok("保存成功");
}
@Override
public Result get(Long id) {
SysConfig config = sysConfigRepository.getOne(id);
return Result.ok(config);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result delete(Long id) {
sysConfigRepository.deleteById(id);
return Result.ok("删除成功");
}
@Override
public Result list(SysConfig config) {
String nativeSql = "SELECT COUNT(*) FROM sys_config ";
nativeSql += common(config);
Long count = dynamicQuery.nativeQueryCount(nativeSql);
PageBean<SysConfig> data = new PageBean<>();
if(count>0){
nativeSql = "SELECT * FROM sys_config ";
nativeSql += common(config);
nativeSql += "ORDER BY gmt_create desc";
Pageable pageable = PageRequest.of(config.getPageNo(),config.getPageSize());
List<SysConfig> list = dynamicQuery.nativeQueryPagingList(SysConfig.class,pageable,nativeSql);
data = new PageBean(list,count);
}
return Result.ok(data);
}
public String common(SysConfig config){
String description = config.getDescription();
String commonSql = "";
if(StringUtils.isNotBlank(description)){
commonSql += "WHERE config_key like '"+description+"%' ";
commonSql += "OR config_value like '"+description+"%' ";
}
return commonSql;
}
}
package com.tools.module.sys.service.impl;
import com.tools.common.constant.SystemConstant;
import com.tools.common.dynamicquery.DynamicQuery;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysMenu;
import com.tools.module.sys.service.SysMenuService;
import com.tools.module.sys.service.SysUserService;
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.List;
@Service
public class SysMenuServiceImpl implements SysMenuService {
@Autowired
private DynamicQuery dynamicQuery;
@Autowired
private SysUserService sysUserService;
@Override
public Result list(SysMenu menu) {
String nativeSql = "SELECT * FROM sys_menu WHERE parent_id=?";
String description = menu.getDescription();
if(StringUtils.isNotBlank(description)){
nativeSql +=" AND name like '"+description+"%'";
}
nativeSql += " ORDER BY order_num";
List<SysMenu> menuList
= dynamicQuery.query(SysMenu.class,nativeSql, menu.getParentId());
return Result.ok(menuList);
}
@Override
public List<SysMenu> select(Long parentId) {
String nativeSql = "SELECT * FROM sys_menu ";
if(parentId!=null){
nativeSql += " WHERE parent_id="+parentId;
}
nativeSql += " ORDER BY order_num desc";
return dynamicQuery.query(SysMenu.class,nativeSql);
}
@Override
@Transactional(rollbackFor=Exception.class)
public Result delete(Long menuId) {
String nativeSql = "SELECT * FROM sys_menu WHERE menu_id = ?";
SysMenu menu =
dynamicQuery.nativeQuerySingleResult(SysMenu.class,nativeSql, menuId);
if(menu.getType().equals(SystemConstant.MenuType.CATALOG)){
nativeSql = "SELECT COUNT(*) FROM sys_menu WHERE parent_id=?";
Long count = dynamicQuery.nativeQueryCount(nativeSql, menuId);
if(count>0){
return Result.error("请先删除下级目录、菜单或者按钮");
}
}else if(menu.getType().equals(SystemConstant.MenuType.MENU)){
/**
* 删除下级按钮
*/
nativeSql = "DELETE FROM sys_menu WHERE parent_id = ?";
dynamicQuery.nativeExecuteUpdate(nativeSql, menuId);
}
/**
* 删除自身
*/
nativeSql = "DELETE FROM sys_menu WHERE menu_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, menuId);
return Result.ok("删除成功");
}
@Override
public List<SysMenu> getByUserId(Long userId) {
String nativeSql = "SELECT DISTINCT m.* FROM sys_menu m ";
nativeSql +="LEFT JOIN sys_role_menu rm ON m.menu_id = rm.menu_id ";
nativeSql +="LEFT JOIN sys_role r ON r.role_id = rm.role_id ";
nativeSql +="WHERE r.role_id IN (SELECT role_id FROM sys_user_role WHERE user_id=?) ";
nativeSql +="AND m.TYPE = 0 ORDER BY m.order_num";
List<SysMenu> list = dynamicQuery.query(SysMenu.class,nativeSql, userId);
list.stream().forEach(menu->{
String subSql = "SELECT DISTINCT m.* FROM sys_menu m ";
subSql +="LEFT JOIN sys_role_menu rm ON m.menu_id = rm.menu_id ";
subSql +="LEFT JOIN sys_role r ON r.role_id = rm.role_id ";
subSql +="WHERE r.role_id IN (SELECT role_id FROM sys_user_role WHERE user_id=?) ";
subSql +="AND m.parent_id = ? ORDER BY m.order_num";
List<SysMenu> subList
= dynamicQuery.query(SysMenu.class,subSql, userId,menu.getMenuId());
menu.setList(subList);
});
return list;
}
@Override
@Transactional(rollbackFor=Exception.class)
public Result drop(Long parentId, Long menuId) {
String nativeSql = "UPDATE sys_menu SET parent_id=? WHERE menu_id=?";
int count = dynamicQuery.nativeExecuteUpdate(nativeSql, parentId,menuId);
if(count==0){
return Result.error();
}else{
return Result.ok("更新成功");
}
}
}
package com.tools.module.sys.service.impl;
import com.tools.common.dynamicquery.DynamicQuery;
import com.tools.common.model.PageBean;
import com.tools.common.model.Result;
import com.tools.common.util.DateUtils;
import com.tools.module.sys.entity.SysOrg;
import com.tools.module.sys.repository.SysOrgRepository;
import com.tools.module.sys.service.SysOrgService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class SysOrgServiceImpl implements SysOrgService {
@Autowired
private DynamicQuery dynamicQuery;
@Autowired
private SysOrgRepository sysOrgRepository;
@Override
public Result list(SysOrg org) {
String nativeSql = "SELECT COUNT(*) FROM sys_org WHERE parent_id=? ";
String description = org.getDescription();
if(StringUtils.isNotBlank(description)){
nativeSql +="AND name like '"+description+"%'";
}
Long count = dynamicQuery.nativeQueryCount(nativeSql, org.getParentId());
PageBean<SysOrg> data = new PageBean<>();
if(count>0){
nativeSql = "SELECT * FROM sys_org WHERE parent_id=? ";
if(StringUtils.isNotBlank(description)){
nativeSql +="AND name like '"+description+"%' ";
}
nativeSql +="ORDER BY gmt_create desc";
Pageable pageable = PageRequest.of(org.getPageNo(),org.getPageSize());
List<SysOrg> list =
dynamicQuery.nativeQueryPagingList(SysOrg.class,pageable,nativeSql, org.getParentId());
data = new PageBean(list,count);
}
return Result.ok(data);
}
@Override
public Result select(Long parentId) {
String nativeSql = "SELECT * FROM sys_org";
if(parentId!=null){
nativeSql += " WHERE parent_id="+parentId;
}
nativeSql += " ORDER BY order_num desc";
List<SysOrg> list = dynamicQuery.query(SysOrg.class,nativeSql);
return Result.ok(list);
}
@Override
@Transactional(rollbackFor=Exception.class)
public Result save(SysOrg org) {
String nativeSql = "SELECT * FROM sys_org WHERE code=?";
SysOrg sysOrg = dynamicQuery.nativeQuerySingleResult(
SysOrg.class,nativeSql, org.getCode());
if(sysOrg==null){
org.setGmtCreate(DateUtils.getTimestamp());
}else{
if(!sysOrg.getOrgId().equals(org.getOrgId())){
return Result.error("机构代码重复");
}
}
org.setGmtModified(DateUtils.getTimestamp());
if(org.getParentId()==null){
org.setParentId(0L);
}
sysOrgRepository.saveAndFlush(org);
return Result.ok("保存成功");
}
@Override
@Transactional(rollbackFor=Exception.class)
public Result delete(Long orgId) {
String nativeSql = "SELECT COUNT(*) FROM sys_org WHERE parent_id=?";
Long count = dynamicQuery.nativeQueryCount(nativeSql, orgId);
if(count>0){
return Result.error("请先删除下级机构");
}else{
nativeSql = "DELETE FROM sys_org WHERE org_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, orgId);
}
return Result.ok("删除成功");
}
}
package com.tools.module.sys.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import com.tools.common.dynamicquery.DynamicQuery;
import com.tools.common.model.PageBean;
import com.tools.common.model.Result;
import com.tools.common.util.DateUtils;
import com.tools.module.sys.entity.SysRole;
import com.tools.module.sys.entity.SysRoleMenu;
import com.tools.module.sys.entity.SysRoleOrg;
import com.tools.module.sys.repository.SysRoleRepository;
import com.tools.module.sys.service.SysRoleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class SysRoleServiceImpl implements SysRoleService {
@Autowired
private DynamicQuery dynamicQuery;
@Autowired
private SysRoleRepository sysRoleRepository;
@Override
public Result list(SysRole role) {
String nativeSql = "SELECT COUNT(*) FROM sys_role ";
nativeSql += common(role);
Long count = dynamicQuery.nativeQueryCount(nativeSql);
PageBean<SysRole> data = new PageBean<>();
if(count>0){
nativeSql = "SELECT * FROM sys_role ";
nativeSql += common(role);
nativeSql += "ORDER BY gmt_create desc ";
Pageable pageable = PageRequest.of(role.getPageNo(),role.getPageSize());
List<SysRole> list = dynamicQuery.nativeQueryPagingList(SysRole.class,pageable,nativeSql);
data = new PageBean(list,count);
}
return Result.ok(data);
}
public String common(SysRole role){
String description = role.getDescription();
String commonSql = "";
if(StringUtils.isNotBlank(description)){
commonSql += "WHERE role_name like '"+description+"%' ";
commonSql += "OR role_sign like '"+description+"%' ";
}
return commonSql;
}
@Override
public Result select() {
String nativeSql = "SELECT * FROM sys_role";
List<SysRole> list = dynamicQuery.query(SysRole.class,nativeSql);
return Result.ok(list);
}
@Override
@Transactional
public Result save(SysRole role) {
String nativeSql = "SELECT * FROM sys_role WHERE role_sign=?";
SysRole sysRole =
dynamicQuery.nativeQuerySingleResult(SysRole.class,nativeSql, role.getRoleSign());
if(sysRole!=null){
if(!sysRole.getRoleSign().equals(role.getRoleSign())){
return Result.error("角色代码重复");
}
}else{
role.setGmtCreate(DateUtils.getTimestamp());
}
role.setGmtModified(DateUtils.getTimestamp());
role.setOrgId((long)-1);
role.setUserIdCreate(StpUtil.getLoginIdAsLong());
sysRoleRepository.saveAndFlush(role);
return Result.ok("保存成功");
}
@Override
@Transactional(rollbackFor=Exception.class)
public Result delete(Long roleId) {
String nativeSql = "DELETE FROM sys_role_menu WHERE role_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, roleId);
nativeSql = "DELETE FROM sys_role WHERE role_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, roleId);
nativeSql = "DELETE FROM sys_user_role WHERE role_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, roleId);
return Result.ok("删除成功");
}
@Override
public Result getMenu(Long roleId) {
String nativeSql = "SELECT menu_id FROM sys_role_menu WHERE role_id=?";
List<String> list = dynamicQuery.query(nativeSql,new Object[]{roleId});
return Result.ok(list);
}
@Override
@Transactional(rollbackFor=Exception.class)
public Result saveMenu(SysRole role) {
Long roleId = role.getRoleId();
String nativeSql = "DELETE FROM sys_role_menu WHERE role_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, roleId);
List<Long> menuIdList = role.getMenuIdList();
if(menuIdList!=null){
menuIdList.forEach(menuId->{
SysRoleMenu roleMenu = new SysRoleMenu();
roleMenu.setMenuId(menuId);
roleMenu.setRoleId(roleId);
dynamicQuery.save(roleMenu);
});
}
return Result.ok("保存成功");
}
@Override
public Result getOrg(Long roleId) {
String nativeSql = "SELECT org_id FROM sys_role_org WHERE role_id=?";
List<String> list = dynamicQuery.query(nativeSql,new Object[]{roleId});
return Result.ok(list);
}
@Override
@Transactional(rollbackFor=Exception.class)
public Result saveOrg(SysRole role) {
Long roleId = role.getRoleId();
String nativeSql = "DELETE FROM sys_role_org WHERE role_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, roleId);
List<Long> orgIdList = role.getOrgIdList();
if(orgIdList!=null){
orgIdList.forEach(orgId->{
SysRoleOrg roleOrg = new SysRoleOrg();
roleOrg.setOrgId(orgId);
roleOrg.setRoleId(roleId);
dynamicQuery.save(roleOrg);
});
}
return Result.ok("保存成功");
}
}
package com.tools.module.sys.service.impl;
import com.tools.common.dynamicquery.DynamicQuery;
import com.tools.common.model.PageBean;
import com.tools.common.model.Result;
import com.tools.common.util.PasswordUtils;
import com.tools.common.util.PwdUtils;
import com.tools.module.business.constants.SysUserConstants;
import com.tools.module.business.utils.AssertUtils;
import com.tools.module.sys.entity.SysUser;
import com.tools.module.sys.entity.SysUserRole;
import com.tools.module.sys.repository.SysUserRepository;
import com.tools.module.sys.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class SysUserServiceImpl implements SysUserService {
@Autowired
private DynamicQuery dynamicQuery;
@Autowired
private PwdUtils pwdUtils;
@Autowired
private SysUserRepository sysUserRepository;
@Value("${pwd.decrypt.salt}")
public String salt;
@Override
@Transactional(rollbackFor = Exception.class)
public Result save(SysUser user) {
String nativeSql = "SELECT * FROM sys_user WHERE login_account=?";
SysUser sysUser = dynamicQuery.nativeQuerySingleResult(
SysUser.class,nativeSql, user.getLoginAccount());
if(sysUser!=null){
if(!sysUser.getUserId().equals(user.getUserId())){
return Result.error("用户名重复");
}
}else{
user.setPassword(PasswordUtils.encode(salt, pwdUtils.decryptPassword(user.getPassword())));
user.setStatus(SysUserConstants.Status.NORMAL);
}
sysUserRepository.saveAndFlush(user);
List<Object> roleList = user.getRoleIdList();
if(roleList!=null){
roleList.forEach(roleId->{
SysUserRole userRole = new SysUserRole();
userRole.setUserId(user.getUserId());
userRole.setRoleId(Long.parseLong(roleId.toString()));
dynamicQuery.save(userRole);
});
}
return Result.ok("保存成功");
}
@Override
public Result get(Long userId) {
/**
* 用户信息
*/
String nativeSql = "SELECT * FROM sys_user WHERE user_id=?";
SysUser user = dynamicQuery.nativeQuerySingleResult(SysUser.class,nativeSql, userId);
/**
* 机构信息
*/
nativeSql = "SELECT * FROM sys_org WHERE org_id=?";
/**
* 角色信息
*/
nativeSql = "SELECT role_id FROM sys_user_role WHERE user_id=?";
List<Object> roleIdList = dynamicQuery.query(nativeSql, userId);
user.setRoleIdList(roleIdList);
nativeSql = "SELECT role_name FROM sys_role WHERE role_id IN (SELECT role_id FROM sys_user_role WHERE user_id=?)";
List<Object> roleNameList = dynamicQuery.query(nativeSql, userId);
user.setRoleNameList(roleNameList);
return Result.ok(user);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Result delete(Long userId) {
String nativeSql = "DELETE FROM sys_user_role WHERE user_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, userId);
nativeSql = "DELETE FROM sys_user WHERE user_id=?";
dynamicQuery.nativeExecuteUpdate(nativeSql, userId);
return Result.ok("删除成功");
}
@Override
public SysUser getUser(String loginAccount) {
AssertUtils.notBlank(loginAccount);
String nativeSql = "SELECT * FROM sys_user u WHERE login_account = ?";
return dynamicQuery.nativeQuerySingleResult(SysUser.class,nativeSql, loginAccount);
}
@Override
public Result list(SysUser user) {
String nativeSql = "SELECT COUNT(*) FROM sys_user ";
nativeSql += common(user);
Long count = dynamicQuery.nativeQueryCount(nativeSql);
PageBean<SysUser> data = new PageBean<>();
if(count>0){
nativeSql = "SELECT * FROM sys_user ";
nativeSql += common(user);
nativeSql += "ORDER BY created_time desc";
// Pageable pageable = PageRequest.of(user.getPageNo(),user.getPageSize());
// List<SysUser> list = dynamicQuery.nativeQueryPagingList(SysUser.class,pageable,nativeSql);
// data = new PageBean(list,count);
}
return Result.ok(data);
}
public String common(SysUser user){
// String description = user.getDescription();
String commonSql = "";
// if(StringUtils.isNotBlank(description)){
// commonSql += "WHERE username like '"+description+"%' ";
// commonSql += "OR nickname like '"+description+"%' ";
// }
return commonSql;
}
@Override
public List<String> listUserRoles(Long userId) {
String nativeSql = "SELECT r.role_sign FROM sys_user u ";
nativeSql +=" LEFT JOIN sys_user_role ur ON u.user_id = ur.user_id";
nativeSql +=" LEFT JOIN sys_role r ON r.role_id = ur.role_id";
nativeSql +=" WHERE u.user_id = ?";
List<String> list = dynamicQuery.query(nativeSql,new Object[]{userId});
return list;
}
@Override
public List<String> listUserPerms(Long userId) {
String nativeSql = "SELECT DISTINCT m.perms FROM sys_user_role ur";
nativeSql +=" LEFT JOIN sys_role_menu rm ON ur.role_id = rm.role_id";
nativeSql +=" LEFT JOIN sys_menu m ON rm.menu_id = m.menu_id";
nativeSql +=" WHERE ur.user_id = ?";
List<String> list = dynamicQuery.query(nativeSql,new Object[]{userId});
return list;
}
@Override
@Transactional(rollbackFor=Exception.class)
public Result updatePwd(SysUser user) {
String password = PasswordUtils.encode(salt, pwdUtils.decryptPassword(user.getPassword()));
String nativeSql = "UPDATE sys_user SET password=? WHERE user_id=?";
int count = dynamicQuery.nativeExecuteUpdate(nativeSql, password,user.getUserId());
if(count==1){
return Result.ok("修改成功");
}else{
return Result.ok("修改失败");
}
}
}
package com.tools.module.sys.web;
import com.tools.common.config.AbstractController;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysConfig;
import com.tools.module.sys.service.SysConfigService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 参数设置
*
*
*/
@Api(tags ="参数设置")
@RestController
@RequestMapping("/sys/config")
public class ConfigController extends AbstractController {
@Autowired
private SysConfigService sysConfigService;
/**
* 参数列表
*/
@PostMapping("/list")
public Result list(SysConfig config){
return sysConfigService.list(config);
}
/**
* 获取
*/
@PostMapping("/get")
public Result get(Long id){
return sysConfigService.get(id);
}
/**
* 保存
*/
@PostMapping("/save")
public Result save(@RequestBody SysConfig config){
return sysConfigService.save(config);
}
/**
* 删除
*/
@PostMapping("/delete")
public Result delete(Long id){
return sysConfigService.delete(id);
}
}
package com.tools.module.sys.web;
import cn.hutool.core.io.FileUtil;
import com.tools.common.constant.SystemConstant;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysFile;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
/**
* 文件管理-在线修改代码
*
*
*/
@Api(tags ="文件管理")
@RestController
@RequestMapping(value = "/sys/file")
public class FileController {
@Value("${spring.profiles.active}")
private String active;
/**
* 列表
* @return
*/
@RequestMapping(value = "list", method = RequestMethod.POST)
public Result list() throws FileNotFoundException {
String filePath = ResourceUtils.getURL("classpath:").getPath();
List<SysFile> fileList = new ArrayList<>();
getAllFilePaths(filePath,fileList,0,"");
return Result.ok(fileList);
}
/**
* 递归获取某目录下的所有子目录以及子文件
* @param filePath
* @param filePathList
* @return
*/
private static List<SysFile> getAllFilePaths(String filePath, List<SysFile> filePathList,
Integer level,String parentPath) {
File[] files = new File(filePath).listFiles();
if (files == null) {
return filePathList;
}
for (File file : files) {
int num = filePathList.size()+1;
SysFile sysFile = new SysFile();
sysFile.setName(file.getName());
sysFile.setFileId(num);
sysFile.setParentId(level);
if (file.isDirectory()) {
sysFile.setDirectory(true);
if(level==0){
if(file.getName().equals("templates")||
file.getName().equals("static")){
filePathList.add(sysFile);
parentPath = SystemConstant.SF_FILE_SEPARATOR+file.getName();
getAllFilePaths(file.getAbsolutePath(), filePathList,num,parentPath);
num++;
}
}else{
filePathList.add(sysFile);
String subParentPath = parentPath+SystemConstant.SF_FILE_SEPARATOR+file.getName();
getAllFilePaths(file.getAbsolutePath(), filePathList,num,subParentPath);
num++;
}
} else {
if(level!=0){
sysFile.setDirectory(false);
sysFile.setParentPath(parentPath+SystemConstant.SF_FILE_SEPARATOR+file.getName());
filePathList.add(sysFile);
num++;
}
}
}
return filePathList;
}
/**
* 获取内容
* @return
*/
@RequestMapping(value = "getContent", method = RequestMethod.POST)
public Result getContent(String filePath) throws FileNotFoundException {
String path = ResourceUtils.getURL("classpath:").getPath();
String content = FileUtil.readUtf8String(path+filePath);
return Result.ok(content);
}
/**
* 保存内容
* @return
*/
@RequestMapping(value = "save", method = RequestMethod.POST)
public Result save(String filePath, String content) throws FileNotFoundException {
String path = ResourceUtils.getURL("classpath:").getPath();
/**
* 生产环境自行解除
*/
if(active.equals("prod")){
return Result.error("演示环境禁止插插插!!!");
}else{
File file = new File(path+filePath);
long lastModified = file.lastModified();
FileUtil.writeUtf8String(content,path+filePath);
file.setLastModified(lastModified);
return Result.ok();
}
}
}
package com.tools.module.sys.web;
import cn.dev33.satoken.stp.StpUtil;
import com.tools.common.model.Result;
import com.tools.common.util.PasswordUtils;
import com.tools.common.util.PwdUtils;
import com.tools.common.util.RedisUtil;
import com.tools.module.sys.entity.SysUser;
import com.tools.module.sys.service.SysUserService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 登录
*/
@Api(tags = "登录")
@Controller
@RequestMapping("/sys")
public class LoginController {
@Value("${pwd.decrypt.salt}")
public String salt;
@Autowired
private SysUserService sysUserService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private PwdUtils pwdUtils;
/**
* 登录
*/
@PostMapping("/login")
@ResponseBody
public Result login(String loginAccount, String password) {
Assert.notNull(loginAccount);
Assert.notNull(password);
try {
SysUser user = sysUserService.getUser(loginAccount);
if (user == null) {
return Result.error("账号或密码错误,请重新输入");
}
//解前端给回来的密码
String decryptPwd = PasswordUtils.encode(salt, pwdUtils.decryptPassword(password));
if (PasswordUtils.matches(salt, decryptPwd, user.getPassword())) {
StpUtil.login(user.getUserId());
} else {
return Result.error("账号或密码错误,请重新输入");
}
} catch (Exception e) {
e.printStackTrace();
return Result.error("登录失败");
}
return Result.ok("登录成功");
}
// /**
// * 注册
// *
// * @param user
// * @return
// */
// @PostMapping("/register")
// @ResponseBody
// public Result register(SysUser user) {
// System.out.println(user.getMobile());
// return Result.ok("注册成功,去登陆");
// }
/**
* 退出
*
* @return
*/
@GetMapping("/logout")
public Result logout() {
Long userId = StpUtil.getLoginIdAsLong();
redisUtil.del("authInfo:" + userId);
StpUtil.logout();
return Result.ok("退出成功");
}
}
package com.tools.module.sys.web;
import cn.dev33.satoken.stp.StpUtil;
import com.tools.common.config.AbstractController;
import com.tools.common.model.Result;
import com.tools.common.util.PasswordUtils;
import com.tools.common.util.PwdUtils;
import com.tools.module.sys.entity.SysUser;
import com.tools.module.sys.service.SysUserService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 个人设置
*/
@Api(tags = "用户管理")
@RestController
@RequestMapping("/member")
public class MemberController extends AbstractController {
@Value("${pwd.decrypt.salt}")
public String salt;
@Autowired
private SysUserService sysUserService;
@Autowired
private PwdUtils pwdUtils;
/**
* 修改密码
*/
@PostMapping("/updatePwd")
public Result updatePwd(@RequestBody SysUser user) {
SysUser entity = (SysUser) StpUtil.getLoginId();
String password = PasswordUtils.encode(salt, pwdUtils.decryptPassword(user.getPassword()));
if (entity.getPassword().equals(password)) {
user.setUserId(entity.getUserId());
return sysUserService.updatePwd(user);
} else {
return Result.error("原密码不正确");
}
}
/**
* 获取当前用户信息
*/
@PostMapping("/info")
public Result info() {
return sysUserService.get(StpUtil.getLoginIdAsLong());
}
}
package com.tools.module.sys.web;
import cn.dev33.satoken.stp.StpUtil;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysMenu;
import com.tools.module.sys.repository.SysMenuRepository;
import com.tools.module.sys.service.SysMenuService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 菜单管理
*
*
*/
@Api(tags ="菜单管理")
@RestController
@RequestMapping("/sys/menu")
public class MenuController {
@Autowired
private SysMenuService sysMenuService;
@Autowired
private SysMenuRepository sysMenuRepository;
/**
* 列表
*/
@RequestMapping("/list")
public Result list(SysMenu menu){
return sysMenuService.list(menu);
}
/**
* 树结构
*/
@RequestMapping("/select")
public Result select(Long parentId){
List<SysMenu> list = sysMenuService.select(parentId);
return Result.ok(list);
}
/**
* 保存
*/
@PostMapping("/save")
public Result save(@RequestBody SysMenu menu){
sysMenuRepository.saveAndFlush(menu);
return Result.ok("保存成功");
}
/**
* 删除
*/
@PostMapping("/delete")
public Result delete(Long menuId){
return sysMenuService.delete(menuId);
}
/**
* 获取菜单
*/
@RequestMapping("/getByUser")
public List<SysMenu> getByUser(){
return sysMenuService.getByUserId(StpUtil.getLoginIdAsLong());
}
/**
* 列表
*/
@RequestMapping("/drop")
public Result drop(Long parentId,Long menuId){
return sysMenuService.drop(parentId,menuId);
}
}
package com.tools.module.sys.web;
import com.tools.common.config.AbstractController;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysOrg;
import com.tools.module.sys.service.SysOrgService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 机构管理
*
*
*/
@Api(tags ="机构管理")
@RestController
@RequestMapping("/sys/org")
public class OrgController extends AbstractController {
@Autowired
private SysOrgService sysOrgService;
/**
* 机构列表
*/
@PostMapping("/list")
public Result list(SysOrg sysOrg){
return sysOrgService.list(sysOrg);
}
/**
* 树结构
*/
@RequestMapping("/select")
public Result select(Long parentId){
return sysOrgService.select(parentId);
}
/**
* 保存
*/
@PostMapping("/save")
public Result save(@RequestBody SysOrg org){
return sysOrgService.save(org);
}
/**
* 删除
*/
@PostMapping("/delete")
public Result delete(Long orgId){
return sysOrgService.delete(orgId);
}
}
package com.tools.module.sys.web;
import com.tools.common.config.AbstractController;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysRole;
import com.tools.module.sys.service.SysRoleService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 角色管理
*
*
*/
@Api(tags ="角色管理")
@RestController
@RequestMapping("/sys/role")
public class RoleController extends AbstractController {
@Autowired
private SysRoleService sysRoleService;
/**
* 角色列表
*/
@PostMapping("/list")
public Result list(SysRole role){
return sysRoleService.list(role);
}
/**
* 角色选择
*/
@PostMapping("/select")
public Result select(){
return sysRoleService.select();
}
/**
* 角色选择
*/
@PostMapping("/selectByUser")
public Result selectByUser(){
return sysRoleService.select();
}
/**
* 保存
*/
@PostMapping("/save")
public Result save(@RequestBody SysRole role){
return sysRoleService.save(role);
}
/**
* 删除
*/
@PostMapping("/delete")
public Result delete(Long roleId){
return sysRoleService.delete(roleId);
}
/**
* 根据角色ID获取菜单
*/
@PostMapping("/getMenu")
public Result getMenu(Long roleId){
return sysRoleService.getMenu(roleId);
}
/**
* 根据角色保存菜单
*/
@PostMapping("/saveMenu")
public Result saveMenu(@RequestBody SysRole role){
return sysRoleService.saveMenu(role);
}
/**
* 根据角色ID获取机构
*/
@PostMapping("/getOrg")
public Result getOrg(Long roleId){
return sysRoleService.getOrg(roleId);
}
/**
* 根据角色保存机构
*/
@PostMapping("/saveOrg")
public Result saveOrg(@RequestBody SysRole role){
return sysRoleService.saveOrg(role);
}
}
package com.tools.module.sys.web;
import cn.dev33.satoken.stp.StpUtil;
import com.tools.common.config.AbstractController;
import com.tools.common.model.Result;
import com.tools.module.sys.entity.SysUser;
import com.tools.module.sys.service.SysUserService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户管理
*/
@Api(tags ="用户管理")
@RestController
@RequestMapping("/sys/user")
public class UserController extends AbstractController {
@Autowired
private SysUserService sysUserService;
/**
* 用户列表
*/
@PostMapping("/list")
public Result list(SysUser user){
return sysUserService.list(user);
}
/**
* 获取
*/
@PostMapping("/get")
public Result get(Long userId){
return sysUserService.get(userId);
}
/**
* 保存
*/
@PostMapping("/save")
public Result save(@RequestBody SysUser user){
return sysUserService.save(user);
}
/**
* 删除
*/
@PostMapping("/delete")
public Result delete(Long userId){
return sysUserService.delete(userId);
}
/**
* 修改密码
*/
@PostMapping("/updatePwd")
public Result updatePwd(SysUser user){
return sysUserService.updatePwd(user);
}
/**
* 获取当前用户信息
*/
@PostMapping("/info")
public Result info(){
return sysUserService.get(StpUtil.getLoginIdAsLong());
}
/**
* 用户列表
*/
// @PostMapping("/online")
// public Result online(){
// Collection<Session> sessions = sessionDAO.getActiveSessions();
// List<Map<String, String>> list = new ArrayList<>();
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// for (Session session : sessions) {
// PrincipalCollection principalCollection = (PrincipalCollection) session
// .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
// if (principalCollection != null) {
// Map<String, String> map = new HashMap<>();
// SysUser user = (SysUser) principalCollection.getPrimaryPrincipal();
// map.put("sessionId", session.getId().toString());
// map.put("userName", user.getUsername());
// map.put("nickName", user.getNickname());
// map.put("host", session.getHost());
// map.put("lastAccessTime", sdf.format(session.getLastAccessTime()));
// list.add(map);
// }
// }
// return Result.ok(list);
// }
}
# 项目contextPath 爪哇笔记 https://blog.52itstyle.vip
server.servlet.context-path=/
# 服务端口
server.port=8080
# session最大超时时间(分钟),默认为30
server.session-timeout=60
# tomcat最大线程数,默认为200
server.tomcat.max-threads=100
# tomcat的URI编码
server.tomcat.uri-encoding=UTF-8
server.servlet.session.tracking-modes = cookie
server.servlet.session.cookie.http-only =true
spring.servlet.multipart.enabled =true
spring.servlet.multipart.max-request-size=20MB
spring.servlet.multipart.max-file-size=20MB
# 静态文件请求匹配方式
spring.mvc.static-path-pattern=/**
#spring.thymeleaf.mode=LEGACYHTML5
#spring boot 2.x 参数变化
spring.aop.proxy-target-class=true
spring.thymeleaf.mode=HTML
#注意中文乱码
table.schema = hxyj-sit
spring.datasource.url=jdbc:mysql://192.168.21.31:3306/${table.schema}?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=hxyj-admin
spring.datasource.password=f4568231aa8f
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
spring.jpa.open-in-view = false
# DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property. Default to "create-drop" when using an embedded database, "none" otherwise.
spring.jpa.hibernate.ddl-auto = update
# Hibernate 4 naming strategy fully qualified name. Not supported with Hibernate 5.
#spring.jpa.hibernate.naming.strategy = org.hibernate.cfg.ImprovedNamingStrategy
# stripped before adding them to the entity manager)
#spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
# 新特性
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.datasource.hikari.minimum-idle=3
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.max-lifetime =30000
spring.datasource.hikari.connection-test-query=SELECT 1
# Redis
# 数据库索引(默认为0)
spring.redis.database=14
# 服务器地址 变更为自己的
spring.redis.host=192.168.21.102
# 服务器连接端口
spring.redis.port=6378
# 服务器连接密码(默认为空)如果有变更为自己的
spring.redis.password=fcd20f468ca0
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=30000
file.path = E:\\file
project.url = https://blog.52itstyle.vip
# ??????
pwd.decrypt.key=MFF4C0G174948373
pwd.decrypt.iv=1946019462025011
pwd.decrypt.salt=fcC0G17468ca0
spring:
profiles:
active: dev
# Sa-Token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: x-request-token
# token有效期,单位s 默认30天, -1代表永不过期
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: 2592000
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
token-style: uuid
# 是否输出操作日志
is-log: true
#jwt密钥
jwt-secret-key: lasjdsjlkdsaljaslkaslkas
\ No newline at end of file
#镜像信息
FROM tomcat:8.5
#维护者
MAINTAINER 10000@qq.com
#将webapp下的全部删除
RUN rm -rf /usr/local/tomcat/webapps/*
#ROOT.war拷贝到/usr/local/tomcat/webapps/下
ADD ROOT.war /usr/local/tomcat/webapps/
#端口
EXPOSE 8080
#设置启动命令
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
\ No newline at end of file
hibernate.dialect.storage_engine=innodb
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan 配置文件如果发生改变,将会被重新加载 scanPeriod 检测间隔时间 BY 科帮网 小柒2012 欢迎关注博客https://blog.52itstyle.com-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>SPTools</contextName>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<!-- 普通日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/tools-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志命名:单个文件大于128MB 按照时间+自增i 生成log文件 -->
<fileNamePattern>log/SPTools-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>128MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 最大保存时间:30天-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<append>true</append>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 错误日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/tools-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志命名:单个文件大于2MB 按照时间+自增i 生成log文件 -->
<fileNamePattern>log/SPTools-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 最大保存时间:180天-->
<maxHistory>180</maxHistory>
</rollingPolicy>
<append>true</append>
<!-- 日志格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 日志级别过滤器 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 日志格式 -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!-- 屏蔽日志 -->
<logger name="springfox" level="ERROR"/>
<logger name="org.hibernate" level="ERROR"/>
<logger name="org.springframework" level="ERROR"/>
<logger name="com.zaxxer.hikari" level="ERROR"/>
<!-- additivity 避免执行2次 -->
<logger name="com.tools" level="INFO" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
</logger>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</configuration>
package com.tools;
import cn.dev33.satoken.stp.StpUtil;
import com.google.common.collect.Lists;
import com.tools.module.sys.entity.SysUser;
import com.tools.module.sys.service.SysUserService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.sql.Timestamp;
/**
* @author alex.yao
* @date 2025/4/6 10:56
*/
@SpringBootTest
public class CutControllerTest {
@Resource
private SysUserService sysUserService;
// private UserService userService;
//
// @MockBean
// private SaWrapper saWrapper; // 使用模拟的 sa 对象。
//
//
// @BeforeEach
// void setUp() {
// userService = new UserService(sysUserService, saWrapper); // 手动通过构造器注入依赖
// }
@Test
public void test_buildProduct() {
StpUtil.login(111);
SysUser sysUser = new SysUser();
sysUser.setUserId(1L);
sysUser.setLoginAccount("123123");
sysUser.setUsername("123123");
sysUser.setPassword("aaaa");
sysUser.setStatus("");
sysUser.setOrgId(0L);
sysUser.setRemark("");
sysUser.setUserIdCreate(0L);
sysUser.setCreatedTime(new Timestamp(new java.util.Date().getTime()));
sysUser.setModifiedTime(new Timestamp(new java.util.Date().getTime()));
sysUser.setIsModifyPwd((short) 0);
sysUser.setOrgName("");
sysUser.setRoleIdList(Lists.newArrayList());
sysUser.setRoleNameList(Lists.newArrayList());
sysUser.setIsDeleted("");
sysUser.setPageData(Lists.newArrayList());
sysUser.setPageSize(0);
sysUser.setTotalCount(0L);
sysUser.setPageNo(0);
sysUser.setDescription("");
sysUserService.save(sysUser);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment