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