init
This commit is contained in:
@@ -1,165 +1,674 @@
|
|||||||
GNU LESSER GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
This version of the GNU Lesser General Public License incorporates
|
The GNU General Public License is a free, copyleft license for
|
||||||
the terms and conditions of version 3 of the GNU General Public
|
software and other kinds of works.
|
||||||
License, supplemented by the additional permissions listed below.
|
|
||||||
|
|
||||||
0. Additional Definitions.
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
When we speak of free software, we are referring to freedom, not
|
||||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
General Public License.
|
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.
|
||||||
|
|
||||||
"The Library" refers to a covered work governed by this License,
|
To protect your rights, we need to prevent others from denying you
|
||||||
other than an Application or a Combined Work as defined below.
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
An "Application" is any work that makes use of an interface provided
|
For example, if you distribute copies of such a program, whether
|
||||||
by the Library, but which is not otherwise based on the Library.
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
Defining a subclass of a class defined by the Library is deemed a mode
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
of using an interface provided by the Library.
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
A "Combined Work" is a work produced by combining or linking an
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
Application with the Library. The particular version of the Library
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
with which the Combined Work was made is also called the "Linked
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
Version".
|
|
||||||
|
|
||||||
The "Minimal Corresponding Source" for a Combined Work means the
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
Corresponding Source for the Combined Work, excluding any source code
|
that there is no warranty for this free software. For both users' and
|
||||||
for portions of the Combined Work that, considered in isolation, are
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
based on the Application, and not on the Linked Version.
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
The "Corresponding Application Code" for a Combined Work means the
|
Some devices are designed to deny users access to install or run
|
||||||
object code and/or source code for the Application, including any data
|
modified versions of the software inside them, although the manufacturer
|
||||||
and utility programs needed for reproducing the Combined Work from the
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
Application, but excluding the System Libraries of the Combined Work.
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
1. Exception to Section 3 of the GNU GPL.
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
You may convey a covered work under sections 3 and 4 of this License
|
The precise terms and conditions for copying, distribution and
|
||||||
without being bound by section 3 of the GNU GPL.
|
modification follow.
|
||||||
|
|
||||||
2. Conveying Modified Versions.
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
If you modify a copy of the Library, and, in your modifications, a
|
0. Definitions.
|
||||||
facility refers to a function or data to be supplied by an Application
|
|
||||||
that uses the facility (other than as an argument passed when the
|
|
||||||
facility is invoked), then you may convey a copy of the modified
|
|
||||||
version:
|
|
||||||
|
|
||||||
a) under this License, provided that you make a good faith effort to
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
ensure that, in the event an Application does not supply the
|
|
||||||
function or data, the facility still operates, and performs
|
|
||||||
whatever part of its purpose remains meaningful, or
|
|
||||||
|
|
||||||
b) under the GNU GPL, with none of the additional permissions of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
this License applicable to that copy.
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
3. Object Code Incorporating Material from Library Header Files.
|
"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.
|
||||||
|
|
||||||
The object code form of an Application may incorporate material from
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
a header file that is part of the Library. You may convey such object
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
code under terms of your choice, provided that, if the incorporated
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
material is not limited to numerical parameters, data structure
|
earlier work or a work "based on" the earlier work.
|
||||||
layouts and accessors, or small macros, inline functions and templates
|
|
||||||
(ten or fewer lines in length), you do both of the following:
|
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the object code that the
|
A "covered work" means either the unmodified Program or a work based
|
||||||
Library is used in it and that the Library and its use are
|
on the Program.
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
To "propagate" a work means to do anything with it that, without
|
||||||
document.
|
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.
|
||||||
|
|
||||||
4. Combined Works.
|
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.
|
||||||
|
|
||||||
You may convey a Combined Work under terms of your choice that,
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
taken together, effectively do not restrict modification of the
|
to the extent that it includes a convenient and prominently visible
|
||||||
portions of the Library contained in the Combined Work and reverse
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
engineering for debugging such modifications, if you also do each of
|
tells the user that there is no warranty for the work (except to the
|
||||||
the following:
|
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.
|
||||||
|
|
||||||
a) Give prominent notice with each copy of the Combined Work that
|
1. Source Code.
|
||||||
the Library is used in it and that the Library and its use are
|
|
||||||
covered by this License.
|
|
||||||
|
|
||||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
The "source code" for a work means the preferred form of the work
|
||||||
document.
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
c) For a Combined Work that displays copyright notices during
|
A "Standard Interface" means an interface that either is an official
|
||||||
execution, include the copyright notice for the Library among
|
standard defined by a recognized standards body, or, in the case of
|
||||||
these notices, as well as a reference directing the user to the
|
interfaces specified for a particular programming language, one that
|
||||||
copies of the GNU GPL and this license document.
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
d) Do one of the following:
|
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.
|
||||||
|
|
||||||
0) Convey the Minimal Corresponding Source under the terms of this
|
The "Corresponding Source" for a work in object code form means all
|
||||||
License, and the Corresponding Application Code in a form
|
the source code needed to generate, install, and (for an executable
|
||||||
suitable for, and under terms that permit, the user to
|
work) run the object code and to modify the work, including scripts to
|
||||||
recombine or relink the Application with a modified version of
|
control those activities. However, it does not include the work's
|
||||||
the Linked Version to produce a modified Combined Work, in the
|
System Libraries, or general-purpose tools or generally available free
|
||||||
manner specified by section 6 of the GNU GPL for conveying
|
programs which are used unmodified in performing those activities but
|
||||||
Corresponding Source.
|
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.
|
||||||
|
|
||||||
1) Use a suitable shared library mechanism for linking with the
|
The Corresponding Source need not include anything that users
|
||||||
Library. A suitable mechanism is one that (a) uses at run time
|
can regenerate automatically from other parts of the Corresponding
|
||||||
a copy of the Library already present on the user's computer
|
Source.
|
||||||
system, and (b) will operate properly with a modified version
|
|
||||||
of the Library that is interface-compatible with the Linked
|
|
||||||
Version.
|
|
||||||
|
|
||||||
e) Provide Installation Information, but only if you would otherwise
|
The Corresponding Source for a work in source code form is that
|
||||||
be required to provide such information under section 6 of the
|
same work.
|
||||||
GNU GPL, and only to the extent that such information is
|
|
||||||
necessary to install and execute a modified version of the
|
|
||||||
Combined Work produced by recombining or relinking the
|
|
||||||
Application with a modified version of the Linked Version. (If
|
|
||||||
you use option 4d0, the Installation Information must accompany
|
|
||||||
the Minimal Corresponding Source and Corresponding Application
|
|
||||||
Code. If you use option 4d1, you must provide the Installation
|
|
||||||
Information in the manner specified by section 6 of the GNU GPL
|
|
||||||
for conveying Corresponding Source.)
|
|
||||||
|
|
||||||
5. Combined Libraries.
|
2. Basic Permissions.
|
||||||
|
|
||||||
You may place library facilities that are a work based on the
|
All rights granted under this License are granted for the term of
|
||||||
Library side by side in a single library together with other library
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
facilities that are not Applications and are not covered by this
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
License, and convey such a combined library under terms of your
|
permission to run the unmodified Program. The output from running a
|
||||||
choice, if you do both of the following:
|
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.
|
||||||
|
|
||||||
a) Accompany the combined library with a copy of the same work based
|
You may make, run and propagate covered works that you do not
|
||||||
on the Library, uncombined with any other library facilities,
|
convey, without conditions so long as your license otherwise remains
|
||||||
conveyed under the terms of this License.
|
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.
|
||||||
|
|
||||||
b) Give prominent notice with the combined library that part of it
|
Conveying under any other circumstances is permitted solely under
|
||||||
is a work based on the Library, and explaining where to find the
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
accompanying uncombined form of the same work.
|
makes it unnecessary.
|
||||||
|
|
||||||
6. Revised Versions of the GNU Lesser General Public License.
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions
|
No covered work shall be deemed part of an effective technological
|
||||||
of the GNU Lesser General Public License from time to time. Such new
|
measure under any applicable law fulfilling obligations under article
|
||||||
versions will be similar in spirit to the present version, but may
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
differ in detail to address new problems or concerns.
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Library as you received it specifies that a certain numbered version
|
Program specifies that a certain numbered version of the GNU General
|
||||||
of the GNU Lesser General Public License "or any later version"
|
Public License "or any later version" applies to it, you have the
|
||||||
applies to it, you have the option of following the terms and
|
option of following the terms and conditions either of that numbered
|
||||||
conditions either of that published version or of any later version
|
version or of any later version published by the Free Software
|
||||||
published by the Free Software Foundation. If the Library as you
|
Foundation. If the Program does not specify a version number of the
|
||||||
received it does not specify a version number of the GNU Lesser
|
GNU General Public License, you may choose any version ever published
|
||||||
General Public License, you may choose any version of the GNU Lesser
|
by the Free Software Foundation.
|
||||||
General Public License ever published by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Library as you received it specifies that a proxy can decide
|
If the Program specifies that a proxy can decide which future
|
||||||
whether future versions of the GNU Lesser General Public License shall
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
apply, that proxy's public statement of acceptance of any version is
|
public statement of acceptance of a version permanently authorizes you
|
||||||
permanent authorization for you to choose that version for the
|
to choose that version for the Program.
|
||||||
Library.
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
|
|||||||
@@ -1,2 +1,43 @@
|
|||||||
# zilean
|
# zilean 生态
|
||||||
知道我刚在时空旅行的时候见到谁了吗?多拉什么梦!
|
|
||||||
|
### 模块说明
|
||||||
|
```txt
|
||||||
|
zilean-base 用户、数据字典等常见的实体类,为独立模块
|
||||||
|
zilean-cache redis、ehcache等,为独立模块
|
||||||
|
zilean-common 各种常量、工具类等,为独立模块
|
||||||
|
zilean-mybatis jpa自动建表、mybatis二次封装,以简化简单的crud,为独立模块
|
||||||
|
zilean-test 框架单元测试,为演示模块
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用
|
||||||
|
```txt
|
||||||
|
该项目使用IDEA进行开发, 以SpringBoot为基础, 下个上SpringMvc版本的.
|
||||||
|
|
||||||
|
1、修改zilean-test中"src/main/java/resources"下的application-database.properties中的
|
||||||
|
数据库连接url "spring.datasource.url" 为你的库
|
||||||
|
|
||||||
|
2、先运行,让其自动创建基础表
|
||||||
|
src\main\java\cn\odboy\zilean\test\ZileanTestApplication.java
|
||||||
|
|
||||||
|
3、在者就能够运行测试用例查看效果了
|
||||||
|
src\test\java\cn\odboy\zilean\test\demo\SqlBuilderTest.java
|
||||||
|
|
||||||
|
4、具体如何使用作者基本做到一看就明白我就不多说了.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 联系方式
|
||||||
|
```txt
|
||||||
|
QQ:1943815081
|
||||||
|
QQ学习群: 587306042
|
||||||
|
WX:mxzf2014
|
||||||
|
```
|
||||||
|
|
||||||
|
### 贡献代码
|
||||||
|
```txt
|
||||||
|
最后如果该Demo对你有帮助不妨右上角点点Star支持一下,我更喜欢你
|
||||||
|
```
|
||||||
|
|
||||||
|
### 鸣谢
|
||||||
|
```txt
|
||||||
|
第三方jar中的各个作者,大爱.
|
||||||
|
```
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
<?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>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.1.7.RELEASE</version>
|
||||||
|
<!-- lookup parent from repository -->
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>zilean</name>
|
||||||
|
<description>Zilean生态</description>
|
||||||
|
<!-- 注意:修改jar为pom -->
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>zilean-common</module>
|
||||||
|
<module>zilean-base</module>
|
||||||
|
<module>zilean-cache</module>
|
||||||
|
<module>zilean-mybatis</module>
|
||||||
|
<module>zilean-test</module>
|
||||||
|
<!--<module>zilean-bms-service</module>-->
|
||||||
|
<!--<module>zilean-bms-web</module>-->
|
||||||
|
<!--<module>zilean-bms-web-main</module>-->
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<!-- 跳过测试阶段 -->
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
<!-- 公共配置块 End -->
|
||||||
|
<springboot.version>2.1.6.RELEASE</springboot.version>
|
||||||
|
<springboot.starter.version>2.1.0</springboot.starter.version>
|
||||||
|
<mysql.connector.version>5.1.38</mysql.connector.version>
|
||||||
|
<lombok.version>1.18.8</lombok.version>
|
||||||
|
<hutool.version>4.5.16</hutool.version>
|
||||||
|
<fastjson.version>1.2.58</fastjson.version>
|
||||||
|
<springboot.druid>1.1.10</springboot.druid>
|
||||||
|
<redis.client.version>2.9.0</redis.client.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!--thymeleaf 依赖,使用thymeleaf标签-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
<!-- 移除嵌入式tomcat插件 -->
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--ServletApi 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!--分布式spring-session 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.session</groupId>
|
||||||
|
<artifactId>spring-session-data-redis</artifactId>
|
||||||
|
<version>2.1.8.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<!--mail 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--mysql 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>${mysql.connector.version}</version>
|
||||||
|
<!--<scope>runtime</scope>-->
|
||||||
|
</dependency>
|
||||||
|
<!--config file 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<!--junit 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!--其他依赖-->
|
||||||
|
<!-- 数据库连接池 -->
|
||||||
|
<!-- 此处的引用有两种 -->
|
||||||
|
<!-- 一种是直接引用druid包,另一种是引用starter方式 -->
|
||||||
|
<!-- 在此处我引用的是start包,为什么呢,因为方便呀... -->
|
||||||
|
<!-- 注:如果没有该包,application.properties/application.yml 中将不会出现关于druid的提示 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
|
<version>${springboot.druid}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- 注意: 我不需要这个是个可运行的项目,所以修改原来的打包方式为maven打包方式 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
java -jar mybatis-generator-core-1.3.7.jar -configfile generatorConfig.xml
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE generatorConfiguration
|
||||||
|
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
|
||||||
|
<generatorConfiguration>
|
||||||
|
<!--数据库驱动 -->
|
||||||
|
<classPathEntry location="mysql-connector-java-5.1.38.jar"/>
|
||||||
|
<context id="DB2Tables" targetRuntime="MyBatis3">
|
||||||
|
<!-- 生成的Java文件的编码 -->
|
||||||
|
<property name="javaFileEncoding" value="UTF-8"/>
|
||||||
|
<!-- 格式化java代码 -->
|
||||||
|
<property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
|
||||||
|
<!-- 格式化XML代码 -->
|
||||||
|
<property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>
|
||||||
|
<!-- JavaBean 实现 序列化 接口 -->
|
||||||
|
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
|
||||||
|
<!-- 以上为插件配置信息 -->
|
||||||
|
<!-- 是否去除自动生成的注释 true:是;false:否 -->
|
||||||
|
<commentGenerator>
|
||||||
|
<!--生成的注释包含时间戳-->
|
||||||
|
<property name="suppressDate" value="true"/>
|
||||||
|
<property name="suppressAllComments" value="true"/>
|
||||||
|
</commentGenerator>
|
||||||
|
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
|
||||||
|
<jdbcConnection
|
||||||
|
driverClass="com.mysql.jdbc.Driver"
|
||||||
|
connectionURL="jdbc:Mysql://47.103.14.6:3306/zilean-bms?characterEncoding=utf8"
|
||||||
|
userId="root"
|
||||||
|
password="$oDboy*#sDa22#11">
|
||||||
|
<property name="useInformationSchema" value="true"/>
|
||||||
|
</jdbcConnection>
|
||||||
|
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal -->
|
||||||
|
<javaTypeResolver>
|
||||||
|
<property name="forceBigDecimals" value="false"/>
|
||||||
|
</javaTypeResolver>
|
||||||
|
<!--生成Model类存放位置 -->
|
||||||
|
<!-- targetProject:生成PO类的位置 -->
|
||||||
|
<javaModelGenerator targetPackage="cn.odboy.zilean.core.entity" targetProject="src/main/java">
|
||||||
|
<!-- enableSubPackages:是否让schema作为包的后缀 -->
|
||||||
|
<property name="enableSubPackages" value="true"/>
|
||||||
|
<!-- 从数据库返回的值被清理前后的空格 -->
|
||||||
|
<property name="trimStrings" value="true"/>
|
||||||
|
</javaModelGenerator>
|
||||||
|
<!--生成映射文件存放位置 -->
|
||||||
|
<sqlMapGenerator targetPackage="cn.odboy.zilean.dao" targetProject="src/main/java">
|
||||||
|
<!-- enableSubPackages:是否让schema作为包的后缀 -->
|
||||||
|
<property name="enableSubPackages" value="true"/>
|
||||||
|
</sqlMapGenerator>
|
||||||
|
<!--生成Dao类存放位置 -->
|
||||||
|
<!--
|
||||||
|
ANNOTATEDMAPPER: 生成java类文件,基于注解的Mapper接口,不会有对应的XML映射文件
|
||||||
|
MIXEDMAPPER:XML和注解的混合形式
|
||||||
|
XMLMAPPER:所有的方法都在XML中,接口调用依赖XML文件
|
||||||
|
-->
|
||||||
|
<javaClientGenerator type="XMLMAPPER" targetPackage="cn.odboy.zilean.dao" targetProject="src/main/java">
|
||||||
|
<property name="enableSubPackages" value="true"/>
|
||||||
|
</javaClientGenerator>
|
||||||
|
<!-- tableName:用于自动生成代码的数据库表;domainObjectName:对应于数据库表的javaBean类名 -->
|
||||||
|
<table
|
||||||
|
schema=""
|
||||||
|
tableName="t_dict_data"
|
||||||
|
domainObjectName="DictData"
|
||||||
|
enableCountByExample="false"
|
||||||
|
enableUpdateByExample="false"
|
||||||
|
enableDeleteByExample="false"
|
||||||
|
enableSelectByExample="false"
|
||||||
|
selectByExampleQueryId="false">
|
||||||
|
</table>
|
||||||
|
<table
|
||||||
|
schema=""
|
||||||
|
tableName="t_dict_Type"
|
||||||
|
domainObjectName="DictType"
|
||||||
|
enableCountByExample="false"
|
||||||
|
enableUpdateByExample="false"
|
||||||
|
enableDeleteByExample="false"
|
||||||
|
enableSelectByExample="false"
|
||||||
|
selectByExampleQueryId="false">
|
||||||
|
</table>
|
||||||
|
<table
|
||||||
|
schema=""
|
||||||
|
tableName="t_operation_log"
|
||||||
|
domainObjectName="OperationLog"
|
||||||
|
enableCountByExample="false"
|
||||||
|
enableUpdateByExample="false"
|
||||||
|
enableDeleteByExample="false"
|
||||||
|
enableSelectByExample="false"
|
||||||
|
selectByExampleQueryId="false">
|
||||||
|
</table>
|
||||||
|
<table
|
||||||
|
schema=""
|
||||||
|
tableName="t_permission"
|
||||||
|
domainObjectName="Permission"
|
||||||
|
enableCountByExample="false"
|
||||||
|
enableUpdateByExample="false"
|
||||||
|
enableDeleteByExample="false"
|
||||||
|
enableSelectByExample="false"
|
||||||
|
selectByExampleQueryId="false">
|
||||||
|
</table>
|
||||||
|
<table
|
||||||
|
schema=""
|
||||||
|
tableName="t_role"
|
||||||
|
domainObjectName="Role"
|
||||||
|
enableCountByExample="false"
|
||||||
|
enableUpdateByExample="false"
|
||||||
|
enableDeleteByExample="false"
|
||||||
|
enableSelectByExample="false"
|
||||||
|
selectByExampleQueryId="false">
|
||||||
|
</table>
|
||||||
|
<table
|
||||||
|
schema=""
|
||||||
|
tableName="t_role_permission"
|
||||||
|
domainObjectName="RolePermission"
|
||||||
|
enableCountByExample="false"
|
||||||
|
enableUpdateByExample="false"
|
||||||
|
enableDeleteByExample="false"
|
||||||
|
enableSelectByExample="false"
|
||||||
|
selectByExampleQueryId="false">
|
||||||
|
</table>
|
||||||
|
<table
|
||||||
|
schema=""
|
||||||
|
tableName="t_user"
|
||||||
|
domainObjectName="User"
|
||||||
|
enableCountByExample="false"
|
||||||
|
enableUpdateByExample="false"
|
||||||
|
enableDeleteByExample="false"
|
||||||
|
enableSelectByExample="false"
|
||||||
|
selectByExampleQueryId="false">
|
||||||
|
</table>
|
||||||
|
</context>
|
||||||
|
</generatorConfiguration>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<!-- maven可以继承父项目中的参数,所以可以删除子模块中相同定义 -->
|
||||||
|
<artifactId>zilean-base</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>zilean-base</name>
|
||||||
|
<description>基础模块</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<!-- 向上查看父节点依赖 -->
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- maven可以继承父项目中的依赖,所以可以删除子模块中相同定义 -->
|
||||||
|
<!--lombok 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<!--jpa 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 优雅的将DO转换成VO -->
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-jdk8 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-jdk8</artifactId>
|
||||||
|
<version>1.0.0.Final</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-processor</artifactId>
|
||||||
|
<version>1.0.0.Final</version>
|
||||||
|
</dependency>
|
||||||
|
<!--zilean-mybatis 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean-mybatis</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<!-- 如果其他包需要依赖这个模块那么就不要加这个 -->
|
||||||
|
<!--<build>-->
|
||||||
|
<!--<plugins>-->
|
||||||
|
<!--<plugin>-->
|
||||||
|
<!--<groupId>org.springframework.boot</groupId>-->
|
||||||
|
<!--<artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||||
|
<!--</plugin>-->
|
||||||
|
<!--</plugins>-->
|
||||||
|
<!--</build>-->
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package cn.odboy.zilean.biz;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.bo.UserBo;
|
||||||
|
import cn.odboy.zilean.common.HttpResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 用户相关业务
|
||||||
|
* @time: 2019/8/8 10:56
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public interface IUserBiz {
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
*
|
||||||
|
* @param username 账号
|
||||||
|
* @param password 密码
|
||||||
|
* @return HttpResult
|
||||||
|
*/
|
||||||
|
HttpResult login(String username, String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户退登
|
||||||
|
*
|
||||||
|
* @param username 账号
|
||||||
|
* @param token 登录成功后返回的token值
|
||||||
|
* @return HttpResult
|
||||||
|
*/
|
||||||
|
HttpResult logout(String username, String token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户菜单权限
|
||||||
|
*
|
||||||
|
* @param userId 用户UD
|
||||||
|
* @return HttpResult
|
||||||
|
*/
|
||||||
|
HttpResult getUserPermission(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存user登录信息,返回token
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
*/
|
||||||
|
String generateJwtToken(String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上次token生成时的salt值和登录用户信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @return UserBo
|
||||||
|
*/
|
||||||
|
UserBo getJwtTokenInfo(String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除token信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
*/
|
||||||
|
void cleanLoginInfo(String username);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据库中保存的用户信息,主要是加密后的密码
|
||||||
|
*
|
||||||
|
* @param userName 用户名
|
||||||
|
* @return UserBo
|
||||||
|
*/
|
||||||
|
UserBo getUserInfo(String userName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户角色列表,强烈建议从缓存中获取
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return List<String>
|
||||||
|
*/
|
||||||
|
String getUserRole(Long userId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package cn.odboy.zilean.biz.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.odboy.zilean.biz.IUserBiz;
|
||||||
|
import cn.odboy.zilean.bo.UserBo;
|
||||||
|
import cn.odboy.zilean.common.HttpResult;
|
||||||
|
import cn.odboy.zilean.common.constant.RedisKeyConsts;
|
||||||
|
import cn.odboy.zilean.dao.IRoleDao;
|
||||||
|
import cn.odboy.zilean.dao.IUserDao;
|
||||||
|
import cn.odboy.zilean.entity.Role;
|
||||||
|
import cn.odboy.zilean.entity.User;
|
||||||
|
import cn.odboy.zilean.map.UserBoMapper;
|
||||||
|
import cn.odboy.zilean.mybatis.core.EntityPropNav;
|
||||||
|
import cn.odboy.zilean.service.UserService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 用户相关业务实现类
|
||||||
|
* @time: 2019/8/8 11:05
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Service("userBiz")
|
||||||
|
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
|
||||||
|
public class UserBizImpl implements IUserBiz {
|
||||||
|
/**
|
||||||
|
* 自动注入: 用户DAO
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
private IUserDao userDao;
|
||||||
|
/**
|
||||||
|
* 自动注入: 权限DAO
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
private IRoleDao roleDao;
|
||||||
|
/**
|
||||||
|
* 自动注入: 用户Service
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
/**
|
||||||
|
* 自动注入: Redis缓存
|
||||||
|
*/
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<Object, Object> redisTemplate;
|
||||||
|
/**
|
||||||
|
* 自动注入: UserDto转换器
|
||||||
|
*/
|
||||||
|
@Resource
|
||||||
|
private UserBoMapper userBoMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
*
|
||||||
|
* @param username 账号
|
||||||
|
* @param password 密码
|
||||||
|
* @return HttpResult
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public HttpResult login(String username, String password) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户退登
|
||||||
|
*
|
||||||
|
* @param username 账号
|
||||||
|
* @param token 登录成功后返回的token值
|
||||||
|
* @return HttpResult
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public HttpResult logout(String username, String token) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户菜单权限
|
||||||
|
*
|
||||||
|
* @param userId 用户UD
|
||||||
|
* @return HttpResult
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public HttpResult getUserPermission(Long userId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存user登录信息,返回token
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String generateJwtToken(String username) {
|
||||||
|
String salt = "123456";
|
||||||
|
// 将salt保存到缓存中
|
||||||
|
redisTemplate.opsForValue().set(StrUtil.format(RedisKeyConsts.TOKEN, username), salt, 3600, TimeUnit.SECONDS);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上次token生成时的salt值和登录用户信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @return UserBo
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public UserBo getJwtTokenInfo(String username) {
|
||||||
|
// 从缓存中取出token生成时用的salt
|
||||||
|
String salt = String.valueOf(redisTemplate.opsForValue().get(StrUtil.format(RedisKeyConsts.TOKEN, username)));
|
||||||
|
UserBo user = getUserInfo(username);
|
||||||
|
user.setSalt(salt);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除token信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void cleanLoginInfo(String username) {
|
||||||
|
// 删除缓存中保存的salt
|
||||||
|
redisTemplate.delete(StrUtil.format(RedisKeyConsts.TOKEN, username));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据库中保存的用户信息,主要是加密后的密码
|
||||||
|
*
|
||||||
|
* @param userName 用户名
|
||||||
|
* @return UserBo
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public UserBo getUserInfo(String userName) {
|
||||||
|
List<User> users = userDao.selectByNav(EntityPropNav.build("username", userName));
|
||||||
|
if (CollUtil.isNotEmpty(users)) {
|
||||||
|
return userBoMapper.userToBo(users.get(0));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户角色,强烈建议从缓存中获取
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getUserRole(Long userId) {
|
||||||
|
List<User> users = userDao.selectByNav(EntityPropNav.build("id", userId));
|
||||||
|
if (CollUtil.isNotEmpty(users)) {
|
||||||
|
Long roleId = users.get(0).getRoleId();
|
||||||
|
Role role = roleDao.selectOneById(roleId);
|
||||||
|
return role.getValue();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package cn.odboy.zilean.bo;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 权限BO
|
||||||
|
* @time: 2019/8/8 3:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public class PermissionBo implements Serializable {
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package cn.odboy.zilean.bo;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 用户Bo
|
||||||
|
* @time: 2019/8/9 6:19
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class UserBo implements Serializable {
|
||||||
|
private Long id;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private String encryptPwd;
|
||||||
|
private String salt;
|
||||||
|
private List<String> roles;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package cn.odboy.zilean.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.odboy.zilean.entity.DictData;
|
||||||
|
import cn.odboy.zilean.mybatis.core.BaseDao;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 字典数据DAO
|
||||||
|
* @time: 2019/8/8 10:35
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IDictDataDao extends BaseDao<DictData> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package cn.odboy.zilean.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.odboy.zilean.entity.DictType;
|
||||||
|
import cn.odboy.zilean.mybatis.core.BaseDao;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 字典类型DAO
|
||||||
|
* @time: 2019/8/8 10:36
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IDictTypeDao extends BaseDao<DictType> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package cn.odboy.zilean.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.odboy.zilean.entity.OperationLog;
|
||||||
|
import cn.odboy.zilean.mybatis.core.BaseDao;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 操作日志DAO
|
||||||
|
* @time: 2019/8/8 10:37
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IOperationLogDao extends BaseDao<OperationLog> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package cn.odboy.zilean.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.odboy.zilean.entity.Permission;
|
||||||
|
import cn.odboy.zilean.mybatis.core.BaseDao;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 菜单权限DAO
|
||||||
|
* @time: 2019/8/8 10:37
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IPermissionDao extends BaseDao<Permission> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package cn.odboy.zilean.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.odboy.zilean.entity.Role;
|
||||||
|
import cn.odboy.zilean.mybatis.core.BaseDao;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 角色DAO
|
||||||
|
* @time: 2019/8/8 10:37
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IRoleDao extends BaseDao<Role> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package cn.odboy.zilean.dao;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.odboy.zilean.entity.RolePermission;
|
||||||
|
import cn.odboy.zilean.mybatis.core.BaseDao;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 角色菜单权限关联DAO
|
||||||
|
* @time: 2019/8/8 10:37
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IRolePermissionDao extends BaseDao<RolePermission> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package cn.odboy.zilean.dao;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.entity.User;
|
||||||
|
import cn.odboy.zilean.mybatis.core.BaseDao;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 用户DAO
|
||||||
|
* @time: 2019/8/8 10:38
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public interface IUserDao extends BaseDao<User> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package cn.odboy.zilean.entity;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 字典数据
|
||||||
|
* @time: 2019/8/3 7:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "dict_data")
|
||||||
|
public class DictData extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 类型简称(eg. PayMode)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) NOT NULL COMMENT '类型简称(eg. PayMode)'")
|
||||||
|
private String abbr;
|
||||||
|
/**
|
||||||
|
* 数据标题(eg. 支付宝)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) NOT NULL COMMENT '数据标题(eg. 支付宝)'")
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* 数据内容(eg. alipay)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) NOT NULL COMMENT '数据内容(eg. alipay)'")
|
||||||
|
private String value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package cn.odboy.zilean.entity;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 字典类型
|
||||||
|
* @time: 2019/8/3 7:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "dict_type")
|
||||||
|
public class DictType extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 类型名称(eg. 付款方式)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) UNIQUE NOT NULL COMMENT '类型名称(eg. 付款方式)'")
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 类型简称(eg. PayMode)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) UNIQUE NOT NULL COMMENT '类型简称(eg. PayMode)'")
|
||||||
|
private String abbr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package cn.odboy.zilean.entity;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 操作日志
|
||||||
|
* @time: 2019/8/8 2:42
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "operation_log")
|
||||||
|
public class OperationLog extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 操作类型
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "TINYINT(1) NOT NULL COMMENT '操作类型'")
|
||||||
|
private Byte opType;
|
||||||
|
/**
|
||||||
|
* 操作内容
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(255) NOT NULL COMMENT '操作内容'")
|
||||||
|
private String content;
|
||||||
|
/**
|
||||||
|
* 操作人
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "BIGINT(20) NOT NULL COMMENT '操作人'")
|
||||||
|
private Long userId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package cn.odboy.zilean.entity;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 权限(可访问菜单)
|
||||||
|
* @time: 2019/8/3 7:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
* <p>
|
||||||
|
* 字段 type 是标示是菜单资源还是普通资源
|
||||||
|
* 菜单资源的意义就是导航菜单,会显示到左侧导航,
|
||||||
|
* 普通资源就是菜单内的按钮或者提交路径,
|
||||||
|
* 这个时候 pid的意义就比较重要了,pid就是上级菜单的id,
|
||||||
|
* 对于页面普通资源来说,就是相应的导航菜单的url
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "permission")
|
||||||
|
public class Permission extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 父ID
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "BIGINT(20) COMMENT '父ID'")
|
||||||
|
private Long pid;
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) NOT NULL COMMENT '标题'")
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* 权限编码(eg. user:list)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) COMMENT '权限编码(eg. user:list)'")
|
||||||
|
private String code;
|
||||||
|
/**
|
||||||
|
* 页面URL
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(255) COMMENT '页面URL'")
|
||||||
|
private String pageUrl;
|
||||||
|
/**
|
||||||
|
* 资源类型
|
||||||
|
* 0、菜单资源 1、普通资源
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "TINYINT(1) NOT NULL COMMENT '0、菜单资源 1、普通资源'")
|
||||||
|
private Byte type;
|
||||||
|
/**
|
||||||
|
* 菜单图标
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(255) COMMENT '菜单图标'")
|
||||||
|
private String ico;
|
||||||
|
/**
|
||||||
|
* 资源是否可用
|
||||||
|
* 0、禁用 1、启用
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "TINYINT(1) NOT NULL COMMENT '资源是否可用'")
|
||||||
|
private Byte status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package cn.odboy.zilean.entity;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 角色
|
||||||
|
* @time: 2019/8/3 7:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "role")
|
||||||
|
public class Role extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 角色名称(eg. 超级管理员)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) NOT NULL COMMENT '角色名称(eg. 超级管理员)'")
|
||||||
|
private String abbr;
|
||||||
|
/**
|
||||||
|
* 角色简称(eg. admin)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(50) NOT NULL COMMENT '角色简称(eg. admin)'")
|
||||||
|
private String title;
|
||||||
|
/**
|
||||||
|
* 角色描述(eg. 拥有至高权限)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(255) COMMENT '角色描述(eg. 拥有至高权限)'")
|
||||||
|
private String value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package cn.odboy.zilean.entity;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 角色权限关联关系
|
||||||
|
* @time: 2019/8/3 7:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "role_permission")
|
||||||
|
public class RolePermission extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 角色Id
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "BIGINT(20) NOT NULL COMMENT '角色Id'")
|
||||||
|
private Long roleId;
|
||||||
|
/**
|
||||||
|
* 权限Id
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "BIGINT(20) NOT NULL COMMENT '权限Id'")
|
||||||
|
private Long permissionId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package cn.odboy.zilean.entity;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 用户
|
||||||
|
* @time: 2019/8/3 7:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = "user")
|
||||||
|
public class User extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 邮箱账号
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(20) UNIQUE NOT NULL COMMENT '邮箱账号'")
|
||||||
|
private String username;
|
||||||
|
/**
|
||||||
|
* 密码(加密)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(18) NOT NULL COMMENT '密码(加密)'")
|
||||||
|
private String userpwd;
|
||||||
|
/**
|
||||||
|
* 头像(JPG,小于500k,70*100px)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(255) COMMENT '头像(JPG,小于500k,70*100px)'")
|
||||||
|
private String logoUrl;
|
||||||
|
/**
|
||||||
|
* 性别(0男、1女)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "TINYINT(1) COMMENT '性别(0男、1女)'")
|
||||||
|
private Byte sex;
|
||||||
|
/**
|
||||||
|
* 真实姓名
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(8) COMMENT '真实姓名'")
|
||||||
|
private String realName;
|
||||||
|
/**
|
||||||
|
* 生日
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "DATE COMMENT '生日'")
|
||||||
|
private Date birth;
|
||||||
|
/**
|
||||||
|
* 联系方式
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(11) COMMENT '联系方式'")
|
||||||
|
private String phoneNum;
|
||||||
|
/**
|
||||||
|
* 参加工作时间
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "DATE COMMENT '参加工作时间'")
|
||||||
|
private Date joinWorkDate;
|
||||||
|
/**
|
||||||
|
* 职业
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(100) COMMENT '职业'")
|
||||||
|
private String maritalStatus;
|
||||||
|
/**
|
||||||
|
* 家乡
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(255) COMMENT '家乡'")
|
||||||
|
private String hometown;
|
||||||
|
/**
|
||||||
|
* 背景音乐
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(255) COMMENT '背景音乐'")
|
||||||
|
private String bgmUrl;
|
||||||
|
/**
|
||||||
|
* 签名(座右铭)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(100) COMMENT '签名(座右铭)'")
|
||||||
|
private String autograph;
|
||||||
|
/**
|
||||||
|
* 上一次登录时间
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "DATETIME COMMENT '上一次登录时间'")
|
||||||
|
private Date lastLoginTime;
|
||||||
|
/**
|
||||||
|
* 角色ID
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "BIGINT(20) COMMENT '角色ID'")
|
||||||
|
private Long roleId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package cn.odboy.zilean.map;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.bo.PermissionBo;
|
||||||
|
import cn.odboy.zilean.entity.Permission;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO PermissionBo转换器
|
||||||
|
* @time: 2019/8/8 3:48
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = "spring")
|
||||||
|
public interface PermissionBoMapper {
|
||||||
|
/**
|
||||||
|
* PermissionBo 转 Permission
|
||||||
|
*
|
||||||
|
* @param permissionBo PermissionBo
|
||||||
|
* @return Permission
|
||||||
|
*/
|
||||||
|
Permission boToPermission(PermissionBo permissionBo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission 转 PermissionBo
|
||||||
|
*
|
||||||
|
* @param permission Permission
|
||||||
|
* @return PermissionBo
|
||||||
|
*/
|
||||||
|
PermissionBo permissionToBo(Permission permission);
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package cn.odboy.zilean.map;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.bo.UserBo;
|
||||||
|
import cn.odboy.zilean.entity.User;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO UserBo转换器
|
||||||
|
* @time: 2019/8/8 3:48
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Mapper(componentModel = "spring")
|
||||||
|
public interface UserBoMapper {
|
||||||
|
/**
|
||||||
|
* UserBo 转 User
|
||||||
|
*
|
||||||
|
* @param userBo UserBo
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
User boToUser(UserBo userBo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User 转 UserBo
|
||||||
|
*
|
||||||
|
* @param user User
|
||||||
|
* @return UserBo
|
||||||
|
*/
|
||||||
|
UserBo userToBo(User user);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package cn.odboy.zilean.service;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.dao.IUserDao;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 用户Service
|
||||||
|
* @time: 2019/8/8 10:48
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class UserService {
|
||||||
|
/**
|
||||||
|
* 自动注入: 用户DAO
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
private IUserDao userDao;
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<!-- maven可以继承父项目中的参数,所以可以删除子模块中相同定义 -->
|
||||||
|
<artifactId>zilean-cache</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>zilean-cache</name>
|
||||||
|
<description>缓存模块</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<!-- lookup parent from repository -->
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- maven可以继承父项目中的依赖,所以可以删除子模块中相同定义 -->
|
||||||
|
<!--lombok 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<!-- FastJson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>${fastjson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- HuTool工具箱-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--redis 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--redis-client 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>redis.clients</groupId>
|
||||||
|
<artifactId>jedis</artifactId>
|
||||||
|
<version>${redis.client.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Spring Boot 缓存支持启动器 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-cache</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Ehcache 坐标 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sf.ehcache</groupId>
|
||||||
|
<artifactId>ehcache</artifactId>
|
||||||
|
<version>2.10.6</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<!-- 如果其他包需要依赖这个模块那么就不要加这个 -->
|
||||||
|
<!--<build>-->
|
||||||
|
<!--<plugins>-->
|
||||||
|
<!--<plugin>-->
|
||||||
|
<!--<groupId>org.springframework.boot</groupId>-->
|
||||||
|
<!--<artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||||
|
<!--</plugin>-->
|
||||||
|
<!--</plugins>-->
|
||||||
|
<!--</build>-->
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package cn.odboy.zilean.cache;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
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.RedisCacheManager;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisOperations;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO Redis配置.自定义redis序列化
|
||||||
|
* @time: 2019/8/8 10:39
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@EnableCaching
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnClass(RedisOperations.class)
|
||||||
|
@EnableConfigurationProperties(RedisProperties.class)
|
||||||
|
public class RedisConfig extends CachingConfigurerSupport {
|
||||||
|
/**
|
||||||
|
* Redis工厂
|
||||||
|
*
|
||||||
|
* @param factory RedisConnectionFactory
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean(name = "redisTemplate")
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@ConditionalOnMissingBean(name = "redisTemplate")
|
||||||
|
public RedisTemplate<Object, Object> redisTemplate(
|
||||||
|
RedisConnectionFactory factory) {
|
||||||
|
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||||||
|
// 使用fastjson序列化
|
||||||
|
RedisFastJsonSerializerConfig fastJsonRedisSerializerConfig =
|
||||||
|
new RedisFastJsonSerializerConfig(Object.class);
|
||||||
|
// value值的序列化采用fastJsonRedisSerializer
|
||||||
|
template.setValueSerializer(fastJsonRedisSerializerConfig);
|
||||||
|
template.setHashValueSerializer(fastJsonRedisSerializerConfig);
|
||||||
|
// key的序列化采用StringRedisSerializer
|
||||||
|
template.setKeySerializer(new StringRedisSerializer());
|
||||||
|
template.setHashKeySerializer(new StringRedisSerializer());
|
||||||
|
template.setConnectionFactory(factory);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存管理器
|
||||||
|
*
|
||||||
|
* @param factory RedisConnectionFactory
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public CacheManager cacheManager(RedisConnectionFactory factory) {
|
||||||
|
RedisCacheManager.RedisCacheManagerBuilder builder =
|
||||||
|
RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(factory);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
package cn.odboy.zilean.cache;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.parser.ParserConfig;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
|
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.SerializationException;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO Redis序列化器之Fastjson版
|
||||||
|
* @time: 2019/8/8 10:39
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public class RedisFastJsonSerializerConfig<T> implements RedisSerializer<T> {
|
||||||
|
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||||
|
private Class<T> clazz;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 解决fastJson autoType is not support错误
|
||||||
|
// ParserConfig.getGlobalInstance().addAccept("cn.odboy.zilean.base");
|
||||||
|
// ParserConfig.getGlobalInstance().addAccept("cn.odboy.zilean.bms.cn.odboy.zilean.entity");
|
||||||
|
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RedisFastJsonSerializerConfig(Class<T> clazz) {
|
||||||
|
super();
|
||||||
|
this.clazz = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(T t) throws SerializationException {
|
||||||
|
if (null == t) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T deserialize(byte[] bytes) throws SerializationException {
|
||||||
|
if (null == bytes || bytes.length <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String str = new String(bytes, DEFAULT_CHARSET);
|
||||||
|
return JSON.parseObject(str, clazz);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
|
||||||
|
<!--
|
||||||
|
这个是磁盘存储路径,当内存缓存满了的时候,就会往这里面放
|
||||||
|
java.io.tmdir是操作系统缓存的临时目录,不同操作系统缓存目录不一样
|
||||||
|
-->
|
||||||
|
<diskStore path="java.io.tmpdir"/>
|
||||||
|
|
||||||
|
<!-- defaultCache:echcache的默认缓存策略 -->
|
||||||
|
<defaultCache
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="120"
|
||||||
|
timeToLiveSeconds="120"
|
||||||
|
maxElementsOnDisk="10000000"
|
||||||
|
diskExpiryThreadIntervalSeconds="120"
|
||||||
|
memoryStoreEvictionPolicy="LRU">
|
||||||
|
<persistence strategy="localTempSwap"/>
|
||||||
|
</defaultCache>
|
||||||
|
<cache name="userCache"
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="120"
|
||||||
|
timeToLiveSeconds="120"
|
||||||
|
maxElementsOnDisk="10000000"
|
||||||
|
diskExpiryThreadIntervalSeconds="120"
|
||||||
|
memoryStoreEvictionPolicy="LRU">
|
||||||
|
<persistence strategy="localTempSwap"/>
|
||||||
|
</cache>
|
||||||
|
</ehcache>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<!-- maven可以继承父项目中的参数,所以可以删除子模块中相同定义 -->
|
||||||
|
<artifactId>zilean-common</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>zilean-common</name>
|
||||||
|
<description>独立常量模块</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<!-- lookup parent from repository -->
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- maven可以继承父项目中的依赖,所以可以删除子模块中相同定义 -->
|
||||||
|
<!--lombok 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<!-- HuTool工具箱-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<!-- 如果其他包需要依赖这个模块那么就不要加这个 -->
|
||||||
|
<!--<build>-->
|
||||||
|
<!--<plugins>-->
|
||||||
|
<!--<plugin>-->
|
||||||
|
<!--<groupId>org.springframework.boot</groupId>-->
|
||||||
|
<!--<artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||||
|
<!--</plugin>-->
|
||||||
|
<!--</plugins>-->
|
||||||
|
<!--</build>-->
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package cn.odboy.zilean.common;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.common.constant.GlobalConsts;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO Ajax请求返回对象
|
||||||
|
* @time: 2019/8/7 8:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class HttpResult implements Serializable {
|
||||||
|
/**
|
||||||
|
* 业务处理成功与否
|
||||||
|
*/
|
||||||
|
private boolean success;
|
||||||
|
/**
|
||||||
|
* 提示信息
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
/**
|
||||||
|
* 数据体
|
||||||
|
*/
|
||||||
|
private Map<String, Object> body = new HashMap<>(GlobalConsts.DEFAULT_COLLECTIONS_SIZE);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.odboy.zilean.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 田俊
|
||||||
|
* @version 1.0.0
|
||||||
|
* @name: RegexConsts <br/>
|
||||||
|
* @description: TODO 常量:数据状态 <br/>
|
||||||
|
* @date: 2019/04/2019/4/1 <br/>
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
public final class DataStatusConsts {
|
||||||
|
/**
|
||||||
|
* 无效数据
|
||||||
|
*/
|
||||||
|
public static final byte DELETE = 1;
|
||||||
|
/**
|
||||||
|
* 有效数据
|
||||||
|
*/
|
||||||
|
public static final byte UNDELETE = 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package cn.odboy.zilean.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 田俊
|
||||||
|
* @version 1.0.0
|
||||||
|
* @name: RegexConsts <br/>
|
||||||
|
* @description: TODO 常量:全局参数 <br/>
|
||||||
|
* @date: 2019/04/2019/4/1 <br/>
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
public final class GlobalConsts {
|
||||||
|
/**
|
||||||
|
* 默认集合对象大小
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_COLLECTIONS_SIZE = 3;
|
||||||
|
/**
|
||||||
|
* OPTION请求
|
||||||
|
*/
|
||||||
|
public static final String HTTP_OPTIONS = "OPTIONS";
|
||||||
|
/**
|
||||||
|
* page
|
||||||
|
*/
|
||||||
|
public static final String ATTR_PAGE = "page";
|
||||||
|
/**
|
||||||
|
* 默认的盐
|
||||||
|
*/
|
||||||
|
public static final String SALT = "Zilean201908010000";
|
||||||
|
|
||||||
|
public static final String MSG_USERNAME_OR_PASSWORD_ERROR = "用户名或者密码错误";
|
||||||
|
public static final String MSG_TOKEN_EXPIRE_RELOGIN = "Token过期,请重新登录";
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package cn.odboy.zilean.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO RedisKey前缀
|
||||||
|
* @time: 2019/7/21 3:31
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public final class RedisKeyConsts {
|
||||||
|
/**
|
||||||
|
* token令牌
|
||||||
|
*/
|
||||||
|
public static final String TOKEN = "zilean:token:{}";
|
||||||
|
/**
|
||||||
|
* 用户信息
|
||||||
|
*/
|
||||||
|
public static final String USER = "zilean:user:{}";
|
||||||
|
}
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
package cn.odboy.zilean.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 田俊
|
||||||
|
* @version 1.0.0
|
||||||
|
* @name: RegexConsts <br/>
|
||||||
|
* @description: TODO 常量:正则表达式 <br/>
|
||||||
|
* @date: 2019/04/2019/4/1 <br/>
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
public final class RegexConsts {
|
||||||
|
/**
|
||||||
|
* 英文单词
|
||||||
|
*/
|
||||||
|
public static final String REGEX_WORD_EN = "^\\w+$";
|
||||||
|
/**
|
||||||
|
* 中文
|
||||||
|
*/
|
||||||
|
public static final String REGEX_WORD_CN = "[\u4E00-\u9FA5]+";
|
||||||
|
/**
|
||||||
|
* 6到30位 数字 + 字符 + _,常用于用户名注册
|
||||||
|
*/
|
||||||
|
public static final String REGEX_WORD_EN_6_30 = "^[a-zA-Z][a-zA-Z0-9_]{6,29}$";
|
||||||
|
/**
|
||||||
|
* 5到20位 数字 + 字符 + _,常用于用户名注册
|
||||||
|
*/
|
||||||
|
public static final String REGEX_WORD_EN_5_20 = "^[a-zA-Z][a-zA-Z0-9_]{5,19}$";
|
||||||
|
/**
|
||||||
|
* 数字 + 字符 + _,且必须已字母开头
|
||||||
|
*/
|
||||||
|
public static final String REGEX_CHAR_NUM_UL = "^[a-zA-Z][a-zA-Z0-9_]+$";
|
||||||
|
/**
|
||||||
|
* 数字 + 字母 组合
|
||||||
|
*/
|
||||||
|
public static final String REGEX_CHAR_NUM = "^[A-Za-z0-9]+$";
|
||||||
|
/**
|
||||||
|
* 字母组合
|
||||||
|
*/
|
||||||
|
public static final String REGEX_CHAR = "^[A-Za-z]+$";
|
||||||
|
/**
|
||||||
|
* 大写字母组合
|
||||||
|
*/
|
||||||
|
public static final String REGEX_CHAR_UC = "^[A-Z]+$";
|
||||||
|
/**
|
||||||
|
* 小写字母组合
|
||||||
|
*/
|
||||||
|
public static final String REGEX_CHAR_LC = "^[a-z]+$";
|
||||||
|
/**
|
||||||
|
* 双字节
|
||||||
|
*/
|
||||||
|
public static final String REGEX_DBCHAR = "[^x00-xff]+";
|
||||||
|
/**
|
||||||
|
* URL地址: 包括 http, ftp 等
|
||||||
|
*/
|
||||||
|
public static final String REGEX_URL = "[a-zA-z]+://[^s]*";
|
||||||
|
/**
|
||||||
|
* HTTP URL
|
||||||
|
*/
|
||||||
|
public static final String REGEX_URL_HTTP = "http(s)?://[^s]+";
|
||||||
|
/**
|
||||||
|
* Internet URL
|
||||||
|
*/
|
||||||
|
public static final String REGEX_URL_INTERNET = "^http(s)?://([\\w-]+.)+[\\w-]+(/[\\w-./?%&=]*)?$";
|
||||||
|
/**
|
||||||
|
* HTML 标签
|
||||||
|
*/
|
||||||
|
public static final String REGEX_HTML_TAG = "<(\\S*?)[^>]*>.*?|<.*? />";
|
||||||
|
/**
|
||||||
|
* IP 地址
|
||||||
|
*/
|
||||||
|
public static final String REGEX_IP = "((25[0-5])|(2[0-4]\\d)|(1\\d{2})|([1-9]\\d)|(\\d)).((25[0-5])|(2[0-4]\\d)|(1\\d{2})|([1-9]\\d)|(\\d)).((25[0-5])|(2[0-4]\\d)|(1\\d{2})|([1-9]\\d)|(\\d)).((25[0-5])|(2[0-4]\\d)|(1\\d{2})|([1-9]\\d)|(\\d))";
|
||||||
|
/**
|
||||||
|
* Email 地址
|
||||||
|
*/
|
||||||
|
public static final String REGEX_EMAIL = "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*.\\w+([-.]\\w+)*";
|
||||||
|
/**
|
||||||
|
* 中国电话号码
|
||||||
|
*/
|
||||||
|
public static final String REGEX_PHONE_CHINA = "0\\d{2,3}-\\d{7,8}";
|
||||||
|
/**
|
||||||
|
* 中国移动电话
|
||||||
|
*/
|
||||||
|
public static final String REGEX_MOBILE_CHINA = "1[3|5|8][0-9]-\\d{8}";
|
||||||
|
/**
|
||||||
|
* 中国身份证号
|
||||||
|
*/
|
||||||
|
public static final String REGEX_IDCARD_CHINA = "\\d{17}[0-9|x|X]|\\d{15}";
|
||||||
|
/**
|
||||||
|
* 中国邮政编码
|
||||||
|
*/
|
||||||
|
public static final String REGEX_ZIPCODE_CHINA = "\\d{6}";
|
||||||
|
/**
|
||||||
|
* QQ号
|
||||||
|
*/
|
||||||
|
public static final String REGEX_QQ = "[1-9][0-9]{4,}";
|
||||||
|
/**
|
||||||
|
* 数字
|
||||||
|
*/
|
||||||
|
public static final String REGEX_CNUMBER = "^[0-9]+$";
|
||||||
|
/**
|
||||||
|
* 正数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_INT_POSITIVE = "^[1-9]\\d*$";
|
||||||
|
/**
|
||||||
|
* 非正数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_INT_NOT_POSITIVE = "^-[1-9]\\d*|0$";
|
||||||
|
/**
|
||||||
|
* 负数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_INT_NEGATIVE = "^-[1-9]\\d*$";
|
||||||
|
/**
|
||||||
|
* 非负数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_INT_NOT_NEGATIVE = "^[1-9]\\d*|0$";
|
||||||
|
/**
|
||||||
|
* 整数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_CINT = "^-?[1-9]\\d*$";
|
||||||
|
/**
|
||||||
|
* 浮点数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_CFLOAT = "^-?([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0)$";
|
||||||
|
/**
|
||||||
|
* 正浮点数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_FLOAT_POSITIVE = "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*$";
|
||||||
|
/**
|
||||||
|
* 非正浮点数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_FLOAT_NOT_POSITIVE = "^(-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*))|0?.0+|0$";
|
||||||
|
/**
|
||||||
|
* 负浮点数
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static final String REGEX_FLOAT_NEGATIVE = "^-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*)$";
|
||||||
|
/**
|
||||||
|
* 非负浮点数
|
||||||
|
*/
|
||||||
|
public static final String REGEX_FLOAT_NOT_NEGATIVE = "^[1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0$";
|
||||||
|
/**
|
||||||
|
* 空行
|
||||||
|
*/
|
||||||
|
public static final String REGEX_SPACE_LINE = "\n\\s*\r";
|
||||||
|
/**
|
||||||
|
* 空字符
|
||||||
|
*/
|
||||||
|
public static final String REGEX_SPACE_CHAR = "^\\s*|\\s*$";
|
||||||
|
/**
|
||||||
|
* 关键字标签正则:仅允许输入中文、英文(含大小写)、数字,输入内容必须以逗号隔开(含中英文逗号),但不能以逗号开头或结尾
|
||||||
|
* 正确格式示例:99,AB,示例,ss,呵呵
|
||||||
|
*/
|
||||||
|
public static final String REGEX_KEY_WORD_TAG = "^([a-zA-Z0-9\\u4e00-\\u9fa5]+[,|,])*[a-zA-Z0-9\\u4e00-\\u9fa5]+$";
|
||||||
|
/**
|
||||||
|
* 能输入有1~3位小数的正实数(包含0)
|
||||||
|
*/
|
||||||
|
public static final String REGEX_INT_ARITHMETIC_NUMBER = "^[0-9]+(\\.[0-9]{1,3})?$";
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.odboy.zilean.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 田俊
|
||||||
|
* @version 1.0.0
|
||||||
|
* @name: SymbolConsts <br/>
|
||||||
|
* @description: TODO 常量:标点符号 <br/>
|
||||||
|
* @date: 2019/03/2019/3/30 <br/>
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
public final class SymbolConsts {
|
||||||
|
/**
|
||||||
|
* 空格
|
||||||
|
*/
|
||||||
|
public static final String SPACE = " ";
|
||||||
|
/**
|
||||||
|
* 逗号
|
||||||
|
*/
|
||||||
|
public static final String DOT = ",";
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package cn.odboy.zilean.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 业务异常
|
||||||
|
* @time: 2019/8/8 10:40
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public class BusinessException extends RuntimeException {
|
||||||
|
/**
|
||||||
|
* 无参构造
|
||||||
|
*/
|
||||||
|
public BusinessException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 含参构造
|
||||||
|
*
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public BusinessException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 含参构造
|
||||||
|
*
|
||||||
|
* @param message 异常信息
|
||||||
|
* @param cause 抛出异常
|
||||||
|
*/
|
||||||
|
public BusinessException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 含参构造
|
||||||
|
*
|
||||||
|
* @param cause 抛出异常
|
||||||
|
*/
|
||||||
|
public BusinessException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package cn.odboy.zilean.common.util;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.odboy.zilean.common.exception.BusinessException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @time: 2019/5/24 22:44
|
||||||
|
* @desc: TODO 断言工具类
|
||||||
|
*/
|
||||||
|
public final class AssertUtils {
|
||||||
|
/**
|
||||||
|
* 表达式结果真时判断
|
||||||
|
*
|
||||||
|
* @param expression Boolean
|
||||||
|
* @param msg 提示信息
|
||||||
|
*/
|
||||||
|
public static void isTrue(Boolean expression, String msg) {
|
||||||
|
if (expression) {
|
||||||
|
throw new BusinessException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数为空时
|
||||||
|
*
|
||||||
|
* @param object 断言对象
|
||||||
|
* @param msg 提示信息
|
||||||
|
*/
|
||||||
|
public static void isNull(Object object, String msg) {
|
||||||
|
if (object == null) {
|
||||||
|
throw new BusinessException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数不空时
|
||||||
|
*
|
||||||
|
* @param object 断言对象
|
||||||
|
* @param msg 提示信息
|
||||||
|
*/
|
||||||
|
public static void notNull(Object object, String msg) {
|
||||||
|
if (object != null) {
|
||||||
|
throw new BusinessException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package cn.odboy.zilean.common.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 集合工具类
|
||||||
|
* @time: 2019/8/9 7:06
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public final class CollectionsUtils {
|
||||||
|
/**
|
||||||
|
* 获取集合中第一个对象
|
||||||
|
*
|
||||||
|
* @param list 对象集合
|
||||||
|
* @param <T> 参考对象
|
||||||
|
* @return 对象
|
||||||
|
*/
|
||||||
|
public static <T> T getOne(List<T> list) {
|
||||||
|
if (CollUtil.isNotEmpty(list)) {
|
||||||
|
return list.get(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
package cn.odboy.zilean.common.util;
|
||||||
|
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 田俊
|
||||||
|
* @version 1.0.0
|
||||||
|
* @name: CookieUtils <br/>
|
||||||
|
* @description: TODO Cookie工具类 <br/>
|
||||||
|
* @date: 2019/03/2019/3/30 <br/>
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
public final class CookieUtils {
|
||||||
|
/**
|
||||||
|
* 读取cookie数组,之后迭代出各个cookie
|
||||||
|
*
|
||||||
|
* @param request HttpServletRequest
|
||||||
|
* @return Cookie[]
|
||||||
|
*/
|
||||||
|
public static Cookie[] getCookies(HttpServletRequest request) {
|
||||||
|
// 根据请求数据,找到cookie数组
|
||||||
|
return request.getCookies();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取cookie
|
||||||
|
*
|
||||||
|
* @param request HttpServletRequest
|
||||||
|
* @param cookieName cookie名称
|
||||||
|
* @return cookie值
|
||||||
|
*/
|
||||||
|
public static String getCookie(HttpServletRequest request, String cookieName) {
|
||||||
|
//根据请求数据,找到cookie数组
|
||||||
|
Cookie[] cookies = request.getCookies();
|
||||||
|
if (cookies != null && cookies.length > 0) {
|
||||||
|
for (Cookie cookie : cookies) {
|
||||||
|
if (cookie != null && cookie.getName().equals(cookieName)) {
|
||||||
|
return cookie.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建cookie,并将新cookie添加到“响应对象”response中。
|
||||||
|
*
|
||||||
|
* @param response HttpServletResponse
|
||||||
|
* @param cookieName cookie名称
|
||||||
|
* @param cookieValue cookie值
|
||||||
|
*/
|
||||||
|
public static void addCookie(HttpServletResponse response, String cookieName, String cookieValue) {
|
||||||
|
// 创建新cookie
|
||||||
|
Cookie cookie = new Cookie(cookieName, cookieValue);
|
||||||
|
// 设置存在时间为无限
|
||||||
|
cookie.setMaxAge(-1);
|
||||||
|
// 设置作用域
|
||||||
|
cookie.setPath("/");
|
||||||
|
// 将cookie添加到response的cookie数组中返回给客户端
|
||||||
|
response.addCookie(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改cookie,可以根据某个cookie的name修改它(不只是name要与被修改cookie一致,path、domain必须也要与被修改cookie一致)
|
||||||
|
*
|
||||||
|
* @param request HttpServletRequest
|
||||||
|
* @param response HttpServletResponse
|
||||||
|
* @param cookieName cookie名称
|
||||||
|
* @param cookieValue cookie值
|
||||||
|
* @return 是否修改成功
|
||||||
|
*/
|
||||||
|
public static boolean editCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue) {
|
||||||
|
Cookie[] cookies = request.getCookies();
|
||||||
|
if (null == cookies) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
for (Cookie cookie : cookies) {
|
||||||
|
// 迭代时如果发现与指定cookieName相同的cookie,就修改相关数据
|
||||||
|
if (cookie.getName().equals(cookieName)) {
|
||||||
|
// 修改value
|
||||||
|
cookie.setValue(cookieValue);
|
||||||
|
cookie.setPath("/");
|
||||||
|
// 修改存活时间
|
||||||
|
cookie.setMaxAge(-1);
|
||||||
|
// 将修改过的cookie存入response,替换掉旧的同名cookie
|
||||||
|
response.addCookie(cookie);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除cookie
|
||||||
|
*
|
||||||
|
* @param request HttpServletRequest
|
||||||
|
* @param response HttpServletResponse
|
||||||
|
* @param cookieName cookie名称
|
||||||
|
* @return 是否删除成功
|
||||||
|
*/
|
||||||
|
public static boolean delCookie(HttpServletRequest request, HttpServletResponse response, String cookieName) {
|
||||||
|
Cookie[] cookies = request.getCookies();
|
||||||
|
if (null == cookies) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
for (Cookie cookie : cookies) {
|
||||||
|
// 如果找到同名cookie,就将value设置为null,将存活时间设置为0,再替换掉原cookie,这样就相当于删除了。
|
||||||
|
if (cookie.getName().equals(cookieName)) {
|
||||||
|
cookie.setValue(null);
|
||||||
|
cookie.setMaxAge(0);
|
||||||
|
cookie.setPath("/");
|
||||||
|
response.addCookie(cookie);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package cn.odboy.zilean.common.util;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 田俊
|
||||||
|
* @version 1.0.0
|
||||||
|
* @name: HttpRequestUtils <br/>
|
||||||
|
* @description: TODO 请求处理 <br/>
|
||||||
|
* @date: 2019/04/2019/4/12 <br/>
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
public final class HttpRequestUtils {
|
||||||
|
/**
|
||||||
|
* 获取webapp请求路径
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getRequestUrl(HttpServletRequest request) {
|
||||||
|
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
|
||||||
|
+ request.getContextPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package cn.odboy.zilean.common.util;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @time: 2019/5/25 6:28
|
||||||
|
* @desc: TODO HttpServlet工具类
|
||||||
|
*/
|
||||||
|
public final class HttpServletUtils {
|
||||||
|
/**
|
||||||
|
* 获取用户真实IP地址,不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
|
||||||
|
* <p>
|
||||||
|
* 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢?
|
||||||
|
* 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
|
||||||
|
* <p>
|
||||||
|
* 如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130,
|
||||||
|
* 192.168.1.100
|
||||||
|
* <p>
|
||||||
|
* 用户真实IP为: 192.168.1.110
|
||||||
|
*
|
||||||
|
* @param request HttpServletRequest
|
||||||
|
* @return 用户真实IP地址
|
||||||
|
*/
|
||||||
|
public static String getIpAddress(HttpServletRequest request) {
|
||||||
|
String ip = request.getHeader("x-forwarded-for");
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getRemoteAddr();
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package cn.odboy.zilean.common.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 田俊
|
||||||
|
* @version 1.0.0
|
||||||
|
* @name: ListUtils <br/>
|
||||||
|
* @description: TODO 数组工具(基于jdk1.8) <br/>
|
||||||
|
* @date: 2019/04/2019/4/2 <br/>
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
public final class ListUtils {
|
||||||
|
public static <K, V> Map<K, V> listToMap(List<V> list, Class clazz, String getKeyMethodName, String getValueMethodName) {
|
||||||
|
Map<K, V> result = new HashMap<>(6);
|
||||||
|
boolean isOk = list != null && list.size() > 0 && !StringUtils.isEmpty(getKeyMethodName)
|
||||||
|
&& !StringUtils.isEmpty(getValueMethodName);
|
||||||
|
if (isOk) {
|
||||||
|
for (Object obj : list) {
|
||||||
|
try {
|
||||||
|
Method getKeyMethod = ReflectUtil.getMethod(clazz, getKeyMethodName);
|
||||||
|
Object targetKey = getKeyMethod.invoke(obj);
|
||||||
|
Method getValueMethod = ReflectUtil.getMethod(clazz, getValueMethodName);
|
||||||
|
Object targetValue = getValueMethod.invoke(obj);
|
||||||
|
result.put((K) targetKey, ((V) targetValue));
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package cn.odboy.zilean.common.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
|
import cn.hutool.core.util.HexUtil;
|
||||||
|
import cn.hutool.crypto.Mode;
|
||||||
|
import cn.hutool.crypto.Padding;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.crypto.symmetric.AES;
|
||||||
|
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 密码工具类
|
||||||
|
* @time: 2019/7/21 18:23
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public final class PasswordUtils {
|
||||||
|
/**
|
||||||
|
* 生成加密密码(理论上可逆,但是当你忘记密码的时候,那就不可逆)
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param password 密码
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String encode(String username, String password) {
|
||||||
|
String content = HexUtil.encodeHexStr(username + ":" + password, CharsetUtil.CHARSET_UTF_8);
|
||||||
|
// 生成密钥
|
||||||
|
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
|
||||||
|
// 构建
|
||||||
|
AES aes;
|
||||||
|
if (content.length() == 16) {
|
||||||
|
aes = new AES(Mode.CTS, Padding.PKCS5Padding, content.getBytes(), "20190506_Odboy".getBytes());
|
||||||
|
} else {
|
||||||
|
aes = new AES(Mode.CTS, Padding.PKCS5Padding, content.substring(0, 16).getBytes(), "20190506_OdboyHH".getBytes());
|
||||||
|
}
|
||||||
|
// 加密
|
||||||
|
byte[] encrypt = aes.encrypt(content);
|
||||||
|
// 解密
|
||||||
|
byte[] decrypt = aes.decrypt(encrypt);
|
||||||
|
return aes.encryptHex(content);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// System.out.println(encode("tianjun", "123456"));
|
||||||
|
// System.out.println(encode("odboy", "123456"));
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package cn.odboy.zilean.common.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.codec.Base64;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.crypto.asymmetric.Sign;
|
||||||
|
import cn.hutool.crypto.asymmetric.SignAlgorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @time: 2019/7/4 21:39
|
||||||
|
* @desc: TODO 签名工具
|
||||||
|
*/
|
||||||
|
public final class SignUtils {
|
||||||
|
private static final Sign SIGN = SecureUtil.sign(SignAlgorithm.MD5withRSA);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取签名Code
|
||||||
|
*
|
||||||
|
* @param username 账号
|
||||||
|
* @param token token令牌
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String signCode(String username, String token) {
|
||||||
|
byte[] data = (username + token).getBytes();
|
||||||
|
// 签名
|
||||||
|
byte[] signed = SIGN.sign(data);
|
||||||
|
// Base64编码
|
||||||
|
return Base64.encode(signed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证签名
|
||||||
|
*
|
||||||
|
* @param username 账号
|
||||||
|
* @param token token令牌
|
||||||
|
* @param signCode 签名Code
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean verify(String username, String token, String signCode) {
|
||||||
|
byte[] data = (username + token).getBytes();
|
||||||
|
// 签名
|
||||||
|
byte[] signed = Base64.decode(signCode);
|
||||||
|
// 验证签名
|
||||||
|
return SIGN.verify(data, signed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// String sign = signCode("1943815081", "ebbddcc5317168b747afd89234ea275e");
|
||||||
|
// System.out.println(sign);
|
||||||
|
// boolean result = verify("1943815081", "ebbddcc5317168b747afd89234ea275e", sign);
|
||||||
|
// System.out.println(result);
|
||||||
|
//
|
||||||
|
// boolean a =
|
||||||
|
// verify(
|
||||||
|
// "1943815081",
|
||||||
|
// "ebbddcc5317168b747afd89234ea275e",
|
||||||
|
//
|
||||||
|
// "fVD69HcPaqxRGRYkdCFKPN4DYw8t1yVa/J2ALumUIpG+ag1y9fCZ038gIfpBw5pQoyJ9DLff0UgphsuO+AhU0PtxEykCLvXo8zwMHn6FGvFzwe1D3SBI9tD9MSDe4E2pH3qr+VpyLyLcsEUAZHos4g9uaaBw8hxAyk/8riVLFUE=");
|
||||||
|
// System.out.println(a);
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# zilean-mybatis
|
||||||
|
|
||||||
|
简化单表重复的CRUD操作,有了它,无需手动建表,简单查询无需重复书写XML。封装隔离后,可轻松嵌入到任何系统里,目前仅针对MySQL有效
|
||||||
|
|
||||||
|
### 特别说明
|
||||||
|
```txt
|
||||||
|
封装隔离后,可轻松嵌入到任何系统里,目前仅针对MySQL有效
|
||||||
|
```
|
||||||
|
|
||||||
|
### 引用Jar
|
||||||
|
```txt
|
||||||
|
Lombok ---------------- 简化get/set/toString等方法, https://www.projectlombok.org/
|
||||||
|
Spring Data JPA ------- Java持久层API
|
||||||
|
MySQL Driver ---------- MySQL数据库驱动
|
||||||
|
MyBatis Framework ----- Mybatis框架
|
||||||
|
HuTool ---------------- 贼好用的Java工具类库
|
||||||
|
Druid ----------------- 阿里数据库连接池组件
|
||||||
|
Fastjson -------------- 阿里Json工具类
|
||||||
|
```
|
||||||
|
|
||||||
|
### 主要功能
|
||||||
|
```txt
|
||||||
|
简化单表crud操作, 基础方法无需书写xml也无需引用mybatis的crud注解
|
||||||
|
运用JPA实现自动建表, 你再也不用烦恼, 表字段究竟怎么取名才好
|
||||||
|
```
|
||||||
|
|
||||||
|
### 注意
|
||||||
|
```txt
|
||||||
|
1、BaseEntity子类必须有javax.persistence.Entity, javax.persistence.Table两个注解
|
||||||
|
2、BaseEntity子类中的@Table必须含有name属性, 并指定表名, 不然会导致建表失败, 并且BaseMapper也取不到表名
|
||||||
|
3、BaseDao子接口必须有org.springframework.stereotype.Repository注解
|
||||||
|
4、根据阿里巴巴Java编码规范, BaseEntity子类中不能出现不属于数据库表的字段, 如需关联查询, 请新建BaseVo的子类
|
||||||
|
5、建议简单的crud使用BaseDao中的方法, 复杂的关联查询使用xml
|
||||||
|
6、如果不需要, 或者不怎么会用Lombok的话, 只需要从pom中移除Lombok依赖, 在对应Lombok注解处加上get/set方法即可
|
||||||
|
```
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<!-- maven可以继承父项目中的参数,所以可以删除子模块中相同定义 -->
|
||||||
|
<artifactId>zilean-mybatis</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>zilean-mybatis</name>
|
||||||
|
<description>简易MyBatis模块</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<!-- lookup parent from repository -->
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- maven可以继承父项目中的依赖,所以可以删除子模块中相同定义 -->
|
||||||
|
<!--lombok 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<!-- HuTool工具箱-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--jpa 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
<version>${springboot.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!--Spring-Mybatis-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
|
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||||
|
<version>2.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- JSON解析 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>${fastjson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- zilean-common 依赖 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean-common</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<!-- 如果其他包需要依赖这个模块那么就不要加这个 -->
|
||||||
|
<!--<build>-->
|
||||||
|
<!--<plugins>-->
|
||||||
|
<!--<plugin>-->
|
||||||
|
<!--<groupId>org.springframework.boot</groupId>-->
|
||||||
|
<!--<artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||||
|
<!--</plugin>-->
|
||||||
|
<!--</plugins>-->
|
||||||
|
<!--</build>-->
|
||||||
|
</project>
|
||||||
+133
@@ -0,0 +1,133 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.cache;
|
||||||
|
|
||||||
|
import cn.hutool.cache.CacheUtil;
|
||||||
|
import cn.hutool.cache.impl.WeakCache;
|
||||||
|
import cn.hutool.core.date.DateUnit;
|
||||||
|
import cn.odboy.zilean.mybatis.constant.SqlConsts;
|
||||||
|
import org.apache.ibatis.cache.Cache;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 田俊
|
||||||
|
* @version 1.0.0
|
||||||
|
* @name: DefaultMyBatisCache <br>
|
||||||
|
* @description: TODO 自定义的Mybatis缓存 <br>
|
||||||
|
* @date: 2019/04/2019/4/6 <br>
|
||||||
|
* @since JDK 1.8
|
||||||
|
*/
|
||||||
|
public final class DefaultMyBatisCache implements Cache {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(DefaultMyBatisCache.class);
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
|
/**
|
||||||
|
* 过期时间:30分钟
|
||||||
|
*/
|
||||||
|
private WeakCache<Object, Object> cache =
|
||||||
|
CacheUtil.newWeakCache(DateUnit.MINUTE.getMillis() * 30);
|
||||||
|
|
||||||
|
public DefaultMyBatisCache() {
|
||||||
|
log.debug("Mybatis自定义缓存初始化");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必须有该构造函数
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
public DefaultMyBatisCache(String id) {
|
||||||
|
log.debug("Mybatis自定义缓存通过ID初始化");
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存编号
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
log.debug("得到ID:" + id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存对象的大小
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getSize() {
|
||||||
|
log.debug("获取缓存大小!");
|
||||||
|
return cache.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存key值缓存对象
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void putObject(Object key, Object value) {
|
||||||
|
log.debug("往缓存中添加元素:key=" + key + ",value=" + value);
|
||||||
|
cache.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过KEY获取缓存对象
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object getObject(Object key) {
|
||||||
|
if (key != null && (SqlConsts.PH_SQL_FIND.contains(String.valueOf(key)))) {
|
||||||
|
// 二级缓存不更新问题
|
||||||
|
cache.remove(key);
|
||||||
|
}
|
||||||
|
log.debug("通过kEY获取值:" + key);
|
||||||
|
log.debug("OVER");
|
||||||
|
log.debug("=======================================================");
|
||||||
|
log.debug("值为:" + cache.get(key));
|
||||||
|
log.debug("=====================OVER==============================");
|
||||||
|
return cache.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过key删除缓存对象
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object removeObject(Object key) {
|
||||||
|
log.debug("移除缓存对象:" + key);
|
||||||
|
cache.remove(key);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空缓存
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
log.debug("清除缓存!");
|
||||||
|
cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存的读写锁
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ReadWriteLock getReadWriteLock() {
|
||||||
|
log.debug("获取锁对象!!!");
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO SQL常量
|
||||||
|
* @time: 2019/8/8 10:41
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public class SqlConsts {
|
||||||
|
/**
|
||||||
|
* 对象属性:主键名称
|
||||||
|
*/
|
||||||
|
public static final String PRIMARY_KEY_NAME = "id";
|
||||||
|
/**
|
||||||
|
* 方法名称:获取主键, 具体查看BaseEntity中的属性名称
|
||||||
|
*/
|
||||||
|
public static final String GET_ID = "getId";
|
||||||
|
/**
|
||||||
|
* 方法名称:设置更新时间, 具体查看BaseEntity中的属性名称
|
||||||
|
*/
|
||||||
|
public static final String SET_UPDATE_TIME = "setUpdateTime";
|
||||||
|
/**
|
||||||
|
* 错误提示:当Entity类没有标注注解@Table(javax.persistence.Table)时, EntityMapper继承了BaseMapper后报错
|
||||||
|
*/
|
||||||
|
public static final String TX_TABLE_NONE =
|
||||||
|
"POJO类中没有@Table注解, 不能使用BaseMapper接口, 如需使用BaseMapper接口, 请加上注解javax.persistence.Table";
|
||||||
|
/**
|
||||||
|
* 错误提示:当分页对象 Page 为null时的提示
|
||||||
|
*/
|
||||||
|
public static final String TX_PAGE_NULL = "分页对象Page不能为空";
|
||||||
|
/**
|
||||||
|
* SQL条件表达式:有效数据
|
||||||
|
*/
|
||||||
|
public static final String EX_SQL_EFFECTIVE_DATA = "delete_flag=0";
|
||||||
|
/**
|
||||||
|
* SQL条件表达式:无效数据
|
||||||
|
*/
|
||||||
|
public static final String EX_SQL_UNEFFECTIVE_DATA = "delete_flag=1";
|
||||||
|
/**
|
||||||
|
* SQL条件表达式:通用统计
|
||||||
|
*/
|
||||||
|
public static final String EX_SQL_CUSTOM_COUNT = "count(0)";
|
||||||
|
/**
|
||||||
|
* SQL条件表达式:分页
|
||||||
|
*/
|
||||||
|
public static final String PR_SQL_PAGE = " LIMIT {}, {}";
|
||||||
|
/**
|
||||||
|
* SQL参数字段:创建时间、主键
|
||||||
|
*/
|
||||||
|
public static final String PR_SQL_ORDER_ID = "create_time desc";
|
||||||
|
/**
|
||||||
|
* SQL查找方法名称头
|
||||||
|
*/
|
||||||
|
public static final String PH_SQL_FIND = "find";
|
||||||
|
/**
|
||||||
|
* GET
|
||||||
|
*/
|
||||||
|
public static final String PH_SQL_GET = "get";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.core;
|
||||||
|
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import cn.odboy.zilean.mybatis.page.Page;
|
||||||
|
import org.apache.ibatis.annotations.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 通用Dao接口
|
||||||
|
* <p>MyBatis提供了2个注解标记:@Select(只能处理字符串常量) 和 @SelectProvider(可以使用一个SQL提供程序来生成相应的SQL语句)
|
||||||
|
* <p>这几个注解声明在Mapper对应的interface的方法上的,注解用于生成查询用的sql语句
|
||||||
|
* 如果对应的Mapper中已使用@Param来注解参数,则在对应的Prodiver的方法中无需写参数
|
||||||
|
* <p>注解中的参数: type参数指定的Class类,必须要能够通过无参的构造函数来初始化
|
||||||
|
* method参数指定的方法,必须是public的,返回值必须为String,可以为static
|
||||||
|
* <p>重点:在Mapper接口和@SelectProvide方法类中,不要使用重载,也就是说,不要使用方法名相同参数不同的方法
|
||||||
|
* @time: 2019/8/8 10:41
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public interface BaseDao<T extends BaseEntity> {
|
||||||
|
/**
|
||||||
|
* 选择性插入(非空属性值), 并返回受影响的行数
|
||||||
|
* <p>
|
||||||
|
* 插入后,可获取到id的值
|
||||||
|
*
|
||||||
|
* @param entity 实体对象
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
@InsertProvider(type = SqlBuilder.class, method = "insertSelective")
|
||||||
|
@Options(useGeneratedKeys = true, keyProperty = "id")
|
||||||
|
int insertSelective(T entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ID删除, 并返回受影响的行数
|
||||||
|
*
|
||||||
|
* @param id 主键ID
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
@UpdateProvider(type = SqlBuilder.class, method = "deleteById")
|
||||||
|
int deleteById(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ID更新, 并返回受影响的行数
|
||||||
|
*
|
||||||
|
* @param entity 实体对象
|
||||||
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
@UpdateProvider(type = SqlBuilder.class, method = "updateSelectiveById")
|
||||||
|
int updateSelectiveById(T entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID查询, 并返回单个实体对象
|
||||||
|
* 注解ResultMap的意思是从sql的执行结果集中取数据,拼装成Enitity的实体类
|
||||||
|
* 当mapper中传入的参数是使用@param
|
||||||
|
* 注解修饰,在xxxProvider类中必须使用Map对象接收参数
|
||||||
|
*
|
||||||
|
* @param id 主键ID
|
||||||
|
* @return 实体对象
|
||||||
|
*/
|
||||||
|
@SelectProvider(type = SqlBuilder.class, method = "selectOneById")
|
||||||
|
T selectOneById(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过类属性和值查询,并返回实体对象集合
|
||||||
|
*
|
||||||
|
* @param nav 类属性名称和值的容器
|
||||||
|
* @return 实体对象集合
|
||||||
|
*/
|
||||||
|
@SelectProvider(type = SqlBuilder.class, method = "selectByNav")
|
||||||
|
List<T> selectByNav(@Param("nav") EntityPropNav nav);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过类属性和值模糊查询,并返回实体对象集合
|
||||||
|
*
|
||||||
|
* @param nav 类属性名称和值的容器
|
||||||
|
* @return 实体对象集合
|
||||||
|
*/
|
||||||
|
@SelectProvider(type = SqlBuilder.class, method = "selectByLikeNav")
|
||||||
|
List<T> selectByLikeNav(@Param("nav") EntityPropNav nav);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页获取对象, 并返回实体对象集合
|
||||||
|
*
|
||||||
|
* @param entity 查询对象
|
||||||
|
* @param page 分页对象
|
||||||
|
* @return 实体对象集合
|
||||||
|
*/
|
||||||
|
@SelectProvider(type = SqlBuilder.class, method = "selectByPage")
|
||||||
|
List<T> selectByPage(@Param("entity") T entity, @Param("page") Page page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不分页, 查询所有(存在全表查询风险,不建议大表与超大表使用)
|
||||||
|
*
|
||||||
|
* @param entity 查询对象entity
|
||||||
|
* @return 实体对象集合
|
||||||
|
*/
|
||||||
|
@SelectProvider(type = SqlBuilder.class, method = "selectAll")
|
||||||
|
List<T> selectAll(@Param("entity") T entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不分页获取范围内对象, 并返回实体对象集合(这个估计会有点bug,如果查询字符串得加单引号不然mybatis会以为它是数据库字段名称)
|
||||||
|
*
|
||||||
|
* @param propName 对象属性名称
|
||||||
|
* @param propValues 对象属性值集合
|
||||||
|
* @return 实体对象集合
|
||||||
|
*/
|
||||||
|
@SelectProvider(type = SqlBuilder.class, method = "selectAllInValues")
|
||||||
|
List<T> selectAllInValues(@Param("propName") String propName, @Param("propValues") List<Object> propValues);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 条件统计数量
|
||||||
|
*
|
||||||
|
* @param entity 查询对象entity
|
||||||
|
* @return 总数量
|
||||||
|
*/
|
||||||
|
@SelectProvider(type = SqlBuilder.class, method = "countAll")
|
||||||
|
long countAll(@Param("entity") T entity);
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.core;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 对象属性名称和值(容器)
|
||||||
|
* @time: 2019/8/10 3:37
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@Log4j2
|
||||||
|
public class EntityPropNav implements Serializable {
|
||||||
|
private static EntityPropNav cloneObj = new EntityPropNav();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象属性名称
|
||||||
|
*/
|
||||||
|
public String name;
|
||||||
|
/**
|
||||||
|
* 对象属性值
|
||||||
|
*/
|
||||||
|
public Object value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私有化构造函数,不得从外部new
|
||||||
|
*/
|
||||||
|
private EntityPropNav() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对象克隆实例, 适合频繁new的场景
|
||||||
|
*
|
||||||
|
* @param name 对象属性名称
|
||||||
|
* @param value 对象属性值
|
||||||
|
* @return EntityPropNav
|
||||||
|
*/
|
||||||
|
public static EntityPropNav build(String name, Object value) {
|
||||||
|
return ObjectUtil.cloneByStream(cloneObj).setName(name).setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置对象属性名称
|
||||||
|
*
|
||||||
|
* @param name 对象属性名称
|
||||||
|
*/
|
||||||
|
public EntityPropNav setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置对象属性值
|
||||||
|
*
|
||||||
|
* @param value 对象属性值
|
||||||
|
*/
|
||||||
|
public EntityPropNav setValue(Object value) {
|
||||||
|
this.value = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,445 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.core;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import cn.hutool.core.util.PageUtil;
|
||||||
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.odboy.zilean.common.constant.GlobalConsts;
|
||||||
|
import cn.odboy.zilean.mybatis.constant.SqlConsts;
|
||||||
|
import cn.odboy.zilean.mybatis.entity.BaseEntity;
|
||||||
|
import cn.odboy.zilean.mybatis.page.Page;
|
||||||
|
import cn.odboy.zilean.mybatis.util.BeanColumnUtils;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.builder.annotation.ProviderContext;
|
||||||
|
import org.apache.ibatis.jdbc.SQL;
|
||||||
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO SQL构造器
|
||||||
|
* @time: 2019/8/8 10:35
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
public class SqlBuilder<T extends BaseEntity> {
|
||||||
|
/**
|
||||||
|
* 表名
|
||||||
|
*/
|
||||||
|
private String tableName = null;
|
||||||
|
/**
|
||||||
|
* 表字段映射
|
||||||
|
*/
|
||||||
|
private String baseColumnList = null;
|
||||||
|
/**
|
||||||
|
* Bean属性名称
|
||||||
|
*/
|
||||||
|
private List<String> beanNames = new ArrayList<>(GlobalConsts.DEFAULT_COLLECTIONS_SIZE);
|
||||||
|
/**
|
||||||
|
* Bean属性名称-->数据库表名 映射关系
|
||||||
|
*/
|
||||||
|
private Map<String, String> beanTableMap = new HashMap<>(GlobalConsts.DEFAULT_COLLECTIONS_SIZE);
|
||||||
|
/**
|
||||||
|
* 数据库表名-->get方法名称
|
||||||
|
*/
|
||||||
|
private Map<String, String> tableGetNameMap = new HashMap<>(GlobalConsts.DEFAULT_COLLECTIONS_SIZE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*
|
||||||
|
* @param context ProviderContext
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private void init(ProviderContext context) throws Exception {
|
||||||
|
if (StrUtil.isBlank(tableName)) {
|
||||||
|
if (!initTableName(context)) {
|
||||||
|
throw new RuntimeException(SqlConsts.TX_TABLE_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取并设置表名
|
||||||
|
*
|
||||||
|
* @param context ProviderContext
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
private boolean initTableName(ProviderContext context) throws Exception {
|
||||||
|
Class mapperType = context.getMapperType();
|
||||||
|
// 强制转换为“参数化类型” [BaseDao<T extends BaseEntity>]
|
||||||
|
ParameterizedType genericSuperclass = (ParameterizedType) mapperType.getGenericInterfaces()[0];
|
||||||
|
// Class类是Type接口的实现类
|
||||||
|
// 获取参数化类型中,实际类型的定义 [new Type[]{T.class}]
|
||||||
|
// 获取数据的第一个元素:T.class
|
||||||
|
// 当前运行类的参数化类型中的实际的类型, 比如BaseMapper<User>, 此处的Class为User.class
|
||||||
|
Class clazz = (Class) genericSuperclass.getActualTypeArguments()[0];
|
||||||
|
// 获取表名
|
||||||
|
// 当entity类有注解时
|
||||||
|
// @javax.persistence.Table(name=sso_user, ...), 自动建表的表名称不得以"t_"或其他前缀开头,只能是类名下换线命名
|
||||||
|
// 没有注解, 返回null
|
||||||
|
Table table = AnnotationUtils.getAnnotation(clazz, Table.class);
|
||||||
|
if (table != null) {
|
||||||
|
this.tableName = table.name();
|
||||||
|
// 获取bean属性名称
|
||||||
|
// 根据jpa内定策略转换为表字段名称
|
||||||
|
Field[] fields = ReflectUtil.getFields(clazz);
|
||||||
|
String sqlColumnName, fieldName;
|
||||||
|
for (Field field : fields) {
|
||||||
|
fieldName = field.getName();
|
||||||
|
sqlColumnName = BeanColumnUtils.getDataBaseColumnName(fieldName);
|
||||||
|
// 建立映射关系
|
||||||
|
beanNames.add(fieldName);
|
||||||
|
beanTableMap.put(fieldName, sqlColumnName);
|
||||||
|
tableGetNameMap.put(sqlColumnName, SqlConsts.PH_SQL_GET + BeanColumnUtils.toUpperCaseFirstOne(fieldName));
|
||||||
|
// 设置查询字段
|
||||||
|
// 定义临时变量
|
||||||
|
StringBuilder column = new StringBuilder();
|
||||||
|
// fix bug: 20190703 由于驼峰命名的原因导致查出来的数据不能设置到实体类中
|
||||||
|
for (Map.Entry<String, String> entry : this.beanTableMap.entrySet()) {
|
||||||
|
// value, 即实体类对应的表字段名称
|
||||||
|
column.append(entry.getValue()).append(" as ");
|
||||||
|
// value, 即实体类本身的属性名称
|
||||||
|
column.append(entry.getKey()).append(",");
|
||||||
|
}
|
||||||
|
// 去除末尾的逗号
|
||||||
|
this.baseColumnList = column.substring(0, column.length() - 1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择性插入
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param entity <T extends BaseEntity>
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String insertSelective(ProviderContext context, T entity) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
if (entity == null) {
|
||||||
|
throw new RuntimeException("entity不能为null");
|
||||||
|
}
|
||||||
|
// 非空属性数量
|
||||||
|
int nonNullPropSize = 0;
|
||||||
|
// 参数字段 有序合集
|
||||||
|
List<String> columns = new ArrayList<>(GlobalConsts.DEFAULT_COLLECTIONS_SIZE);
|
||||||
|
// 参数字段值 有序合集
|
||||||
|
List<String> values = new ArrayList<>(GlobalConsts.DEFAULT_COLLECTIONS_SIZE);
|
||||||
|
List<String> nonNullList = getNonNullList(entity, beanNames, tableGetNameMap, beanTableMap);
|
||||||
|
for (String beanName : nonNullList) {
|
||||||
|
// 此处不能用nonNullPropSize++, ++操作符是线程不安全的
|
||||||
|
nonNullPropSize = nonNullPropSize + 1;
|
||||||
|
// 获取属性名称
|
||||||
|
columns.add(beanTableMap.get(beanName));
|
||||||
|
values.add("#{" + beanName + "}");
|
||||||
|
}
|
||||||
|
// 判断是不是什么都没做
|
||||||
|
if (nonNullPropSize == 0) {
|
||||||
|
throw new RuntimeException("至少有一个字段有值!");
|
||||||
|
}
|
||||||
|
// 组装SQL
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.INSERT_INTO(SqlBuilder.this.tableName);
|
||||||
|
sql.INTO_COLUMNS(columns.toArray(new String[0]));
|
||||||
|
sql.INTO_VALUES(values.toArray(new String[0]));
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("Entity -> " + JSON.toJSONString(entity));
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ID(逻辑)删除
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param id 主键值
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String deleteById(ProviderContext context, Long id) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
if (id == null) {
|
||||||
|
throw new RuntimeException("id不能为null");
|
||||||
|
}
|
||||||
|
// 组装SQL
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.UPDATE(this.tableName);
|
||||||
|
sql.SET(SqlConsts.EX_SQL_UNEFFECTIVE_DATA);
|
||||||
|
sql.WHERE(SqlConsts.PRIMARY_KEY_NAME + "=#{" + SqlConsts.PRIMARY_KEY_NAME + "}");
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("ID -> " + id);
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ID更新
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param entity <T extends BaseEntity>
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String updateSelectiveById(ProviderContext context, T entity) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
log.info(JSON.toJSONString(context));
|
||||||
|
// 如果ID为空
|
||||||
|
if (ReflectUtil.invoke(entity, SqlConsts.GET_ID) == null) {
|
||||||
|
throw new RuntimeException("id不能为null");
|
||||||
|
}
|
||||||
|
// 设置更新时间
|
||||||
|
ReflectUtil.invoke(entity, SqlConsts.SET_UPDATE_TIME, DateTime.now());
|
||||||
|
// 组装SQL
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.UPDATE(this.tableName);
|
||||||
|
List<String> nonNullList = getNonNullList(entity, beanNames, tableGetNameMap, beanTableMap);
|
||||||
|
for (String beanName : nonNullList) {
|
||||||
|
// 不更新id字段
|
||||||
|
if (SqlConsts.PRIMARY_KEY_NAME.equalsIgnoreCase(beanName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 配置映射关系
|
||||||
|
sql.SET(this.beanTableMap.get(beanName) + "=#{" + beanName + "}");
|
||||||
|
}
|
||||||
|
sql.WHERE(SqlConsts.PRIMARY_KEY_NAME + "=#{" + SqlConsts.PRIMARY_KEY_NAME + "}");
|
||||||
|
sql.AND();
|
||||||
|
sql.WHERE(SqlConsts.EX_SQL_EFFECTIVE_DATA);
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("Entity -> " + JSON.toJSONString(entity));
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过ID查询
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param id 主键
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String selectOneById(ProviderContext context, Long id) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
if (id == null) {
|
||||||
|
throw new RuntimeException("id不能为null");
|
||||||
|
}
|
||||||
|
// 组装SQL
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.SELECT(this.baseColumnList);
|
||||||
|
sql.FROM(this.tableName);
|
||||||
|
sql.WHERE(SqlConsts.PRIMARY_KEY_NAME + "=" + id);
|
||||||
|
sql.AND();
|
||||||
|
sql.WHERE(SqlConsts.EX_SQL_EFFECTIVE_DATA);
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("ID -> " + id);
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过类属性和值查询,并返回实体对象集合
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param nav 类属性名称和值的容器
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String selectByNav(ProviderContext context, @Param("nav") EntityPropNav nav) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
if (nav == null) {
|
||||||
|
throw new RuntimeException("nav不能为null");
|
||||||
|
}
|
||||||
|
if (nav.getName() == null) {
|
||||||
|
throw new RuntimeException("nav.name不能为null");
|
||||||
|
}
|
||||||
|
// 组装SQL
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.SELECT(this.baseColumnList);
|
||||||
|
sql.FROM(this.tableName);
|
||||||
|
sql.WHERE(beanTableMap.get(String.valueOf(nav.name)) + "=#{nav.value}");
|
||||||
|
sql.WHERE(SqlConsts.EX_SQL_EFFECTIVE_DATA);
|
||||||
|
sql.ORDER_BY(SqlConsts.PR_SQL_ORDER_ID);
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("Nav -> " + JSON.toJSONString(nav));
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过类属性和值模糊查询,并返回实体对象集合
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param nav 类属性名称和值的容器
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String selectByLikeNav(ProviderContext context, @Param("nav") EntityPropNav nav) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
if (nav == null) {
|
||||||
|
throw new RuntimeException("nav不能为null");
|
||||||
|
}
|
||||||
|
if (nav.getName() == null) {
|
||||||
|
throw new RuntimeException("nav.name不能为null");
|
||||||
|
}
|
||||||
|
if (nav.getValue() == null) {
|
||||||
|
throw new RuntimeException("nav.value不能为null");
|
||||||
|
}
|
||||||
|
// 组装SQL
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.SELECT(this.baseColumnList);
|
||||||
|
sql.FROM(this.tableName);
|
||||||
|
sql.WHERE(beanTableMap.get(String.valueOf(nav.name)) + " like CONCAT('%',#{nav.value},'%')");
|
||||||
|
sql.WHERE(SqlConsts.EX_SQL_EFFECTIVE_DATA);
|
||||||
|
sql.ORDER_BY(SqlConsts.PR_SQL_ORDER_ID);
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("Nav -> " + JSON.toJSONString(nav));
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页获取对象, 并返回实体对象集合
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param entity 查询对象
|
||||||
|
* @param page 分页对象
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String selectByPage(ProviderContext context, @Param("entity") T entity, @Param("page") Page page)
|
||||||
|
throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
if (page == null) {
|
||||||
|
throw new RuntimeException(SqlConsts.TX_PAGE_NULL);
|
||||||
|
}
|
||||||
|
// 组装SQL
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.SELECT(this.baseColumnList);
|
||||||
|
sql.FROM(this.tableName);
|
||||||
|
List<String> nonNullList = getNonNullList(entity, beanNames, tableGetNameMap, beanTableMap);
|
||||||
|
for (String beanName : nonNullList) {
|
||||||
|
sql.WHERE(this.beanTableMap.get(beanName) + "=#{entity." + beanName + "}");
|
||||||
|
}
|
||||||
|
sql.WHERE(SqlConsts.EX_SQL_EFFECTIVE_DATA);
|
||||||
|
int[] startEndIndex = PageUtil.transToStartEnd(page.getPage(), page.getPageSize());
|
||||||
|
sql.ORDER_BY(SqlConsts.PR_SQL_ORDER_ID + StrUtil.format(SqlConsts.PR_SQL_PAGE, startEndIndex[0], startEndIndex[1]));
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("entity -> " + JSON.toJSONString(entity));
|
||||||
|
log.info("Page -> " + JSON.toJSONString(page));
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不分页, 查询所有(存在全表查询风险,不建议大表与超大表使用)
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param entity 非空, 查询对象entity
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String selectAll(ProviderContext context, @Param("entity") T entity) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
// 组装SQL
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.SELECT(this.baseColumnList);
|
||||||
|
sql.FROM(this.tableName);
|
||||||
|
List<String> nonNullList = getNonNullList(entity, beanNames, tableGetNameMap, beanTableMap);
|
||||||
|
for (String beanName : nonNullList) {
|
||||||
|
sql.WHERE(this.beanTableMap.get(beanName) + "=#{entity." + beanName + "}");
|
||||||
|
}
|
||||||
|
sql.WHERE(SqlConsts.EX_SQL_EFFECTIVE_DATA);
|
||||||
|
sql.ORDER_BY(SqlConsts.PR_SQL_ORDER_ID);
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("entity -> " + JSON.toJSONString(entity));
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不分页获取范围内对象, 并返回实体对象集合(这个估计会有点bug,如果查询字符串得加单引号不然mybatis会以为它是数据库字段名称)
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param propName 对象属性名称
|
||||||
|
* @param propValues 对象属性值集合
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String selectAllInValues(ProviderContext context, @Param("propName") String propName,
|
||||||
|
@Param("propValues") List<Object> propValues) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
if (propName == null) {
|
||||||
|
throw new RuntimeException("propName不能为null");
|
||||||
|
}
|
||||||
|
if (CollectionUtil.isEmpty(propValues)) {
|
||||||
|
throw new RuntimeException("propValues不能为null、或存在为null的对象");
|
||||||
|
}
|
||||||
|
// 组合ID
|
||||||
|
StringBuilder idsArrays = new StringBuilder();
|
||||||
|
for (Object propValue : propValues) {
|
||||||
|
idsArrays.append(propValue);
|
||||||
|
idsArrays.append(",");
|
||||||
|
}
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.SELECT(this.baseColumnList);
|
||||||
|
sql.FROM(this.tableName);
|
||||||
|
sql.WHERE(beanTableMap.get(propName) + " in (" + idsArrays.substring(0, idsArrays.length() - 1) + ")");
|
||||||
|
sql.AND();
|
||||||
|
sql.WHERE(SqlConsts.EX_SQL_EFFECTIVE_DATA);
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("propName -> " + propName);
|
||||||
|
log.info("propValues -> " + JSON.toJSONString(propValues));
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 条件统计数量
|
||||||
|
*
|
||||||
|
* @param context 上下文
|
||||||
|
* @param entity 非空, 查询对象entity
|
||||||
|
* @return SQL
|
||||||
|
*/
|
||||||
|
public String countAll(ProviderContext context, @Param("entity") T entity) throws Exception {
|
||||||
|
this.init(context);
|
||||||
|
SQL sql = new SQL();
|
||||||
|
sql.SELECT(SqlConsts.EX_SQL_CUSTOM_COUNT);
|
||||||
|
sql.FROM(this.tableName);
|
||||||
|
List<String> nonNullList = getNonNullList(entity, beanNames, tableGetNameMap, beanTableMap);
|
||||||
|
for (String beanName : nonNullList) {
|
||||||
|
sql.WHERE(this.beanTableMap.get(beanName) + "=#{entity." + beanName + "}");
|
||||||
|
}
|
||||||
|
sql.WHERE(SqlConsts.EX_SQL_EFFECTIVE_DATA);
|
||||||
|
log.info("SQL -> " + sql.toString());
|
||||||
|
log.info("entity -> " + JSON.toJSONString(entity));
|
||||||
|
return sql.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取非空属性合集
|
||||||
|
*
|
||||||
|
* @param assetObj 被校验对象
|
||||||
|
* @param assetObjProps 被校验对象所有属性名称
|
||||||
|
* @param tableGetNameMap 表列名与对象GET属性方法名称的映射关系
|
||||||
|
* @param beanTableMap 对象属性名称与表列名的映射关系
|
||||||
|
* @return List<String>
|
||||||
|
*/
|
||||||
|
private List<String> getNonNullList(Object assetObj, List<String> assetObjProps, Map<String, String> tableGetNameMap,
|
||||||
|
Map<String, String> beanTableMap) {
|
||||||
|
List<String> result = new ArrayList<>(GlobalConsts.DEFAULT_COLLECTIONS_SIZE);
|
||||||
|
//assetObj不为空,即有查询条件的分页
|
||||||
|
if (assetObj != null) {
|
||||||
|
// 类属性值
|
||||||
|
Object beanPropValue;
|
||||||
|
// 遍历类属性
|
||||||
|
for (String assetObjProp : assetObjProps) {
|
||||||
|
// 1、通过beanName获取表字段名称
|
||||||
|
// 2、通过表字段名称获取get方法名称
|
||||||
|
// 3、通过反射获取属性值
|
||||||
|
beanPropValue = ReflectUtil.invoke(assetObj, tableGetNameMap.get(beanTableMap.get(assetObjProp)));
|
||||||
|
// 如果属性值不为null
|
||||||
|
if (beanPropValue != null) {
|
||||||
|
result.add(assetObjProp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.entity;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO BaseEntity 与数据库表结构一一对应,通过DAO层向上传输数据源对象(即Entity)
|
||||||
|
* @time: 2019/8/8 10:42
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@MappedSuperclass
|
||||||
|
public abstract class BaseEntity implements Serializable {
|
||||||
|
/**
|
||||||
|
* 自增主键
|
||||||
|
*/
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(columnDefinition = "BIGINT(20) UNIQUE NOT NULL COMMENT '自增主键'")
|
||||||
|
protected Long id;
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "DATETIME NOT NULL COMMENT '创建时间'")
|
||||||
|
protected Date createTime;
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "DATETIME COMMENT '更新时间'")
|
||||||
|
protected Date updateTime;
|
||||||
|
/**
|
||||||
|
* 软删除标识(1、已删除 0、未删除)
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "TINYINT(1) NOT NULL DEFAULT 0 COMMENT '软删除标识'")
|
||||||
|
protected Integer deleteFlag;
|
||||||
|
/**
|
||||||
|
* 备注信息
|
||||||
|
*/
|
||||||
|
@Column(columnDefinition = "VARCHAR(100) NOT NULL DEFAULT '' COMMENT '备注信息'")
|
||||||
|
protected String remark;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.page;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 页面索引、数据数量
|
||||||
|
* @time: 2019/8/8 10:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class Page implements Serializable {
|
||||||
|
private Integer page = 1;
|
||||||
|
private Integer pageSize = 10;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.page;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 分页对象
|
||||||
|
* @time: 2019/8/8 10:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class Pagination<T> implements Serializable {
|
||||||
|
/**
|
||||||
|
* 数据集合
|
||||||
|
*/
|
||||||
|
private List<T> rows;
|
||||||
|
/**
|
||||||
|
* 数据总数
|
||||||
|
*/
|
||||||
|
private Long total;
|
||||||
|
/**
|
||||||
|
* 页面参数
|
||||||
|
*/
|
||||||
|
private Page page;
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package cn.odboy.zilean.mybatis.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 实体类属性名与数据库字段名互转
|
||||||
|
* @time: 2019/8/8 10:43
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
public final class BeanColumnUtils {
|
||||||
|
private BeanColumnUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类属性名称转SQL字段名
|
||||||
|
*
|
||||||
|
* @param beanPropName 类属性名称
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getDataBaseColumnName(String beanPropName) {
|
||||||
|
if (!StringUtils.isEmpty(beanPropName)) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (char c : beanPropName.toCharArray()) {
|
||||||
|
if (Character.isUpperCase(c)) {
|
||||||
|
sb.append("_").append(Character.toLowerCase(c));
|
||||||
|
} else {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
throw new NullPointerException("beanPropName不能为null");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回有的值条件,比如有个User类,有属性name,id
|
||||||
|
* 当只有id有值时,返回and id ={id的值}
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws
|
||||||
|
* @author ld
|
||||||
|
* @date 2019/02/11 14:13
|
||||||
|
*/
|
||||||
|
public String gainConditionFromObjectByField(Object object) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
// 取出所有属性
|
||||||
|
Field[] fields = object.getClass().getDeclaredFields();
|
||||||
|
for (Field f : fields) {
|
||||||
|
String fieldName = f.getName();
|
||||||
|
// 取属性值
|
||||||
|
Object value = getFieldValue(this, fieldName);
|
||||||
|
if (ObjectUtil.isNotNull(value)) {
|
||||||
|
Class<?> type = f.getType();
|
||||||
|
if ("class java.lang.String".equals(type.toString())) {
|
||||||
|
sb.append(" and ").append(fieldName).append("='").append(value).append("'");
|
||||||
|
} else {
|
||||||
|
sb.append(" and ").append(fieldName).append("=").append(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字段值
|
||||||
|
*
|
||||||
|
* @param object 对象
|
||||||
|
* @param fieldName 类的属性名称
|
||||||
|
* @return 字段值
|
||||||
|
*/
|
||||||
|
private String getFieldValue(Object object, String fieldName) {
|
||||||
|
Object o = invokeMethod(object, fieldName);
|
||||||
|
return ObjectUtil.isNotNull(o) ? o.toString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行某个Field的getField方法
|
||||||
|
*
|
||||||
|
* @param object 对象
|
||||||
|
* @param fieldName 类的属性名称
|
||||||
|
* @return Object
|
||||||
|
*/
|
||||||
|
private Object invokeMethod(Object object, String fieldName) {
|
||||||
|
Class<?> testClass = object.getClass();
|
||||||
|
// 首字母大写
|
||||||
|
// fieldName -> FieldName
|
||||||
|
String methodName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
|
||||||
|
try {
|
||||||
|
return ReflectUtil.invoke(testClass, "get" + methodName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 首字母转大写
|
||||||
|
*
|
||||||
|
* @param s String
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String toUpperCaseFirstOne(String s) {
|
||||||
|
|
||||||
|
if (Character.isUpperCase(s.charAt(0))) {
|
||||||
|
// 如果第一位为大写字母, 直接返回
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
return String.valueOf(Character.toUpperCase(s.charAt(0))) + s.substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<!-- maven可以继承父项目中的参数,所以可以删除子模块中相同定义 -->
|
||||||
|
<artifactId>zilean-test</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>zilean-test</name>
|
||||||
|
<description>框架功能测试模块</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<!-- lookup parent from repository -->
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- maven可以继承父项目中的依赖,所以可以删除子模块中相同定义 -->
|
||||||
|
<!--lombok 依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<!-- HuTool工具箱-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean-base</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.odboy</groupId>
|
||||||
|
<artifactId>zilean-cache</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
|
<artifactId>mybatis-spring-boot-starter-test</artifactId>
|
||||||
|
<version>1.3.2</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package cn.odboy.zilean.test;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO 应用入口
|
||||||
|
* @time: 2019/8/11 7:25
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
* <p>
|
||||||
|
* SpringBootApplication-scanBasePackages-->定义扫描的根节点
|
||||||
|
* MapperScan-->定义扫描mapper接口所在包
|
||||||
|
* EntityScan-->定义JPA自动建表扫描所在包
|
||||||
|
*/
|
||||||
|
@SpringBootApplication(scanBasePackages = "cn.odboy.zilean")
|
||||||
|
@MapperScan("cn.odboy.zilean.dao")
|
||||||
|
@EntityScan("cn.odboy.zilean.entity")
|
||||||
|
public class ZileanTestApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ZileanTestApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
## -------------------------Redis\u914D\u7F6E(\u9AD8\u901F\u7F13\u5B58)
|
||||||
|
# \u670D\u52A1\u5668\u5730\u5740
|
||||||
|
spring.redis.host=47.103.14.6
|
||||||
|
# \u7AEF\u53E3\u53F7
|
||||||
|
spring.redis.port=6379
|
||||||
|
# \u8BBF\u95EE\u5BC6\u7801
|
||||||
|
spring.redis.password=Odboy#Redis!@$wRsSa
|
||||||
|
# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570(\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236)
|
||||||
|
spring.redis.jedis.pool.max-active=50
|
||||||
|
# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4(\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236)
|
||||||
|
spring.redis.jedis.pool.max-wait=-1ms
|
||||||
|
# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
|
||||||
|
spring.redis.jedis.pool.max-idle=10
|
||||||
|
# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
|
||||||
|
spring.redis.jedis.pool.min-idle=0
|
||||||
|
# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4(\u6BEB\u79D2)
|
||||||
|
spring.redis.timeout=100ms
|
||||||
|
# \u6570\u636E\u5E93\u7D22\u5F15(\u9ED8\u8BA4\u4E3A0)
|
||||||
|
spring.redis.database=1
|
||||||
|
## -------------------------EhCache\u914D\u7F6E
|
||||||
|
spring.cache.ehcache.config=ehcache.xml
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
## -------------------------\u6570\u636E\u6E90\u914D\u7F6E
|
||||||
|
spring.datasource.username=root
|
||||||
|
spring.datasource.password=123456
|
||||||
|
spring.datasource.url=jdbc:mysql://192.168.172.3:3306/zilean-test?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true
|
||||||
|
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
|
||||||
|
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
||||||
|
## -------------------------\u6570\u636E\u6E90\u8FDE\u63A5\u6C60\u914D\u7F6E
|
||||||
|
# \u521D\u59CB\u5316\u65F6\u5EFA\u7ACB\u7269\u7406\u8FDE\u63A5\u7684\u4E2A\u6570
|
||||||
|
spring.datasource.druid.initial-size=5
|
||||||
|
# \u6700\u5C0F\u8FDE\u63A5\u6C60\u6570\u91CF
|
||||||
|
spring.datasource.druid.min-idle=5
|
||||||
|
# \u6700\u5927\u8FDE\u63A5\u6C60\u6570\u91CF\uFF0CmaxIdle\u5DF2\u7ECF\u4E0D\u518D\u4F7F\u7528
|
||||||
|
spring.datasource.druid.max-active=20
|
||||||
|
# \u83B7\u53D6\u8FDE\u63A5\u65F6\u6700\u5927\u7B49\u5F85\u65F6\u95F4\uFF0C\u5355\u4F4D\u6BEB\u79D2
|
||||||
|
spring.datasource.druid.max-wait=60000
|
||||||
|
# \u7533\u8BF7\u8FDE\u63A5\u7684\u65F6\u5019\u68C0\u6D4B\uFF0C\u5982\u679C\u7A7A\u95F2\u65F6\u95F4\u5927\u4E8EtimeBetweenEvictionRunsMillis\uFF0C\u6267\u884CvalidationQuery\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548
|
||||||
|
spring.datasource.druid.test-while-idle=true
|
||||||
|
# \u65E2\u4F5C\u4E3A\u68C0\u6D4B\u7684\u95F4\u9694\u65F6\u95F4\u53C8\u4F5C\u4E3AtestWhileIdel\u6267\u884C\u7684\u4F9D\u636E
|
||||||
|
spring.datasource.druid.time-between-eviction-runs-millis=60000
|
||||||
|
# \u9500\u6BC1\u7EBF\u7A0B\u65F6\u68C0\u6D4B\u5F53\u524D\u8FDE\u63A5\u7684\u6700\u540E\u6D3B\u52A8\u65F6\u95F4\u548C\u5F53\u524D\u65F6\u95F4\u5DEE\u5927\u4E8E\u8BE5\u503C\u65F6\uFF0C\u5173\u95ED\u5F53\u524D\u8FDE\u63A5
|
||||||
|
spring.datasource.druid.min-evictable-idle-time-millis=30000
|
||||||
|
# \u7528\u6765\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548\u7684sql\uFF0C\u5FC5\u987B\u662F\u4E00\u4E2A\u67E5\u8BE2\u8BED\u53E5
|
||||||
|
# mysql\u4E2D\u4E3A select 'x'
|
||||||
|
# oracle\u4E2D\u4E3A select 1 from dual
|
||||||
|
spring.datasource.druid.validation-query=select 'x'
|
||||||
|
# \u7533\u8BF7\u8FDE\u63A5\u65F6\u4F1A\u6267\u884CvalidationQuery\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548\uFF0C\u5F00\u542F\u4F1A\u964D\u4F4E\u6027\u80FD\uFF0C\u9ED8\u8BA4\u4E3Atrue
|
||||||
|
spring.datasource.druid.test-on-borrow=false
|
||||||
|
# \u5F52\u8FD8\u8FDE\u63A5\u65F6\u4F1A\u6267\u884CvalidationQuery\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6709\u6548\uFF0C\u5F00\u542F\u4F1A\u964D\u4F4E\u6027\u80FD\uFF0C\u9ED8\u8BA4\u4E3Atrue
|
||||||
|
spring.datasource.druid.test-on-return=false
|
||||||
|
# \u662F\u5426\u7F13\u5B58preparedStatement\uFF0Cmysql5.5+\u5EFA\u8BAE\u5F00\u542F
|
||||||
|
# pool-prepared-statements: true
|
||||||
|
# \u5F53\u503C\u5927\u4E8E0\u65F6poolPreparedStatements\u4F1A\u81EA\u52A8\u4FEE\u6539\u4E3Atrue
|
||||||
|
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
|
||||||
|
# \u914D\u7F6E\u6269\u5C55\u63D2\u4EF6
|
||||||
|
spring.datasource.druid.filters=stat,wall
|
||||||
|
# \u5408\u5E76\u591A\u4E2ADruidDataSource\u7684\u76D1\u63A7\u6570\u636E
|
||||||
|
spring.datasource.druid.use-global-data-source-stat=true
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
## -------------------------Jpa\u914D\u7F6E(\u4E3B\u8981\u7528\u4E8E\u81EA\u52A8\u5EFA\u8868)
|
||||||
|
# \u5EFA\u8868\u7B56\u7565, \u5B9E\u4F53\u7C7B\u53D8\u66F4\u5373\u6539\u53D8\u8868\u7ED3\u6784
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
# \u8868\u5B57\u6BB5\u547D\u540D\u89C4\u5219, \u9047\u5230\u5927\u5199\u5B57\u6BCD \u52A0\u201D_\u201D\u7684\u547D\u540D
|
||||||
|
spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
|
||||||
|
# \u663E\u793A\u5EFA\u8868\u8BED\u53E5
|
||||||
|
spring.jpa.show-sql=true
|
||||||
|
# \u9ED8\u8BA4\u4F7F\u7528MyISAM(\u8868\u793A\u4F7F\u7528MySQL)
|
||||||
|
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
|
||||||
|
# Open Session In View\u7B80\u79F0OSIV\uFF0C\u662F\u4E3A\u4E86\u89E3\u51B3\u5728mvc\u7684controller\u4E2D\u4F7F\u7528\u4E86hibernate\u7684lazy load\u7684\u5C5E\u6027\u65F6\u6CA1\u6709session\u629B\u51FA\u7684LazyInitializationException\u5F02\u5E38\uFF1B\u5BF9hibernate\u6765\u8BF4ToMany\u5173\u7CFB\u9ED8\u8BA4\u662F\u5EF6\u8FDF\u52A0\u8F7D\uFF0C\u800CToOne\u5173\u7CFB\u5219\u9ED8\u8BA4\u662F\u7ACB\u5373\u52A0\u8F7D
|
||||||
|
spring.jpa.open-in-view=false
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
## -------------------------MyBatis\u914D\u7F6E(ORM)
|
||||||
|
# mapper\u6620\u5C04\u6587\u4EF6\u6240\u5728\u7684\u8DEF\u5F84
|
||||||
|
mybatis.mapper-locations=classpath:mappers/**/*Mapper.xml
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
## \u5E94\u7528\u914D\u7F6E
|
||||||
|
# \u662F\u5426\u5F00\u542F\u8C03\u8BD5\u6A21\u5F0F\uFF0C\u8F93\u51FA\u6240\u6709\u4FE1\u606F
|
||||||
|
debug=false
|
||||||
|
## Server\u914D\u7F6E
|
||||||
|
server.port=8080
|
||||||
|
server.tomcat.uri-encoding=utf-8
|
||||||
|
server.servlet.context-path=/zliean-test
|
||||||
|
spring.profiles.active=database,jpa,mybatis,cache
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package cn.odboy.zilean.test;
|
||||||
|
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
|
||||||
|
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@MybatisTest
|
||||||
|
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
|
||||||
|
public class ZileanTestApplicationTests {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package cn.odboy.zilean.test.demo;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import cn.odboy.zilean.dao.IUserDao;
|
||||||
|
import cn.odboy.zilean.entity.User;
|
||||||
|
import cn.odboy.zilean.mybatis.core.EntityPropNav;
|
||||||
|
import cn.odboy.zilean.mybatis.page.Page;
|
||||||
|
import cn.odboy.zilean.test.ZileanTestApplicationTests;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.test.annotation.Rollback;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: Odboy
|
||||||
|
* @version: Jdk 1.8
|
||||||
|
* @desc: TODO SqlHandle功能单元测试
|
||||||
|
* @time: 2019/8/9 7:22
|
||||||
|
* @blog: www.odboy.cn
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
public class SqlBuilderTest extends ZileanTestApplicationTests {
|
||||||
|
@Autowired
|
||||||
|
private IUserDao userDao;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsert() {
|
||||||
|
log.info("新增");
|
||||||
|
User user;
|
||||||
|
for (int i = 0; i < 100000; i++) {
|
||||||
|
user = new User();
|
||||||
|
user.setUsername("tianjun" + i);
|
||||||
|
user.setUserpwd("123456");
|
||||||
|
user.setBgmUrl("背景音乐Url");
|
||||||
|
user.setAutograph("如果你的人生没有那么多的喝彩,就请默默努力吧");
|
||||||
|
user.setBirth(DateTime.now());
|
||||||
|
user.setHometown("江西省赣州市上犹县");
|
||||||
|
user.setJoinWorkDate(DateTime.now());
|
||||||
|
user.setLastLoginTime(DateTime.now());
|
||||||
|
user.setMaritalStatus("全栈工程师");
|
||||||
|
user.setPhoneNum("13621988781");
|
||||||
|
user.setRealName("田俊");
|
||||||
|
user.setLogoUrl("头像Url");
|
||||||
|
user.setRemark("呵呵哒~");
|
||||||
|
user.setSex(Byte.valueOf("0"));
|
||||||
|
user.setCreateTime(DateTime.now());
|
||||||
|
log.info(JSON.toJSONString(user));
|
||||||
|
Assert.assertSame("受影响的行数", 1, userDao.insertSelective(user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Rollback(false)
|
||||||
|
public void testUpdate() {
|
||||||
|
User user = new User();
|
||||||
|
log.info("修改");
|
||||||
|
user.setId(2L);
|
||||||
|
user.setBgmUrl("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||||
|
Assert.assertSame("受影响的行数", 1, userDao.updateSelectiveById(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Rollback(false)
|
||||||
|
public void testDelete() {
|
||||||
|
log.info("删除");
|
||||||
|
Assert.assertSame("受影响的行数", 1, userDao.deleteById(201L));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuery() {
|
||||||
|
List<User> users;
|
||||||
|
User user;
|
||||||
|
long total;
|
||||||
|
|
||||||
|
log.info("通过主键ID查询");
|
||||||
|
user = userDao.selectOneById(2L);
|
||||||
|
log.info("user=" + JSON.toJSONString(user));
|
||||||
|
|
||||||
|
log.info("通过对象属性名称和值查询");
|
||||||
|
users = userDao.selectByNav(EntityPropNav.build("username", "tianjun"));
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
users = userDao.selectByNav(EntityPropNav.build("id", 2));
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
|
||||||
|
log.info("通过对象属性名称和值模糊查询");
|
||||||
|
users = userDao.selectByLikeNav(EntityPropNav.build("username", "tian"));
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
|
||||||
|
log.info("无条件分页查询");
|
||||||
|
users = userDao.selectByPage(null, new Page());
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
|
||||||
|
log.info("条件分页查询");
|
||||||
|
user = new User();
|
||||||
|
user.setId(2L);
|
||||||
|
users = userDao.selectByPage(user, new Page());
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
|
||||||
|
|
||||||
|
log.info("不分页查询所有");
|
||||||
|
users = userDao.selectAll(null);
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
|
||||||
|
log.info("含条件不分页查询所有");
|
||||||
|
user = new User();
|
||||||
|
user.setUsername("tianjun1");
|
||||||
|
users = userDao.selectAll(user);
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
|
||||||
|
log.info("简易 in 查询");
|
||||||
|
users = userDao.selectAllInValues("id", CollUtil.newArrayList(1, 2, 4, 5));
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
users = userDao.selectAllInValues("username", CollUtil.newArrayList("'tianjun1'", "'tianjun3'"));
|
||||||
|
log.info("users=" + JSON.toJSONString(users));
|
||||||
|
|
||||||
|
log.info("无条件统计数量");
|
||||||
|
total = userDao.countAll(null);
|
||||||
|
log.info("total=" + total);
|
||||||
|
|
||||||
|
log.info("含条件统计数量");
|
||||||
|
user = new User();
|
||||||
|
user.setUsername("tianjun1");
|
||||||
|
total = userDao.countAll(user);
|
||||||
|
log.info("total=" + total);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# entity
|
||||||
|
数据库映射类,与数据库字段一一对应
|
||||||
|
# dao
|
||||||
|
数据库操作映射层,控制表数据CRUD,或简单查询
|
||||||
|
# service
|
||||||
|
简单的函数,比如新增、删除、修改、查询,不对数据进行处理,封装dao,也不调用dao进行复杂业务
|
||||||
|
# biz
|
||||||
|
灵活运用service实现各种复杂的业务,不仅仅包含CRUD, 简单的CRUD可以直接引用dao
|
||||||
|
特殊的必须使用sql才能处理的就引用service进行处理
|
||||||
|
# bo(这里写vo也行, 个人理解, 不喜勿碰)
|
||||||
|
包含在返回给客户端(即浏览器)Result中的各种bo,用于向前端输出所需要的数据
|
||||||
|
# query
|
||||||
|
查询对象,即一个以上(不包含)的查询值时,必须将参数封装成query对象
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# zilean-common
|
||||||
|
公共的方法、对象、常量等等
|
||||||
|
# zilean-base
|
||||||
|
基础业务,比如:用户、数据字典、操作日志、权限等等
|
||||||
|
# zilean-cache
|
||||||
|
缓存模块,本地缓存、Redis缓存、ehcache等等
|
||||||
|
# zilean-mybatis
|
||||||
|
自定义MyBatis模块,简化一般CRUD
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# zilean-{项目简称}-{子模块简称}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Jwt Token认证框架
|
||||||
|
使用带签名的token来做用户和权限验证
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Shiro权限管理框架
|
||||||
|
## SecurityManager
|
||||||
|
可以理解成控制中心,所有请求最终基本上都通过它来代理转发,一般我们程序中不需要直接跟他打交道。
|
||||||
|
## Subject
|
||||||
|
请求主体。比如登录用户,比如一个被授权的app。在程序中任何地方都可以通过SecurityUtils.getSubject()获取到当前的subject。subject中可以获取到Principal,这个是subject的标识,比如登陆用户的用户名或者id等,shiro不对值做限制。但是在登录和授权过程中,程序需要通过principal来识别唯一的用户。
|
||||||
|
## Realm
|
||||||
|
通俗一点理解就是realm可以访问安全相关数据,提供统一的数据封装来给上层做数据校验。shiro的建议是每种数据源定义一个realm,比如用户数据存在数据库可以使用JdbcRealm;存在属性配置文件可以使用PropertiesRealm。一般我们使用shiro都使用自定义的realm。
|
||||||
|
当有多个realm存在的时候,shiro在做用户校验的时候会按照定义的策略来决定认证是否通过,shiro提供的可选策略有一个成功或者所有都成功等。
|
||||||
|
## 总结
|
||||||
|
一个realm对应了一个CredentialsMatcher,用来做用户提交认证信息和realm获取得用户信息做比对,shiro已经提供了常用的比如用户密码和存储的Hash后的密码的对比。
|
||||||
|
## 使用Shiro主要做了三件事
|
||||||
|
1、用户登录时做用户名密码校验
|
||||||
|
2、用户登录后收到请求时做JWT Token的校验
|
||||||
|
3、用户权限的校验
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
分层领域模型规约:
|
||||||
|
|
||||||
|
DO( Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。
|
||||||
|
DTO( Data Transfer Object):数据传输对象,Service或Manager向外传输的对象。
|
||||||
|
BO( Business Object):业务对象。 由Service层输出的封装业务逻辑的对象。
|
||||||
|
AO( Application Object):应用对象。 在Web层与Service层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
|
||||||
|
VO( View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。
|
||||||
|
POJO( Plain Ordinary Java Object):在本手册中, POJO专指只有setter/getter/toString的简单类,包括DO/DTO/BO/VO等。
|
||||||
|
Query:数据查询对象,各层接收上层的查询请求。 注意超过2个参数的查询封装,禁止使用Map类来传输。
|
||||||
|
领域模型命名规约:
|
||||||
|
|
||||||
|
数据对象:xxxDO,xxx即为数据表名。
|
||||||
|
数据传输对象:xxxDTO,xxx为业务领域相关的名称。
|
||||||
|
展示对象:xxxVO,xxx一般为网页名称。
|
||||||
|
POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。
|
||||||
Reference in New Issue
Block a user