HINOTOR 2 years ago
parent 70dff2caa5
commit 93cf71adb0

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="demo" />
<module name="leyou-api-gateway" />
<module name="leyou-authentication-common" />
<module name="leyou-authentication-service" />
<module name="leyou-cart" />
<module name="leyou-comment-service" />
<module name="leyou-comments-interface" />
<module name="leyou-comments-service" />
<module name="leyou-common" />
<module name="leyou-config" />
<module name="leyou-goods-web" />
<module name="leyou-item-interface" />
<module name="leyou-item-service" />
<module name="leyou-mongondb" />
<module name="leyou-order-interface" />
<module name="leyou-order-service" />
<module name="leyou-registry" />
<module name="leyou-search" />
<module name="leyou-seckill-interface" />
<module name="leyou-seckill-service" />
<module name="leyou-sms" />
<module name="leyou-upload" />
<module name="leyou-user-interface" />
<module name="leyou-user-service" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="demo" target="1.8" />
<module name="leyou-comment" target="1.8" />
<module name="leyou-comment-interface" target="1.8" />
<module name="leyou-comment-service" target="1.8" />
<module name="leyou-mongondb" target="1.8" />
<module name="leyou-review" target="1.8" />
<module name="leyou-review-interface" target="1.8" />
<module name="leyou-review-service" target="1.8" />
<module name="leyou-review-servie" target="1.8" />
<module name="leyou-test" target="1.8" />
<module name="leyout-test" target="1.8" />
</bytecodeTargetLevel>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="leyou-api-gateway" options="-parameters" />
<module name="leyou-authentication-common" options="-parameters" />
<module name="leyou-authentication-service" options="-parameters" />
<module name="leyou-cart" options="-parameters" />
<module name="leyou-comments-interface" options="-parameters" />
<module name="leyou-comments-service" options="-parameters" />
<module name="leyou-common" options="-parameters" />
<module name="leyou-config" options="-parameters" />
<module name="leyou-goods-web" options="-parameters" />
<module name="leyou-item-interface" options="-parameters" />
<module name="leyou-item-service" options="-parameters" />
<module name="leyou-order-interface" options="-parameters" />
<module name="leyou-order-service" options="-parameters" />
<module name="leyou-registry" options="-parameters" />
<module name="leyou-search" options="-parameters" />
<module name="leyou-seckill-interface" options="-parameters" />
<module name="leyou-seckill-service" options="-parameters" />
<module name="leyou-sms" options="-parameters" />
<module name="leyou-upload" options="-parameters" />
<module name="leyou-user-interface" options="-parameters" />
<module name="leyou-user-service" options="-parameters" />
</option>
</component>
</project>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-api-gateway" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-authentication" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-authentication/leyou-authentication-common" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-authentication/leyou-authentication-service" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-cart" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-comments" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-comments/leyou-comments-interface" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-comments/leyou-comments-service" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-common" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-config" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-goods-web" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-item" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-item/leyou-item-interface" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-item/leyou-item-service" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-order" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-order/leyou-order-interface" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-order/leyou-order-service" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-registry" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-search" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-secskill" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-secskill/leyou-seckill-interface" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-secskill/leyou-seckill-service" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-sms" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-upload" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-user" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-user/leyou-user-interface" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyou-user/leyou-user-service" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/leyout-test" charset="UTF-8" />
</component>
</project>

@ -0,0 +1,43 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ConstantConditions" enabled="false" level="WARNING" enabled_by_default="false">
<option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
<option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
</inspection_tool>
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="date" />
</inspection_tool>
<inspection_tool class="MavenModelInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SpringJavaInjectionPointsAutowiringInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="ThymeleafVariablesResolveInspection" enabled="false" level="ERROR" enabled_by_default="false" />
</profile>
</component>

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
<option value="$PROJECT_DIR$/leyou-review/leyou-review-service/pom.xml" />
<option value="$PROJECT_DIR$/leyou-review/leyou-review-servie/pom.xml" />
</list>
</option>
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
<option name="myDefaultNotNull" value="javax.validation.constraints.NotNull" />
<option name="myNullables">
<value>
<list size="9">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="9">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="javax.validation.constraints.NotNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/leyou-comment/leyou-comment-service/leyou-comment-service.iml" filepath="$PROJECT_DIR$/leyou-comment/leyou-comment-service/leyou-comment-service.iml" />
</modules>
</component>
</project>

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

@ -0,0 +1,265 @@
### 一、架构图
![img](https://img-blog.csdnimg.cn/20181212215151153.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
### 二、包含的微服务
![img](https://img-blog.csdnimg.cn/20181212215548926.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
### 2.1 网关微服务
> 架构图
![img](https://img-blog.csdnimg.cn/20181214102311483.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
不管是来自于客户端PC或移动端的请求还是服务内部调用。一切对服务的请求都会经过Zuul这个网关然后再由网关来实现 鉴权、动态路由等等操作。Zuul就是我们服务的统一入口。
> 配置
![img](https://img-blog.csdnimg.cn/20181214102758667.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中除了具备服务路由、均衡负载功能之外它还具备了`权限控制`等功能。为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。
> 主要功能
身份认证与安全识别每个资源的验证要求并拒绝那些与要求不相符的请求。对jwt鉴权
动态路由:动态地将请求路由到不同的后端集群。
负载均衡和熔断
### 2.2 授权中心微服务
> 结合RSA的鉴权
![img](https://img-blog.csdnimg.cn/20181214104033784.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
- 首先利用RSA生成公钥和私钥。私钥保存在授权中心公钥保存在Zuul和各个微服务
- 用户请求登录
- 授权中心校验通过后用私钥对JWT进行签名加密
- 返回jwt给用户
- 用户携带JWT访问
- Zuul直接通过公钥解密JWT进行验证验证通过则放行
- 请求到达微服务微服务直接用公钥解析JWT获取用户信息无需访问授权中心
> 授权中心的主要职责
1. 用户鉴权接收用户的登录请求通过用户中心的接口进行校验通过后生成JWT。使用私钥生成JWT并返回
2. 服务鉴权微服务间的调用不经过Zuul会有风险需要鉴权中心进行认证。原理与用户鉴权类似但逻辑稍微复杂一些未实现
### 2.3 购物车微服务
> 功能需求
- 用户可以在登录状态下将商品添加到购物车
放入数据库
放入redis采用
- 用户可以在未登录状态下将商品添加到购物车
- 放入localstorage
- 用户可以使用购物车一起结算下单
- 用户可以查询自己的购物车
- 用户可以在购物车中修改购买商品的数量。
- 用户可以在购物车中删除商品。
- 在购物车中展示商品优惠信息
- 提示购物车商品价格变化
> 流程图
![img](https://img-blog.csdnimg.cn/20181214104500266.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
这幅图主要描述了两个功能:新增商品到购物车、查询购物车。
- 新增商品:
- 判断是否登录
- 是则添加商品到后台Redis中
- 否则添加商品到本地的Localstorage
- 无论哪种新增,完成后都需要查询购物车列表:
- 判断是否登录
- 否直接查询localstorage中数据并展示
- 是:已登录,则需要先看本地是否有数据,
- 有需要提交到后台添加到redis合并数据而后查询
- 否直接去后台查询redis而后返回
### 2.4 评论微服务(新增)
> 功能需求
1. 用户在确认收货后可以对商品进行评价,每个用户对订单中的商品只能发布一次顶级评论,可以追评,也可以回复别人的评论。
2. 当用户确认收货后没有进行手动评价时3天后自动五星好评
> 表结构设计
parent和isparent字段是用来实现评论嵌套的。
> 实现
使用MongoDB存储评论基本的CRUD。
### 2.5 配置中心微服务
> 需求
在分布式系统中由于服务数量巨多为了方便服务配置文件统一管理实时更新所以需要分布式配置中心组件。在Spring Cloud中有分布式配置中心组件spring cloudconfig 它支持配置服务放在配置服务的内存中即本地也支持放在远程Git仓库中。
使用SpringCloudBus来实现配置的自动更新。
> 组成结构
在spring cloud config 组件中分两个角色一是config server二是config client。
Config Server是一个可横向扩展、集中式的配置服务器它用于集中管理应用程序各个环境下的配置默认使用Git存储配置文件内容也可以使用SVN存储或者是本地文件存存储
Config Client是Config Server的客户端用于操作存储在Config Server中的配置内容。微服务在启动时会请求Config Server获取配置文件的内容请求到后再启动容器
> 实现
创建配置中心对Config Server进行配置然后在其它微服务中配置Config Client。最后使用Github上的Webhooks进行配置的动态刷新所以还要使用内网穿透工具同时要在配置中心中添加过滤器因为使用Webhooks提交请求时会加上一段Payload而本地是无法解析这个Payload的所以要将它过滤掉。
### 2.6 页面静态化微服务
商品详情浏览量比较大并发高所以单独开启一个微服务用来展示商品详情并且对其进行静态化处理保存为静态html文件。在用户访问商品详情页面时让nginx对商品请求进行监听指向本地静态页面如果本地没找到才反向代理到页面详情微服务端口。
### 2.7 后台管理微服务
主要是对商品分类、品牌、商品的规格参数以及商品的CRUD为后台管理提供各种接口。
### 2.8 订单微服务
主要接口有:
- 创建订单
- 查询订单
- 更新订单状态
- 根据订单号生成微信付款链接
- 根据订单号查询支付状态
### 2.9 注册中心
> 基本架构
![img](https://img-blog.csdnimg.cn/2018121514422783.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
- Eureka就是服务注册中心可以是一个集群对外暴露自己的地址
- 提供者启动后向Eureka注册自己信息地址提供什么服务
- 消费者向Eureka订阅服务Eureka会将对应服务的所有提供者地址列表发送给消费者并且定期更新
- 心跳(续约)提供者定期通过http方式向Eureka刷新自己的状态
主要功能就是对各种服务进行管理。
### 2.10 搜索微服务
主要是对Elasticsearch的应用将所有商品数据封装好后添加到Elasticsearch的索引库中然后进行搜索过滤查询相应的商品信息。
### 2.11 秒杀微服务
主要接口有:
- 添加参加秒杀的商品
- 查询秒杀商品
- 创建秒杀地址
- 验证秒杀地址
- 秒杀
秒杀的实现及其优化:
前端:秒杀地址的隐藏、使用图形验证码
后端:接口限流,使用消息队列,调用订单微服务执行下单操作。
TODO需要改进~~~~~~~~~~~~~
### 2.12 短信微服务
因为系统中不止注册一个地方需要短信发送,因此将短信发送抽取为微服务:`leyou-sms-service`,凡是需要的地方都可以使用。
另外因为短信发送API调用时长的不确定性为了提高程序的响应速度短信发送我们都将采用异步发送方式
- 短信服务监听MQ消息收到消息后发送短信。
- 其它服务要发送短信时通过MQ通知短信微服务。
### 2.13 文件上传微服务
使用分布式文件系统FastDFS实现图片上传。
> FastDFS架构
![img](https://img-blog.csdnimg.cn/20181215150632856.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
FastDFS两个主要的角色Tracker Server 和 Storage Server 。
- Tracker Server跟踪服务器主要负责调度storage节点与client通信在访问上起负载均衡的作用和记录storage节点的运行状态是连接client和storage节点的枢纽。
- Storage Server存储服务器保存文件和文件的meta data元数据每个storage server会启动一个单独的线程主动向Tracker cluster中每个tracker server报告其状态信息包括磁盘使用情况文件同步情况及文件上传下载次数统计等信息
- Group文件组多台Storage Server的集群。上传一个文件到同组内的一台机器上后FastDFS会将该文件即时同步到同组内的其它所有机器上起到备份的作用。不同组的服务器保存的数据不同而且相互独立不进行通信。
- Tracker Cluster跟踪服务器的集群有一组Tracker Server跟踪服务器组成。
- Storage Cluster 存储集群有多个Group组成。
> 上传流程
![img](https://img-blog.csdnimg.cn/2018121515081720.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
1. Client通过Tracker server查找可用的Storage server。
2. Tracker server向Client返回一台可用的Storage server的IP地址和端口号。
3. Client直接通过Tracker server返回的IP地址和端口与其中一台Storage server建立连接并进行文件上传。
4. 上传完成Storage server返回Client一个文件ID文件上传结束。
> 下载流程
![img](https://img-blog.csdnimg.cn/20181215150912300.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5ajIwMThneXE=,size_16,color_FFFFFF,t_70)
1. Client通过Tracker server查找要下载文件所在的的Storage server。
2. Tracker server向Client返回包含指定文件的某个Storage server的IP地址和端口号。
3. Client直接通过Tracker server返回的IP地址和端口与其中一台Storage server建立连接并指定要下载文件。
4. 下载文件成功。
### 2.14 用户中心微服务
提供的接口:
- 检查用户名和手机号是否可用
- 发送短信验证码
- 用户注册
- 用户查询
- 修改用户个人资料
### 三、如何启动项目
在虚拟机中进行以下中间件的配置:
- ES搜索
- FDFS文件上传
- nginx代理FDFS中的图片及静态图片
- Rabbitmq数据同步
- Redis缓存
并将配置文件中所有和虚拟机相关的ip进行修改
本机中需要的配置:
- nginx前端所有请求统一代理到网关域名的反向代理
- host实现域名访问
具体请参照https://blog.csdn.net/lyj2018gyq/article/details/83654179#2.1%20Nginx
### 四、数据库
我的版本是最老的一般,所以数据库可能会和新的不一致,关键就是在商品详情页面的显示上,可以参考我`leyou-goods-web`中的写法,最终效果一致。
另外在数据库中又多了几张表:`tb_address`、`tb_seckill_order`、`tb_seckill_sku`,地址表建议保留,其他的可以连同秒杀微服务一起删掉(如果你不需要的话)
### 五、博客地址
[传送门](https://blog.csdn.net/lyj2018gyq/article/category/7963560)

@ -0,0 +1,97 @@
<?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">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.gateway</groupId>
<artifactId>leyou-api-gateway</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!--是springboot提供的微服务检测接口默认对外提供几个接口-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--引入jwt相关配置-->
<dependency>
<groupId>com.leyou.common</groupId>
<artifactId>leyou-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.leyou.authentication</groupId>
<artifactId>leyou-authentication-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!--配置管理依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- docker的maven插件官网 https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>47.104.175.20:5000/${project.artifactId}:${project.version}</imageName>
<baseImage>jdk1.8</baseImage>
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://47.104.175.20:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,25 @@
package com.leyou;
/**
* Author: 98050
* Time: 2018-08-03 20:41
* Feature:
*/
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
/**
* @author li
* @time: 2018-08-03 20:41
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class LyApiGateway {
public static void main(String[] args) {
SpringApplication.run(LyApiGateway.class,args);
}
}

@ -0,0 +1,33 @@
package com.leyou.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @Author: 98050
* @Time: 2018-10-24 16:55
* @Feature:
*/
//@ConfigurationProperties(prefix = "leyou.filter")
@Configuration
@RefreshScope
public class FilterProperties {
@Value("${leyou.filter.allowPaths}")
private String allowPaths;
public String getAllowPaths() {
return allowPaths;
}
public void setAllowPaths(String allowPaths) {
this.allowPaths = allowPaths;
}
}

@ -0,0 +1,44 @@
package com.leyou.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* @author li
* @time:2018/8/7
*
*/
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,不要写*否则cookie就无法使用了
config.addAllowedOrigin("http://manage.leyou.com");
config.addAllowedOrigin("http://www.leyou.com");
//2) 是否发送Cookie信息
config.setAllowCredentials(true);
//3) 允许的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
// 4允许的头信息
config.addAllowedHeader("*");
//2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}

@ -0,0 +1,85 @@
package com.leyou.config;
import com.leyou.auth.utils.RsaUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.File;
import java.security.PublicKey;
/**
* @Author: 98050
* @Time: 2018-10-24 16:12
* @Feature: jwt
*/
//@ConfigurationProperties(prefix = "leyou.jwt")
@Configuration
@RefreshScope
public class JwtProperties {
/**
*
*/
private PublicKey publicKey;
/**
*
*/
@Value("${leyou.jwt.pubKeyPath}")
private String pubKeyPath;
/**
* cookie
*/
@Value("${leyou.jwt.cookieName}")
private String cookieName;
private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);
public PublicKey getPublicKey() {
return publicKey;
}
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
public String getPubKeyPath() {
return pubKeyPath;
}
public void setPubKeyPath(String pubKeyPath) {
this.pubKeyPath = pubKeyPath;
}
public String getCookieName() {
return cookieName;
}
public void setCookieName(String cookieName) {
this.cookieName = cookieName;
}
public static Logger getLogger() {
return logger;
}
/**
* @PostConstruct :
*/
@PostConstruct
public void init(){
try {
// 获取公钥
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
} catch (Exception e) {
logger.error("获取公钥失败!", e);
throw new RuntimeException();
}
}
}

@ -0,0 +1,95 @@
package com.leyou.filter;
import com.leyou.auth.utils.JwtUtils;
import com.leyou.config.FilterProperties;
import com.leyou.config.JwtProperties;
import com.leyou.utils.CookieUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
/**
* @Author: 98050
* @Time: 2018-10-24 16:21
* @Feature:
*/
@Component
//@EnableConfigurationProperties({JwtProperties.class,FilterProperties.class})
public class LoginFilter extends ZuulFilter {
@Autowired
private JwtProperties properties;
@Autowired
private FilterProperties filterProperties;
private static final Logger logger = LoggerFactory.getLogger(LoginFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 5;
}
@Override
public boolean shouldFilter() {
//1.获取上下文
RequestContext context = RequestContext.getCurrentContext();
//2.获取request
HttpServletRequest request = context.getRequest();
//3.获取路径
String requestUri = request.getRequestURI();
logger.info(requestUri);
//4.判断白名单
return !isAllowPath(requestUri);
}
private boolean isAllowPath(String requestUri) {
//1.定义一个标记
boolean flag = false;
//2.遍历允许访问的路径
List<String> paths = Arrays.asList(this.filterProperties.getAllowPaths().split(" "));
for (String path : paths){
if (requestUri.startsWith(path)){
flag = true;
break;
}
}
return flag;
}
@Override
public Object run() throws ZuulException {
//1.获取上下文
RequestContext context = RequestContext.getCurrentContext();
//2.获取request
HttpServletRequest request = context.getRequest();
//3.获取token
String token = CookieUtils.getCookieValue(request,this.properties.getCookieName());
//4.校验
try{
//4.1 校验通过,放行
JwtUtils.getInfoFromToken(token,this.properties.getPublicKey());
}catch (Exception e){
//4.2 校验不通过返回403
context.setSendZuulResponse(false);
context.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
}
return null;
}
}

@ -0,0 +1,7 @@
spring:
cloud:
config:
name: gateway
profile: dev
label: master
uri: http://127.0.0.1:10011

@ -0,0 +1,50 @@
<?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">
<parent>
<artifactId>leyou-authentication</artifactId>
<groupId>com.leyou.authentication</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.authentication</groupId>
<artifactId>leyou-authentication-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.xx.webapps.api.main.WebappsApiBidMain</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,35 @@
package com.leyou.auth.entity;
/**
*
*/
public class UserInfo {
private Long id;
private String username;
public UserInfo() {
}
public UserInfo(Long id, String username) {
this.id = id;
this.username = username;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

@ -0,0 +1,6 @@
package com.leyou.auth.utils;
public abstract class JwtConstans {
public static final String JWT_KEY_ID = "id";
public static final String JWT_KEY_USER_NAME = "username";
}

@ -0,0 +1,112 @@
package com.leyou.auth.utils;
import com.leyou.auth.entity.UserInfo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* @author: li
* @create: 2018-10-23
**/
public class JwtUtils {
/**
* token
*
* @param userInfo
* @param privateKey
* @param expireMinutes
* @return
* @throws Exception
*/
public static String generateToken(UserInfo userInfo, PrivateKey privateKey, int expireMinutes) throws Exception {
return Jwts.builder()
.claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
.claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
.setExpiration(DateTime.now().plusDays(expireMinutes).toDate())
.signWith(SignatureAlgorithm.RS256, privateKey)
.compact();
}
/**
* token
*
* @param userInfo
* @param privateKey
* @param expireMinutes
* @return
* @throws Exception
*/
public static String generateToken(UserInfo userInfo, byte[] privateKey, int expireMinutes) throws Exception {
return Jwts.builder()
.claim(JwtConstans.JWT_KEY_ID, userInfo.getId())
.claim(JwtConstans.JWT_KEY_USER_NAME, userInfo.getUsername())
.setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
.signWith(SignatureAlgorithm.RS256, RsaUtils.getPrivateKey(privateKey))
.compact();
}
/**
* token
*
* @param token token
* @param publicKey
* @return
* @throws Exception
*/
private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
}
/**
* token
*
* @param token token
* @param publicKey
* @return
* @throws Exception
*/
private static Jws<Claims> parserToken(String token, byte[] publicKey) throws Exception {
return Jwts.parser().setSigningKey(RsaUtils.getPublicKey(publicKey))
.parseClaimsJws(token);
}
/**
* token
*
* @param token
* @param publicKey
* @return
* @throws Exception
*/
public static UserInfo getInfoFromToken(String token, PublicKey publicKey) throws Exception {
Jws<Claims> claimsJws = parserToken(token, publicKey);
Claims body = claimsJws.getBody();
return new UserInfo(
ObjectUtils.toLong(body.get(JwtConstans.JWT_KEY_ID)),
ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
);
}
/**
* token
*
* @param token
* @param publicKey
* @return
* @throws Exception
*/
public static UserInfo getInfoFromToken(String token, byte[] publicKey) throws Exception {
Jws<Claims> claimsJws = parserToken(token, publicKey);
Claims body = claimsJws.getBody();
return new UserInfo(
ObjectUtils.toLong(body.get(JwtConstans.JWT_KEY_ID)),
ObjectUtils.toString(body.get(JwtConstans.JWT_KEY_USER_NAME))
);
}
}

@ -0,0 +1,34 @@
package com.leyou.auth.utils;
import org.apache.commons.lang3.StringUtils;
public class ObjectUtils {
public static String toString(Object obj) {
if (obj == null) {
return null;
}
return obj.toString();
}
public static Long toLong(Object obj) {
if (obj == null) {
return 0L;
}
if (obj instanceof Double || obj instanceof Float) {
return Long.valueOf(StringUtils.substringBefore(obj.toString(), "."));
}
if (obj instanceof Number) {
return Long.valueOf(obj.toString());
}
if (obj instanceof String) {
return Long.valueOf(obj.toString());
} else {
return 0L;
}
}
public static Integer toInt(Object obj) {
return toLong(obj).intValue();
}
}

@ -0,0 +1,99 @@
package com.leyou.auth.utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* Created by ace on 2018/10/23.
*
* @author li
*/
public class RsaUtils {
/**
*
*
* @param filename classpath
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(String filename) throws Exception {
byte[] bytes = readFile(filename);
return getPublicKey(bytes);
}
/**
*
*
* @param filename classpath
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(String filename) throws Exception {
byte[] bytes = readFile(filename);
return getPrivateKey(bytes);
}
/**
*
*
* @param bytes
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(byte[] bytes) throws Exception {
X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePublic(spec);
}
/**
*
*
* @param bytes
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(byte[] bytes) throws Exception {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePrivate(spec);
}
/**
* rsa,
*
* @param publicKeyFilename
* @param privateKeyFilename
* @param secret
* @throws IOException
* @throws NoSuchAlgorithmException
*/
public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
SecureRandom secureRandom = new SecureRandom(secret.getBytes());
keyPairGenerator.initialize(1024, secureRandom);
KeyPair keyPair = keyPairGenerator.genKeyPair();
// 获取公钥并写出
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
writeFile(publicKeyFilename, publicKeyBytes);
// 获取私钥并写出
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
writeFile(privateKeyFilename, privateKeyBytes);
}
private static byte[] readFile(String fileName) throws Exception {
return Files.readAllBytes(new File(fileName).toPath());
}
private static void writeFile(String destPath, byte[] bytes) throws IOException {
File dest = new File(destPath);
if (!dest.exists()) {
dest.createNewFile();
}
Files.write(dest.toPath(), bytes);
}
}

@ -0,0 +1,60 @@
package com.leyou.auth.test;
import com.leyou.auth.entity.UserInfo;
import com.leyou.auth.utils.JwtUtils;
import com.leyou.auth.utils.RsaUtils;
import org.junit.Before;
import org.junit.Test;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;
/**
* @Author: 98050
* @Time: 2018-10-23 20:58
* @Feature: JWT
*/
public class JwtTest {
private static final String pubKeyPath = "G:\\tmp\\rsa\\rsa.pub";
private static final String priKeyPath = "G:\\tmp\\rsa\\rsa.pri";
private PublicKey publicKey;
private PrivateKey privateKey;
@Test
public void testRsa() throws Exception {
RsaUtils.generateKey(pubKeyPath, priKeyPath, "234");
}
@Before
public void testGetRsa() throws Exception {
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
this.privateKey = RsaUtils.getPrivateKey(priKeyPath);
}
@Test
public void testGenerateToken() throws Exception {
// 生成token
String token = JwtUtils.generateToken(new UserInfo(20L, "jack"), privateKey, 5);
System.out.println("token = " + token);
}
@Test
public void testParseToken() throws Exception {
String token = "eyJhbGciOiJSUzI1NiJ9.eyJpZCI6MjAsInVzZXJuYW1lIjoiamFjayIsImV4cCI6MTU0MDMwMjU4MX0.KFGDe8V8TwLl5xGqM1brPV50JXf3Z6G4cXPIeYxsqaeeol06BnXNNsyLAbUSrFxloUf-hQqO41O1OrtERllU-JfZXs6MA6rTBSfpar2MJRSZyDGKqfBpPoRED3yZv8oFuzI_94GONqsipmGyQFqWUkhTf9k0tZ5LPRvvGl9tkvc";
// 解析token
UserInfo user = JwtUtils.getInfoFromToken(token, publicKey);
System.out.println("id: " + user.getId());
System.out.println("userName: " + user.getUsername());
}
@Test
public void date(){
System.out.println(new Date());
}
}

@ -0,0 +1,110 @@
<?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">
<parent>
<artifactId>leyou-authentication</artifactId>
<groupId>com.leyou.authentication</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.authentication</groupId>
<artifactId>leyou-authentication-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.leyou.authentication</groupId>
<artifactId>leyou-authentication-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.leyou.common</groupId>
<artifactId>leyou-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.leyou.user</groupId>
<artifactId>leyou-user-interface</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!--配置管理依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- docker的maven插件官网 https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>47.104.175.20:5000/${project.artifactId}:${project.version}</imageName>
<baseImage>jdk1.8</baseImage>
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://47.104.175.20:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,20 @@
package com.leyou.auth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @Author: 98050
* @Time: 2018-10-23 20:11
* @Feature:
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LyAuthApplication {
public static void main(String[] args) {
SpringApplication.run(LyAuthApplication.class,args);
}
}

@ -0,0 +1,13 @@
package com.leyou.auth.client;
import com.leyou.user.api.UserApi;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @Author: 98050
* @Time: 2018-10-23 23:48
* @Feature: feignclient
*/
@FeignClient(value = "user-service")
public interface UserClient extends UserApi {
}

@ -0,0 +1,87 @@
package com.leyou.auth.controller;
import com.leyou.auth.entity.UserInfo;
import com.leyou.auth.properties.JwtProperties;
import com.leyou.auth.service.AuthService;
import com.leyou.auth.utils.JwtUtils;
import com.leyou.utils.CookieUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author: 98050
* @Time: 2018-10-23 22:43
* @Feature:
*/
@Controller
//@EnableConfigurationProperties(JwtProperties.class)
public class AuthController {
@Autowired
private AuthService authService;
@Autowired
private JwtProperties properties;
/**
*
* @param username
* @param password
* @param request
* @param response
* @return
*/
@PostMapping("accredit")
public ResponseEntity<Void> authentication(
@RequestParam("username") String username,
@RequestParam("password") String password,
HttpServletRequest request,
HttpServletResponse response
){
//1.登录校验
String token = this.authService.authentication(username,password);
if (StringUtils.isBlank(token)){
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
//2.将token写入cookie并指定httpOnly为true防止通过js获取和修改
CookieUtils.setCookie(request,response,properties.getCookieName(),token,properties.getCookieMaxAge(),true);
return ResponseEntity.ok().build();
}
/**
*
* @param token
* @return
*/
@GetMapping("verify")
public ResponseEntity<UserInfo> verifyUser(@CookieValue("LY_TOKEN") String token,HttpServletRequest request,
HttpServletResponse response){
try{
//1.从token中解析token信息
UserInfo userInfo = JwtUtils.getInfoFromToken(token,this.properties.getPublicKey());
//2.解析成功要重新刷新token
token = JwtUtils.generateToken(userInfo,this.properties.getPrivateKey(),this.properties.getExpire());
//3.更新Cookie中的token
CookieUtils.setCookie(request,response,this.properties.getCookieName(),token,this.properties.getCookieMaxAge());
//4.解析成功返回用户信息
return ResponseEntity.ok(userInfo);
}catch (Exception e){
e.printStackTrace();
}
//5.出现异常,相应401
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}

@ -0,0 +1,158 @@
package com.leyou.auth.properties;
import com.leyou.auth.utils.RsaUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.io.File;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* @Author: 98050
* @Time: 2018-10-23 22:20
* @Feature: jwt
*/
//@ConfigurationProperties(prefix = "leyou.jwt")
@Configuration
@RefreshScope
public class JwtProperties {
/**
*
*/
@Value("${leyou.jwt.secret}")
private String secret;
/**
*
*/
@Value("${leyou.jwt.pubKeyPath}")
private String pubKeyPath;
/**
*
*/
@Value("${leyou.jwt.priKeyPath}")
private String priKeyPath;
/**
* token
*/
@Value("${leyou.jwt.expire}")
private int expire;
/**
*
*/
private PublicKey publicKey;
/**
*
*/
private PrivateKey privateKey;
/**
* cookie
*/
@Value("${leyou.jwt.cookieName}")
private String cookieName;
/**
* cookie
*/
@Value("${leyou.jwt.cookieMaxAge}")
private Integer cookieMaxAge;
private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getPubKeyPath() {
return pubKeyPath;
}
public void setPubKeyPath(String pubKeyPath) {
this.pubKeyPath = pubKeyPath;
}
public String getPriKeyPath() {
return priKeyPath;
}
public void setPriKeyPath(String priKeyPath) {
this.priKeyPath = priKeyPath;
}
public int getExpire() {
return expire;
}
public void setExpire(int expire) {
this.expire = expire;
}
public PublicKey getPublicKey() {
return publicKey;
}
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
public PrivateKey getPrivateKey() {
return privateKey;
}
public void setPrivateKey(PrivateKey privateKey) {
this.privateKey = privateKey;
}
public String getCookieName() {
return cookieName;
}
public void setCookieName(String cookieName) {
this.cookieName = cookieName;
}
public Integer getCookieMaxAge() {
return cookieMaxAge;
}
public void setCookieMaxAge(Integer cookieMaxAge) {
this.cookieMaxAge = cookieMaxAge;
}
/**
* @PostConstruct :
*/
@PostConstruct
public void init(){
try {
File pubKey = new File(pubKeyPath);
File priKey = new File(priKeyPath);
if (!pubKey.exists() || !priKey.exists()) {
// 生成公钥和私钥
RsaUtils.generateKey(pubKeyPath, priKeyPath, secret);
}
// 获取公钥和私钥
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
this.privateKey = RsaUtils.getPrivateKey(priKeyPath);
} catch (Exception e) {
logger.error("初始化公钥和私钥失败!", e);
throw new RuntimeException();
}
}
}

@ -0,0 +1,16 @@
package com.leyou.auth.service;
/**
* @Author: 98050
* @Time: 2018-10-23 22:46
* @Feature:
*/
public interface AuthService {
/**
*
* @param username
* @param password
* @return
*/
String authentication(String username, String password);
}

@ -0,0 +1,52 @@
package com.leyou.auth.service.impl;
import com.leyou.auth.client.UserClient;
import com.leyou.auth.entity.UserInfo;
import com.leyou.auth.properties.JwtProperties;
import com.leyou.auth.service.AuthService;
import com.leyou.auth.utils.JwtUtils;
import com.leyou.user.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author: 98050
* @Time: 2018-10-23 22:47
* @Feature:
*/
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private UserClient userClient;
@Autowired
private JwtProperties properties;
/**
*
* @param username
* @param password
* @return
*/
@Override
public String authentication(String username, String password) {
try{
//1.调用微服务查询用户信息
User user = this.userClient.queryUser(username,password);
//2.查询结果为空则直接返回null
if (user == null){
return null;
}
//3.查询结果不为空则生成token
String token = JwtUtils.generateToken(new UserInfo(user.getId(), user.getUsername()),
properties.getPrivateKey(), properties.getExpire());
return token;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}

@ -0,0 +1,7 @@
spring:
cloud:
config:
name: auth
profile: dev
label: master
uri: http://127.0.0.1:10011

@ -0,0 +1,60 @@
//import com.leyou.auth.LyAuthApplication;
//import com.leyou.auth.service.AuthService;
//import org.junit.Test;
//import org.junit.runner.RunWith;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.context.SpringBootTest;
//import org.springframework.test.context.junit4.SpringRunner;
//
//import java.io.*;
//
///**
// * @Author: 98050
// * @Time: 2018-11-15 00:00
// * @Feature: 获取5000用户的Token写入文件中
// */
//@RunWith(SpringRunner.class)
//@SpringBootTest(classes = LyAuthApplication.class)
//public class TokenTest {
//
// @Autowired
// private AuthService authService;
//
// @Test
// public void getToken() throws IOException {
// File userInfo = new File("G:/userInfo.txt");
// if (userInfo.exists()){
// userInfo.delete();
// }
// FileWriter fw = new FileWriter(userInfo, true);
// BufferedWriter bw = new BufferedWriter(fw);
// for (int i =0;i < 50 ; i++) {
// String token = this.authService.authentication("username"+i,"abcdefg"+i);
// bw.append("username"+i+","+token+"\r\n");
// }
// bw.close();
// fw.close();
//
// }
//
// @Test
// public void getTokenCSV(){
// try {
// File csv = new File("G://Token.csv");//CSV文件
// BufferedWriter bw = new BufferedWriter(new FileWriter(csv, true));
// for (int i =0; i < 50; i++) {
// //新增一行数据
// String token = this.authService.authentication("username"+i,"abcdefg"+i);
// bw.write("username"+i+","+token);
// bw.newLine();
// }
// bw.close();
// } catch (FileNotFoundException e) {
// //捕获File对象生成时的异常
// e.printStackTrace();
// } catch (IOException e) {
// //捕获BufferedWriter对象关闭时的异常
// e.printStackTrace();
// }
// }
//}

@ -0,0 +1,21 @@
<?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">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.authentication</groupId>
<artifactId>leyou-authentication</artifactId>
<packaging>pom</packaging>
<modules>
<module>leyou-authentication-common</module>
<module>leyou-authentication-service</module>
</modules>
</project>

@ -0,0 +1,102 @@
<?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">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.cart</groupId>
<artifactId>leyou-cart</artifactId>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.leyou.authentication</groupId>
<artifactId>leyou-authentication-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.leyou.common</groupId>
<artifactId>leyou-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.leyou.item.interface</groupId>
<artifactId>leyou-item-interface</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!--配置管理依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- docker的maven插件官网 https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>47.104.175.20:5000/${project.artifactId}:${project.version}</imageName>
<baseImage>jdk1.8</baseImage>
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://47.104.175.20:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,21 @@
package com.leyou.cart;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @Author: 98050
* @Time: 2018-10-24 20:46
* @Feature:
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LyCartApplication {
public static void main(String[] args) {
SpringApplication.run(LyCartApplication.class,args);
}
}

@ -0,0 +1,13 @@
package com.leyou.cart.client;
import com.leyou.item.api.GoodsApi;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @Author: 98050
* @Time: 2018-10-25 21:03
* @Feature: FeignClient
*/
@FeignClient(value = "item-service")
public interface GoodsClient extends GoodsApi {
}

@ -0,0 +1,45 @@
package com.leyou.cart.config;
import com.leyou.cart.interceptor.LoginInterceptor;
import com.leyou.cart.properties.JwtProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author: 98050
* @Time: 2018-10-25 19:48
* @Feature:
*/
@Configuration
//@EnableConfigurationProperties(JwtProperties.class)
public class MvcConfig implements WebMvcConfigurer {
@Autowired
private JwtProperties jwtProperties;
@Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor(jwtProperties);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");
}
// @Bean
// public FilterRegistrationBean someFilterRegistration1() {
// //新建过滤器注册类
// FilterRegistrationBean registration = new FilterRegistrationBean();
// // 添加我们写好的过滤器
// registration.setFilter( new CartFilter());
// // 设置过滤器的URL模式
// registration.addUrlPatterns("/*");
// return registration;
// }
}

@ -0,0 +1,69 @@
package com.leyou.cart.controller;
import com.leyou.cart.pojo.Cart;
import com.leyou.cart.service.CartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @Author: 98050
* @Time: 2018-10-25 20:41
* @Feature:
*/
@Controller
public class CartController {
@Autowired
private CartService cartService;
/**
*
* @param cart
* @return
*/
@PostMapping
public ResponseEntity<Void> addCart(@RequestBody Cart cart){
this.cartService.addCart(cart);
return ResponseEntity.ok().build();
}
/**
*
* @return
*/
@GetMapping
public ResponseEntity<List<Cart>> queryCartList(){
List<Cart> carts = this.cartService.queryCartList();
if(carts == null){
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
return ResponseEntity.ok(carts);
}
/**
*
* @return
*/
@PutMapping
public ResponseEntity<Void> updateNum(@RequestParam("skuId") Long skuId,@RequestParam("num") Integer num){
this.cartService.updateNum(skuId,num);
return ResponseEntity.ok().build();
}
/**
*
* @param skuId
* @return
*/
@DeleteMapping("{skuId}")
public ResponseEntity<Void> deleteCart(@PathVariable("skuId") String skuId){
this.cartService.deleteCart(skuId);
return ResponseEntity.ok().build();
}
}

@ -0,0 +1,29 @@
package com.leyou.cart.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @Author: 98050
* @Time: 2018-10-25 20:00
* @Feature:
*/
//@WebFilter(filterName = "CartFilter",urlPatterns = {"/**"})
public class CartFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("具体过滤规则");
}
@Override
public void destroy() {
System.out.println("销毁");
}
}

@ -0,0 +1,104 @@
package com.leyou.cart.interceptor;
import com.leyou.auth.entity.UserInfo;
import com.leyou.auth.utils.JwtUtils;
import com.leyou.cart.properties.JwtProperties;
import com.leyou.utils.CookieUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author: 98050
* @Time: 2018-10-25 18:17
* @Feature:
*/
public class LoginInterceptor extends HandlerInterceptorAdapter {
private JwtProperties jwtProperties;
/**
* 线
*/
private static final ThreadLocal<UserInfo> t1 = new ThreadLocal<>();
public LoginInterceptor(JwtProperties jwtProperties) {
this.jwtProperties = jwtProperties;
}
/**
* *
* * false
* * afterCompletion(),退
* * true
* *
* * Controller
* *
* * postHandle()
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.查询token
String token = CookieUtils.getCookieValue(request,jwtProperties.getCookieName());
if (StringUtils.isBlank(token)){
//2.未登录返回401
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
//3.有token查询用户信息
try{
//4.解析成功,说明已经登录
UserInfo userInfo;
userInfo = JwtUtils.getInfoFromToken(token,jwtProperties.getPublicKey());
//5.放入线程域
t1.set(userInfo);
return true;
}catch (Exception e){
//6.抛出异常证明未登录返回401
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
}
/**
*
* modelAndView
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
/**
* DispatcherServlet,
* ,afterCompletion()
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//防止内存泄漏
t1.remove();
}
public static UserInfo getLoginUser(){
return t1.get();
}
}

@ -0,0 +1,112 @@
package com.leyou.cart.pojo;
/**
* @Author: 98050
* @Time: 2018-10-25 20:27
* @Feature:
*/
public class Cart {
/**
* Id
*/
private Long userId;
/**
* id
*/
private Long skuId;
/**
*
*/
private String title;
/**
*
*/
private String image;
/**
*
*/
private Long price;
/**
*
*/
private Integer num;
/**
*
*/
private String ownSpec;
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getSkuId() {
return skuId;
}
public void setSkuId(Long skuId) {
this.skuId = skuId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Long getPrice() {
return price;
}
public void setPrice(Long price) {
this.price = price;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public String getOwnSpec() {
return ownSpec;
}
public void setOwnSpec(String ownSpec) {
this.ownSpec = ownSpec;
}
@Override
public String toString() {
return "Cart{" +
"userId=" + userId +
", skuId=" + skuId +
", title='" + title + '\'' +
", image='" + image + '\'' +
", price=" + price +
", num=" + num +
", ownSpec='" + ownSpec + '\'' +
'}';
}
}

@ -0,0 +1,83 @@
package com.leyou.cart.properties;
import com.leyou.auth.utils.RsaUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.security.PublicKey;
/**
* @Author: 98050
* @Time: 2018-10-25 16:12
* @Feature: jwt
*/
//@ConfigurationProperties(prefix = "leyou.jwt")
@Configuration
@RefreshScope
public class JwtProperties {
/**
*
*/
private PublicKey publicKey;
/**
*
*/
@Value("${leyou.jwt.pubKeyPath}")
private String pubKeyPath;
/**
* cookie
*/
@Value("${leyou.jwt.cookieName}")
private String cookieName;
private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);
public PublicKey getPublicKey() {
return publicKey;
}
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
public String getPubKeyPath() {
return pubKeyPath;
}
public void setPubKeyPath(String pubKeyPath) {
this.pubKeyPath = pubKeyPath;
}
public String getCookieName() {
return cookieName;
}
public void setCookieName(String cookieName) {
this.cookieName = cookieName;
}
public static Logger getLogger() {
return logger;
}
/**
* @PostConstruct :
*/
@PostConstruct
public void init(){
try {
// 获取公钥
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
} catch (Exception e) {
logger.error("获取公钥失败!", e);
throw new RuntimeException();
}
}
}

@ -0,0 +1,37 @@
package com.leyou.cart.service;
import com.leyou.cart.pojo.Cart;
import java.util.List;
/**
* @Author: 98050
* @Time: 2018-10-25 20:47
* @Feature:
*/
public interface CartService {
/**
*
* @param cart
*/
void addCart(Cart cart);
/**
*
* @return
*/
List<Cart> queryCartList();
/**
*
* @param skuId
* @param num
*/
void updateNum(Long skuId, Integer num);
/**
*
* @param skuId
*/
void deleteCart(String skuId);
}

@ -0,0 +1,139 @@
package com.leyou.cart.service.impl;
import com.leyou.auth.entity.UserInfo;
import com.leyou.cart.client.GoodsClient;
import com.leyou.cart.interceptor.LoginInterceptor;
import com.leyou.cart.pojo.Cart;
import com.leyou.cart.service.CartService;
import com.leyou.item.pojo.Sku;
import com.leyou.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author: 98050
* @Time: 2018-10-25 20:48
* @Feature:
*/
@Service
public class CartServiceImpl implements CartService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private GoodsClient goodsClient;
private static String KEY_PREFIX = "leyou:cart:uid:";
private final Logger logger = LoggerFactory.getLogger(CartServiceImpl.class);
/**
*
* @param cart
*/
@Override
public void addCart(Cart cart) {
//1.获取用户
UserInfo userInfo = LoginInterceptor.getLoginUser();
//2.Redis的key
String key = KEY_PREFIX + userInfo.getId();
//3.获取hash操作对象
BoundHashOperations<String,Object,Object> hashOperations = this.stringRedisTemplate.boundHashOps(key);
//4.查询是否存在
Long skuId = cart.getSkuId();
Integer num = cart.getNum();
Boolean result = hashOperations.hasKey(skuId.toString());
if (result){
//5.存在,获取购物车数据
String json = hashOperations.get(skuId.toString()).toString();
cart = JsonUtils.parse(json,Cart.class);
//6.修改购物车数量
cart.setNum(cart.getNum() + num);
}else{
//7.不存在,新增购物车数据
cart.setUserId(userInfo.getId());
//8.其他商品信息,需要查询商品微服务
Sku sku = this.goodsClient.querySkuById(skuId);
cart.setImage(StringUtils.isBlank(sku.getImages()) ? "" : StringUtils.split(sku.getImages(),",")[0]);
cart.setPrice(sku.getPrice());
cart.setTitle(sku.getTitle());
cart.setOwnSpec(sku.getOwnSpec());
}
//9.将购物车数据写入redis
hashOperations.put(cart.getSkuId().toString(),JsonUtils.serialize(cart));
}
/**
*
* @return
*/
@Override
public List<Cart> queryCartList() {
//1.获取登录的用户信息
UserInfo userInfo = LoginInterceptor.getLoginUser();
//2.判断是否存在购物车
String key = KEY_PREFIX + userInfo.getId();
if (!this.stringRedisTemplate.hasKey(key)) {
//3.不存在直接返回
return null;
}
BoundHashOperations<String,Object,Object> hashOperations = this.stringRedisTemplate.boundHashOps(key);
List<Object> carts = hashOperations.values();
//4.判断是否有数据
if (CollectionUtils.isEmpty(carts)){
return null;
}
//5.查询购物车数据
return carts.stream().map( o -> JsonUtils.parse(o.toString(),Cart.class)).collect(Collectors.toList());
}
/**
*
* @param skuId
* @param num
*/
@Override
public void updateNum(Long skuId, Integer num) {
//1.获取登录用户
UserInfo userInfo = LoginInterceptor.getLoginUser();
String key = KEY_PREFIX + userInfo.getId();
BoundHashOperations<String,Object,Object> hashOperations = this.stringRedisTemplate.boundHashOps(key);
//2.获取购物车
String json = hashOperations.get(skuId.toString()).toString();
Cart cart = JsonUtils.parse(json,Cart.class);
cart.setNum(num);
//3.写入购物车
hashOperations.put(skuId.toString(),JsonUtils.serialize(cart));
}
/**
*
* @param skuId
*/
@Override
public void deleteCart(String skuId) {
//1.获取登录用户
UserInfo userInfo = LoginInterceptor.getLoginUser();
String key = KEY_PREFIX + userInfo.getId();
BoundHashOperations<String,Object,Object> hashOperations = this.stringRedisTemplate.boundHashOps(key);
//2.删除商品
hashOperations.delete(skuId);
}
}

@ -0,0 +1,7 @@
spring:
cloud:
config:
name: cart
profile: dev
label: master
uri: http://127.0.0.1:10011

@ -0,0 +1,55 @@
//package com.leyou.redis;
//
//import com.leyou.cart.LyCartApplication;
//import org.junit.Test;
//import org.junit.runner.RunWith;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.context.SpringBootTest;
//import org.springframework.data.redis.core.BoundHashOperations;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.StringRedisTemplate;
//import org.springframework.test.context.junit4.SpringRunner;
//
//import java.util.List;
//
///**
// * @Author: 98050
// * @Time: 2018-10-25 22:58
// * @Feature:
// */
//@RunWith(SpringRunner.class)
//@SpringBootTest(classes = LyCartApplication.class)
//public class RedisTest {
//
// @Autowired
// private StringRedisTemplate stringRedisTemplate;
//
// @Autowired
// private RedisTemplate<String,String> redisTemplate;
//
// @Test
// public void test(){
//
// BoundHashOperations<String,String,String> boundHashOperations = this.redisTemplate.boundHashOps("test");
//// boundHashOperations.put("1", "test1");
//// boundHashOperations.put("2", "test2");
//// boundHashOperations.put("3", "test3");
// List<String> result = boundHashOperations.values();
// for (Object o : result){
// System.out.println(o);
// }
// }
//
// @Test
// public void test2(){
//
// BoundHashOperations<String,String,String> boundHashOperations = this.redisTemplate.boundHashOps("test");
//// boundHashOperations.put("1", "test1");
//// boundHashOperations.put("2", "test2");
//// boundHashOperations.put("3", "test3");
// List<String> result = boundHashOperations.values();
// for (Object o : result){
// System.out.println(o);
// }
// }
//}

@ -0,0 +1,46 @@
<?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">
<parent>
<artifactId>leyou-comments</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.comments</groupId>
<artifactId>leyou-comments-interface</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.xx.webapps.api.main.WebappsApiBidMain</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,213 @@
package com.leyou.comments.pojo;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @Author: 98050
* @Time: 2018-11-26 14:45
* @Feature:
*/
public class Review implements Serializable {
@Id
private String _id;
/**
* id
*/
private String orderid;
/**
* id
*/
private String spuid;
/**
*
*/
private String content;
/**
*
*/
private Date publishtime;
/**
* id
*/
private String userid;
/**
*
*/
private String nickname;
/**
*
*/
private Integer visits;
/**
*
*/
private Integer thumbup;
/**
*
*/
private List<String> images;
/**
*
*/
private Integer comment;
/**
*
*/
private Boolean iscomment;
/**
* id
*/
private String parentid;
/**
*
*/
private Boolean isparent;
/**
*
*/
private Integer type;
/**
* json
*/
public Review() {
}
public Review(String orderid,String spuid, String content, String userid, String nickname, List<String> images, Boolean iscomment, String parentid, Boolean isparent, Integer type) {
this.orderid = orderid;
this.spuid = spuid;
this.content = content;
this.userid = userid;
this.nickname = nickname;
this.images = images;
this.iscomment = iscomment;
this.parentid = parentid;
this.isparent = isparent;
this.type = type;
}
public String getOrderid() {
return orderid;
}
public void setOrderid(String orderid) {
this.orderid = orderid;
}
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getSpuid() {
return spuid;
}
public void setSpuid(String spuid) {
this.spuid = spuid;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getPublishtime() {
return publishtime;
}
public void setPublishtime(Date publishtime) {
this.publishtime = publishtime;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getVisits() {
return visits;
}
public void setVisits(Integer visits) {
this.visits = visits;
}
public Integer getThumbup() {
return thumbup;
}
public void setThumbup(Integer thumbup) {
this.thumbup = thumbup;
}
public List<String> getImages() {
return images;
}
public void setImages(List<String> images) {
this.images = images;
}
public Integer getComment() {
return comment;
}
public void setComment(Integer comment) {
this.comment = comment;
}
public Boolean getIscomment() {
return iscomment;
}
public void setIscomment(Boolean comment) {
this.iscomment = comment;
}
public String getParentid() {
return parentid;
}
public void setParentid(String parentid) {
this.parentid = parentid;
}
public Boolean getIsparent() {
return isparent;
}
public void setIsparent(Boolean parent) {
this.isparent = parent;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
}

@ -0,0 +1,69 @@
package com.leyou.comments.pojo;
/**
* @Author: 98050
* @Time: 2018-11-26 16:46
* @Feature:
*/
public class Spit {
private String _id;
private String content;
private String userid;
private String nickname;
private Integer visits;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public Integer getVisits() {
return visits;
}
public void setVisits(Integer visits) {
this.visits = visits;
}
@Override
public String toString() {
return "Spit{" +
"_id='" + _id + '\'' +
", content='" + content + '\'' +
", userid='" + userid + '\'' +
", nickname='" + nickname + '\'' +
", visits=" + visits +
'}';
}
}

@ -0,0 +1,137 @@
<?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">
<!--<parent>-->
<!--<artifactId>leyou-comments</artifactId>-->
<!--<groupId>com.leyou.parent</groupId>-->
<!--<version>1.0.0-SNAPSHOT</version>-->
<!--</parent>-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.comments</groupId>
<artifactId>leyou-comments-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<!--配置管理依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.leyou.authentication</groupId>
<artifactId>leyou-authentication-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.leyou.authentication</groupId>
<artifactId>leyou-authentication-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.leyou.common</groupId>
<artifactId>leyou-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.leyou.comments</groupId>
<artifactId>leyou-comments-interface</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.leyou.order</groupId>
<artifactId>leyou-order-interface</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- docker的maven插件官网 https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>47.104.175.20:5000/${project.artifactId}:${project.version}</imageName>
<baseImage>jdk1.8</baseImage>
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://47.104.175.20:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,20 @@
package com.leyou.comments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @Author: 98050
* @Time: 2018-11-29 15:41
* @Feature: feign
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LyCommentsApplication {
public static void main(String[] args) {
SpringApplication.run(LyCommentsApplication.class,args);
}
}

@ -0,0 +1,55 @@
package com.leyou.comments.bo;
/**
* @Author: 98050
* @Time: 2018-11-26 21:40
* @Feature:
*/
public class CommentRequestParam {
/**
* id
*/
private Long spuId;
/**
*
*/
private Integer page;
/**
*
*/
private static final Integer DEFAULT_SIZE = 20;
/**
*
*/
private static final Integer DEFAULT_PAGE = 1;
public Long getSpuId() {
return spuId;
}
public void setSpuId(Long spuId) {
this.spuId = spuId;
}
public Integer getPage() {
if (page == null){
return DEFAULT_PAGE;
}
/**
* 1
*/
return Math.max(DEFAULT_PAGE,page);
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getDefaultSize() {
return DEFAULT_SIZE;
}
}

@ -0,0 +1,13 @@
package com.leyou.comments.client;
import com.leyou.order.api.OrderApi;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @Author: 98050
* @Time: 2018-11-12 15:19
* @Feature:
*/
@FeignClient(value = "order-service")
public interface OrderClient extends OrderApi {
}

@ -0,0 +1,20 @@
package com.leyou.comments.config;
import com.leyou.comments.properties.IdWorkerProperties;
import com.leyou.utils.IdWorker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: 98050
* @create: 2018-10-27
**/
@Configuration
//@EnableConfigurationProperties(IdWorkerProperties.class)
public class IdWorkerConfig {
@Bean
public IdWorker idWorker(IdWorkerProperties prop) {
return new IdWorker(prop.getWorkerId(), prop.getDataCenterId());
}
}

@ -0,0 +1,52 @@
package com.leyou.comments.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.leyou.comments.interceptor.LoginInterceptor;
import com.leyou.comments.properties.JwtProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* @author: 98050
* @create: 2018-10-27
**/
@Configuration
@EnableWebMvc
//@EnableConfigurationProperties(JwtProperties.class)
public class MvcConfig implements WebMvcConfigurer {
@Autowired
private JwtProperties jwtProperties;
@Bean
public LoginInterceptor loginInterceptor() {
return new LoginInterceptor(jwtProperties);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> excludePath = new ArrayList<>();
excludePath.add("/list");
excludePath.add("/commentId/**");
excludePath.add("/comment");
excludePath.add("/visit/**");
registry.addInterceptor(loginInterceptor())
.addPathPatterns("/**").excludePathPatterns(excludePath);
}
}

@ -0,0 +1,140 @@
package com.leyou.comments.controller;
import com.leyou.auth.entity.UserInfo;
import com.leyou.comments.bo.CommentRequestParam;
import com.leyou.comments.interceptor.LoginInterceptor;
import com.leyou.comments.pojo.Review;
import com.leyou.comments.service.CommentService;
import com.leyou.common.pojo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* @Author: 98050
* @Time: 2018-11-26 21:30
* @Feature:
*/
@RequestMapping
@RestController
public class CommentController {
@Autowired
private CommentService commentService;
@Autowired
private RedisTemplate redisTemplate;
private final String THUMBUP_PREFIX = "thumbup";
/**
*
* @param requestParam
* @return
*/
@GetMapping("list")
public ResponseEntity findReviewBySpuId(@RequestBody CommentRequestParam requestParam){
Page<Review> result = commentService.findReviewBySpuId(requestParam);
if (result == null){
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
PageResult pageResult = new PageResult();
pageResult.setTotal(result.getTotalElements());
pageResult.setItems(result.getContent());
pageResult.setTotalPage((long)result.getTotalPages());
return ResponseEntity.ok(pageResult);
}
/**
*
* @param id
* @return
*/
@PutMapping("thumb/{id}")
public ResponseEntity<Boolean> updateThumbup(@PathVariable String id){
//1.首先判断当前用户是否点过赞
UserInfo userInfo = LoginInterceptor.getLoginUser();
String userId = userInfo.getId()+"";
if (redisTemplate.opsForValue().get(THUMBUP_PREFIX + userId + "_" + id) != null){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
boolean result = this.commentService.updateThumbup(id);
if (!result){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
redisTemplate.opsForValue().set(THUMBUP_PREFIX + userId + "_" + id,"1");
return ResponseEntity.ok(result);
}
/**
*
* @param review
* @return
*/
@PostMapping("comment/{orderId}")
public ResponseEntity<Void> addReview(@PathVariable("orderId") Long orderId,@RequestBody Review review){
boolean result = this.commentService.add(orderId,review);
if (!result){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
return ResponseEntity.status(HttpStatus.CREATED).build();
}
/**
* id
* @param id
* @return
*/
@GetMapping("/commentId/{id}")
public ResponseEntity<Review> findReviewById(@PathVariable("id") String id){
Review review = this.commentService.findOne(id);
if (review == null){
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
return ResponseEntity.ok(review);
}
/**
*
* @param review
* @return
*/
@PutMapping("/comment")
public ResponseEntity<Void> updateReview(@RequestBody Review review){
this.commentService.update(review);
return ResponseEntity.status(HttpStatus.OK).build();
}
/**
* id
* @param id
* @return
*/
@DeleteMapping("/commentId/{id}")
public ResponseEntity<Void> deleteReview(@PathVariable("id") String id){
this.commentService.deleteById(id);
return ResponseEntity.status(HttpStatus.OK).build();
}
/**
* id访1
* @param id
* @return
*/
@PutMapping("visit/{id}")
public ResponseEntity<Void> updateReviewVisit(@PathVariable("id") String id){
boolean result = this.commentService.updateVisits(id);
if (!result){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
return ResponseEntity.status(HttpStatus.OK).build();
}
}

@ -0,0 +1,24 @@
package com.leyou.comments.dao;
import com.leyou.comments.pojo.Review;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* @Author: 98050
* @Time: 2018-11-26 20:51
* @Feature:
*/
public interface CommentDao extends MongoRepository<Review,String> {
/**
*
* @param spuId
* @param pageable
* @return
*/
Page<Review> findReviewBySpuid(String spuId, Pageable pageable);
}

@ -0,0 +1,13 @@
package com.leyou.comments.dao;
import com.leyou.comments.pojo.Spit;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* @Author: 98050
* @Time: 2018-11-26 20:47
* @Feature:
*/
public interface SpitDao extends MongoRepository<Spit,String> {
}

@ -0,0 +1,103 @@
package com.leyou.comments.interceptor;
import com.leyou.auth.entity.UserInfo;
import com.leyou.auth.utils.JwtUtils;
import com.leyou.comments.properties.JwtProperties;
import com.leyou.utils.CookieUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author: 98050
* @Time: 2018-10-25 18:17
* @Feature:
*/
public class LoginInterceptor extends HandlerInterceptorAdapter {
private JwtProperties jwtProperties;
/**
* 线
*/
private static final ThreadLocal<UserInfo> t1 = new ThreadLocal<>();
public LoginInterceptor(JwtProperties jwtProperties) {
this.jwtProperties = jwtProperties;
}
/**
* *
* * false
* * afterCompletion(),退
* * true
* *
* * Controller
* *
* * postHandle()
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.查询token
String token = CookieUtils.getCookieValue(request,jwtProperties.getCookieName());
if (StringUtils.isBlank(token)){
//2.未登录返回401
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
//3.有token查询用户信息
try{
//4.解析成功,说明已经登录
UserInfo userInfo = JwtUtils.getInfoFromToken(token,jwtProperties.getPublicKey());
//5.放入线程域
t1.set(userInfo);
return true;
}catch (Exception e){
//6.抛出异常证明未登录返回401
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
}
/**
*
* modelAndView
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
/**
* DispatcherServlet,
* ,afterCompletion()
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
t1.remove();
}
public static UserInfo getLoginUser(){
return t1.get();
}
}

@ -0,0 +1,77 @@
package com.leyou.comments.listener;
import com.leyou.comments.dao.CommentDao;
import com.leyou.comments.pojo.Review;
import com.leyou.comments.service.CommentService;
import com.leyou.order.vo.CommentsParameter;
import com.leyou.utils.IdWorker;
import com.leyou.utils.JsonUtils;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @Author: 98050
* @Time: 2018-12-12 11:54
* @Feature:
*/
@Component
public class CommentsListener {
@Autowired
private IdWorker idWorker;
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private CommentDao commentDao;
/**
*
* @param string
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "leyou.comments.queue",durable = "true"), //队列持久化
exchange = @Exchange(
value = "leyou.comments.exchange",
ignoreDeclarationExceptions = "true",
type = ExchangeTypes.TOPIC
),
key = {"user.comments"}
))
public void listenCommentsMessage(String string){
CommentsParameter commentsParameter = JsonUtils.parse(string, CommentsParameter.class);
if (commentsParameter == null){
return;
}
Review review = commentsParameter.getReview();
review.set_id(idWorker.nextId() + "");
review.setPublishtime(new Date());
review.setComment(0);
review.setThumbup(0);
review.setVisits(0);
if (review.getParentid() != null && !"".equals(review.getParentid())){
//如果存在上级id则上级评论数加1将上级评论的isParent设置为true浏览量加一
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(review.getParentid()));
Update update = new Update();
update.inc("comment",1);
update.set("isparent",true);
update.inc("visits",1);
this.mongoTemplate.updateFirst(query,update,"review");
}
commentDao.save(review);
}
}

@ -0,0 +1,43 @@
package com.leyou.comments.properties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
/**
* @author: 98050
* @create: 2018-10-27
**/
//@ConfigurationProperties(prefix = "leyou.worker")
@Configuration
@RefreshScope
public class IdWorkerProperties {
/**
* id
*/
@Value("${leyou.worker.workerId}")
private long workerId;
/**
*
*/
@Value("${leyou.worker.dataCenterId}")
private long dataCenterId;
public long getWorkerId() {
return workerId;
}
public void setWorkerId(long workerId) {
this.workerId = workerId;
}
public long getDataCenterId() {
return dataCenterId;
}
public void setDataCenterId(long dataCenterId) {
this.dataCenterId = dataCenterId;
}
}

@ -0,0 +1,72 @@
package com.leyou.comments.properties;
import com.leyou.auth.utils.RsaUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.security.PublicKey;
/**
* @author: 9805
* @create: 2018-10-27
**/
//@ConfigurationProperties(prefix = "leyou.jwt")
@Configuration
@RefreshScope
public class JwtProperties {
/**
*
*/
@Value("${leyou.jwt.pubKeyPath}")
private String pubKeyPath;
/**
*
*/
private PublicKey publicKey;
@Value("${leyou.jwt.cookieName}")
private String cookieName;
private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);
@PostConstruct
public void init(){
try {
// 获取公钥和私钥
this.publicKey = RsaUtils.getPublicKey(pubKeyPath);
} catch (Exception e) {
logger.error("初始化公钥失败!", e);
throw new RuntimeException();
}
}
public String getPubKeyPath() {
return pubKeyPath;
}
public void setPubKeyPath(String pubKeyPath) {
this.pubKeyPath = pubKeyPath;
}
public PublicKey getPublicKey() {
return publicKey;
}
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
public String getCookieName() {
return cookieName;
}
public void setCookieName(String cookieName) {
this.cookieName = cookieName;
}
}

@ -0,0 +1,63 @@
package com.leyou.comments.service;
import com.leyou.comments.bo.CommentRequestParam;
import com.leyou.comments.pojo.Review;
import org.springframework.data.domain.Page;
/**
* @Author: 98050
* @Time: 2018-11-26 15:40
* @Feature:
*/
public interface CommentService {
/**
* id
*
* @param id
* @return
*/
Review findOne(String id);
/**
*
* @param review
* @param orderId
* @return
*/
boolean add(Long orderId,Review review);
/**
*
*
* @param review
*/
void update(Review review);
/**
*
*
* @param id
*/
void deleteById(String id);
/**
*
* @param commentRequestParam
* @return
*/
Page<Review> findReviewBySpuId(CommentRequestParam commentRequestParam);
/**
*
* @param id
*/
boolean updateThumbup(String id);
/**
* 1
* @param id
*/
boolean updateVisits(String id);
}

@ -0,0 +1,158 @@
package com.leyou.comments.service.impl;
import com.leyou.comments.bo.CommentRequestParam;
import com.leyou.comments.client.OrderClient;
import com.leyou.comments.dao.CommentDao;
import com.leyou.comments.pojo.Review;
import com.leyou.comments.service.CommentService;
import com.leyou.utils.IdWorker;
import com.mongodb.client.result.UpdateResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Optional;
/**
* @Author: 98050
* @Time: 2018-11-26 15:41
* @Feature:
*/
@Service
public class CommentServiceImpl implements CommentService {
@Autowired
private CommentDao commentDao;
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private IdWorker idWorker;
@Autowired
private OrderClient orderClient;
@Override
public Review findOne(String id) {
//判断空
Optional<Review> optional = commentDao.findById(id);
return optional.orElse(null);
}
/**
*
*
* @param review
*/
@Override
@Transactional(rollbackFor = Exception.class)
public boolean add(Long orderId,Review review) {
//1.检查用户是否在该商品下发表过顶级评论过
if (review.getIsparent()) {
Query query2 = new Query();
query2.addCriteria(Criteria.where("userid").is(review.getUserid()));
query2.addCriteria(Criteria.where("orderid").is(review.getOrderid()));
query2.addCriteria(Criteria.where("spuid").is(review.getSpuid()));
List<Review> old = this.mongoTemplate.find(query2, Review.class);
if (old.size() > 0 && old.get(0).getIsparent()) {
return false;
}
}
//2.修改订单状态,6代表评价状态
boolean result = this.orderClient.updateOrderStatus(orderId, 6).getBody();
if (!result){
return false;
}
//3.添加评论
/**
*
*/
review.set_id(idWorker.nextId() + "");
review.setPublishtime(new Date());
review.setComment(0);
review.setThumbup(0);
review.setVisits(0);
if (review.getParentid() != null && !"".equals(review.getParentid())){
//如果存在上级id则上级评论数加1将上级评论的isParent设置为true浏览量加一
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(review.getParentid()));
Update update = new Update();
update.inc("comment",1);
update.set("isparent",true);
update.inc("visits",1);
this.mongoTemplate.updateFirst(query,update,"review");
}
commentDao.save(review);
return true;
}
/**
*
*
* @param review
*/
@Override
public void update(Review review) {
commentDao.save(review);
}
/**
*
*
* @param id
*/
@Override
public void deleteById(String id) {
commentDao.deleteById(id);
}
/**
*
* @param commentRequestParam
* @return
*/
@Override
public Page<Review> findReviewBySpuId(CommentRequestParam commentRequestParam) {
PageRequest pageRequest = PageRequest.of(commentRequestParam.getPage()-1, commentRequestParam.getDefaultSize());
return this.commentDao.findReviewBySpuid(commentRequestParam.getSpuId()+"",pageRequest);
}
/**
* ()
* @param id
*/
@Override
public boolean updateThumbup(String id) {
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(id));
Update update = new Update();
update.inc("thumbup",1);
UpdateResult result = this.mongoTemplate.updateFirst(query,update,"review");
return result.isModifiedCountAvailable();
}
/**
* 访
* @param id
*/
@Override
public boolean updateVisits(String id) {
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(id));
Update update = new Update();
update.inc("visits",1);
UpdateResult result = this.mongoTemplate.updateFirst(query,update,"review");
return result.isModifiedCountAvailable();
}
}

@ -0,0 +1,7 @@
spring:
cloud:
config:
name: comments
profile: dev
label: master
uri: http://127.0.0.1:10011

@ -0,0 +1,70 @@
//import com.leyou.comments.LyCommentsApplication;
//import com.leyou.comments.dao.CommentDao;
//import com.leyou.comments.pojo.Review;
//import com.leyou.comments.service.CommentService;
//import org.junit.Test;
//import org.junit.runner.RunWith;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.context.SpringBootTest;
//import org.springframework.test.context.junit4.SpringRunner;
//
//import java.util.ArrayList;
//import java.util.List;
//
///**
// * @Author: 98050
// * @Time: 2018-12-09 20:37
// * @Feature:
// */
//@RunWith(SpringRunner.class)
//@SpringBootTest(classes = LyCommentsApplication.class)
//public class CommentsTest {
//
// @Autowired
// private CommentService commentService;
//
// @Autowired
// private CommentDao commentDao;
//
// /**
// * 为spuId为2的商品添加100条评顶级论数据
// */
// @Test
// public void LoadData(){
// for (int i = 0; i < 100; i++) {
// String spuId = "2";
// String content = "手机不错"+i;
// String userId = (35 + i) + "";
// String nickname = "username"+i;
// List<String> images = new ArrayList<>();
// boolean iscomment = i % 2 == 0;
// String parentId = 0 + "";
// boolean isparent = true;
// int type = i % 5;
// //Review review = new Review(spuId, content, userId, nickname, images, iscomment, parentId,isparent,type);
//
// //commentService.add(review);
// }
// }
//
// @Test
// public void LoadOneData(){
// String spuId = "2";
// String content = "苹果手机不错";
// String userId = 36 + "";
// String nickname = "username1";
// List<String> images = new ArrayList<>();
// boolean iscomment = true;
// String parentId = "1071767095416725504";
// boolean isparent = false;
// int type = 4;
// //Review review = new Review(spuId, content, userId, nickname, images, iscomment, parentId,isparent,type);
//
// //commentService.add(review);
// }
//
// @Test
// public void delete(){
// commentDao.deleteAll();
// }
//}

@ -0,0 +1,46 @@
//import com.leyou.comments.LyCommentsApplication;
//import com.leyou.comments.dao.SpitDao;
//import com.leyou.comments.pojo.Spit;
//import org.junit.Test;
//import org.junit.runner.RunWith;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.context.SpringBootTest;
//import org.springframework.data.mongodb.core.MongoTemplate;
//import org.springframework.data.mongodb.core.query.Criteria;
//import org.springframework.data.mongodb.core.query.Query;
//import org.springframework.test.context.junit4.SpringRunner;
//
//import java.util.List;
//
//@RunWith(SpringRunner.class)
//@SpringBootTest(classes = LyCommentsApplication.class)
//public class LeyouReviewServieApplicationTests {
//
// @Autowired
// private SpitDao spitDAO;
//
// @Autowired
// private MongoTemplate mongoTemplate;
//
// @Test
// public void contextLoads() {
// Spit spit = new Spit();
// spit.set_id("5");
// spit.setContent("123123123");
// spit.setNickname("123123123");
// spit.setUserid("123121");
// spit.setVisits(1234);
// spitDAO.save(spit);
// }
//
// @Test
// public void findTest(){
// Criteria criteria = new Criteria();
// criteria.andOperator(Criteria.where("_id").is("5"),Criteria.where("visits").is(1234));
// List<Spit> spits = this.mongoTemplate.find(new Query(criteria),Spit.class);
// System.out.println("数量:"+spits.size());
// for (Spit spit : spits){
// System.out.println(spit);
// }
// }
//}

@ -0,0 +1,21 @@
<?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">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.parent</groupId>
<artifactId>leyou-comments</artifactId>
<packaging>pom</packaging>
<modules>
<module>leyou-comments-service</module>
<module>leyou-comments-interface</module>
</modules>
</project>

@ -0,0 +1,58 @@
<?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">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.common</groupId>
<artifactId>leyou-common</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!--日志包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,61 @@
package com.leyou.common.pojo;
import java.util.List;
/**
* @author li
* @param <T>
*/
public class PageResult<T> {
/**
*
*/
private Long total;
/**
*
*/
private Long totalPage;
/**
*
*/
private List<T> items;
public PageResult() {
}
public PageResult(Long total, List<T> items) {
this.total = total;
this.items = items;
}
public PageResult(Long total, Long totalPage, List<T> items) {
this.total = total;
this.totalPage = totalPage;
this.items = items;
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<T> getItems() {
return items;
}
public void setItems(List<T> items) {
this.items = items;
}
public Long getTotalPage() {
return totalPage;
}
public void setTotalPage(Long totalPage) {
this.totalPage = totalPage;
}
}

@ -0,0 +1,18 @@
package com.leyou.myexception;
/**
* @Author: 98050
* @Time: 2018-11-05 16:09
* @Feature:
*/
public enum LyException {
/**
*
*/
CATEGORY_NOT_FOUND,
/**
*
*/
BRAND_NOT_FOUND,
}

@ -0,0 +1,13 @@
package com.leyou.myexception;
/**
* @Author: 98050
* @Time: 2018-11-05 16:07
* @Feature:
*/
public class MyException extends RuntimeException {
public MyException(LyException exception) {
super(exception.toString());
}
}

@ -0,0 +1,86 @@
package com.leyou.parameter.pojo;
/**
* @Author: 98050
* Time: 2018-08-08 11:38
* Feature:
*/
public class BrandQueryByPageParameter {
/*
* - pageint
- rowsint
- sortByString
- descboolean
- keyString
* */
private Integer page;
private Integer rows;
private String sortBy;
private Boolean desc;
private String key;
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getRows() {
return rows;
}
public void setRows(Integer rows) {
this.rows = rows;
}
public String getSortBy() {
return sortBy;
}
public void setSortBy(String sortBy) {
this.sortBy = sortBy;
}
public Boolean getDesc() {
return desc;
}
public void setDesc(Boolean desc) {
this.desc = desc;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public BrandQueryByPageParameter(Integer page, Integer rows, String sortBy, Boolean desc, String key) {
this.page = page;
this.rows = rows;
this.sortBy = sortBy;
this.desc = desc;
this.key = key;
}
public BrandQueryByPageParameter(){
super();
}
@Override
public String toString() {
return "BrandQueryByPageParameter{" +
"page=" + page +
", rows=" + rows +
", sortBy='" + sortBy + '\'' +
", desc=" + desc +
", key='" + key + '\'' +
'}';
}
}

@ -0,0 +1,42 @@
package com.leyou.parameter.pojo;
/**
* @Author: 98050
* Time: 2018-08-14 22:19
* Feature:
*/
public class SpuQueryByPageParameter extends BrandQueryByPageParameter{
/**
* - pageint
* - rowsint
* - sortByString
* - descboolean
* - keyString
* - saleable:
*/
private Boolean saleable;
public Boolean getSaleable() {
return saleable;
}
public void setSaleable(Boolean saleable) {
this.saleable = saleable;
}
public SpuQueryByPageParameter(Integer page, Integer rows, String sortBy, Boolean desc, String key, Boolean saleable) {
super(page, rows, sortBy, desc, key);
this.saleable = saleable;
}
public SpuQueryByPageParameter(Boolean saleable) {
this.saleable = saleable;
}
@Override
public String toString() {
return "SpuQueryByPageParameter{" +
"saleable=" + saleable +
'}';
}
}

@ -0,0 +1,81 @@
package com.leyou.response;
/**
* @Author: 98050
* @Time: 2018-11-24 21:37
* @Feature:
*/
public class CodeMsg {
private int code;
private String msg;
/**
*
*/
public static CodeMsg SUCCESS = new CodeMsg(0, "success");
public static CodeMsg SERVER_ERROR = new CodeMsg(500100, "服务端异常");
public static CodeMsg BIND_ERROR = new CodeMsg(500101, "参数校验异常:%s");
public static CodeMsg REQUEST_ILLEGAL = new CodeMsg(500102, "请求非法");
public static CodeMsg ACCESS_LIMIT_REACHED= new CodeMsg(500104, "访问太频繁!");
/**
* 5002XX
*/
public static CodeMsg LOGIN_ERROR = new CodeMsg(500210, "用户未登录");
public static CodeMsg PASSWORD_EMPTY = new CodeMsg(500211, "登录密码不能为空");
public static CodeMsg MOBILE_EMPTY = new CodeMsg(500212, "手机号不能为空");
public static CodeMsg MOBILE_ERROR = new CodeMsg(500213, "手机号格式错误");
public static CodeMsg MOBILE_NOT_EXIST = new CodeMsg(500214, "手机号不存在");
public static CodeMsg PASSWORD_ERROR = new CodeMsg(500215, "密码错误");
//商品模块 5003XX
/**
* 5004XX
*/
public static CodeMsg ORDER_NOT_EXIST = new CodeMsg(500400, "订单不存在");
/**
* 5005XX
*/
public static CodeMsg MIAO_SHA_OVER = new CodeMsg(500500, "商品已经秒杀完毕");
public static CodeMsg REPEATE_MIAOSHA = new CodeMsg(500501, "不能重复秒杀");
public static CodeMsg MIAOSHA_FAIL = new CodeMsg(500502, "秒杀失败");
private CodeMsg( ) {
}
private CodeMsg( int code,String msg ) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public CodeMsg fillArgs(Object... args) {
int code = this.code;
String message = String.format(this.msg, args);
return new CodeMsg(code, message);
}
@Override
public String toString() {
return "CodeMsg [code=" + code + ", msg=" + msg + "]";
}
}

@ -0,0 +1,65 @@
package com.leyou.response;
/**
* @Author: 98050
* @Time: 2018-11-24 21:41
* @Feature:
*/
public class Result<T> {
private int code;
private String msg;
private T data;
/**
*
* */
public static <T> Result<T> success(T data){
Result<T> result = new Result<T>(data);
result.code = CodeMsg.SUCCESS.getCode();
return new Result<T>(data);
}
/**
*
* */
public static <T> Result<T> error(CodeMsg codeMsg){
return new Result<T>(codeMsg);
}
private Result(T data) {
this.data = data;
}
private Result(int code, String msg) {
this.code = code;
this.msg = msg;
}
private Result(CodeMsg codeMsg) {
if(codeMsg != null) {
this.code = codeMsg.getCode();
this.msg = codeMsg.getMsg();
}
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}

@ -0,0 +1,20 @@
package com.leyou.utils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @Author: 98050
* @Time: 2018-10-23 10:49
* @Feature:
*/
public class CodecUtils {
public static String passwordBcryptEncode(String username,String password){
return new BCryptPasswordEncoder().encode(username + password);
}
public static Boolean passwordConfirm(String rawPassword,String encodePassword){
return new BCryptPasswordEncoder().matches(rawPassword,encodePassword);
}
}

@ -0,0 +1,222 @@
package com.leyou.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
*
* Cookie
* @author li
* @time 2018/8/5
*/
public final class CookieUtils {
protected static final Logger logger = LoggerFactory.getLogger(CookieUtils.class);
/**
* Cookie,
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName) {
return getCookieValue(request, cookieName, false);
}
/**
* Cookie
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null){
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
if (isDecoder) {
retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
} else {
retValue = cookieList[i].getValue();
}
break;
}
}
} catch (UnsupportedEncodingException e) {
logger.error("Cookie Decode Error.", e);
}
return retValue;
}
/**
* Cookie,
*
* @param request
* @param cookieName
* @return
*/
public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
Cookie[] cookieList = request.getCookies();
if (cookieList == null || cookieName == null){
return null;
}
String retValue = null;
try {
for (int i = 0; i < cookieList.length; i++) {
if (cookieList[i].getName().equals(cookieName)) {
retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
break;
}
}
} catch (UnsupportedEncodingException e) {
logger.error("Cookie Decode Error.", e);
}
return retValue;
}
/**
* Cookie ,
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue) {
setCookie(request, response, cookieName, cookieValue, -1);
}
/**
* Cookie ,
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage) {
setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
}
/**
* Cookie ,
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, boolean isEncode) {
setCookie(request, response, cookieName, cookieValue, -1, isEncode);
}
/**
* Cookie ,
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
}
/**
* Cookie , ()
*/
public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
}
/**
* Cookiecookie
*/
public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String cookieName) {
doSetCookie(request, response, cookieName, "", -1, false);
}
/**
* Cookie使
*
* @param cookieMaxage
* cookie
*/
private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
try {
if (cookieValue == null) {
cookieValue = "";
} else if (isEncode) {
cookieValue = URLEncoder.encode(cookieValue, "utf-8");
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0) {
cookie.setMaxAge(cookieMaxage);
}
if (null != request) {
// 设置域名的cookie
cookie.setDomain(getDomainName(request));
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
logger.error("Cookie Encode Error.", e);
}
}
/**
* Cookie使
*
* @param cookieMaxage
* cookie
*/
private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
try {
if (cookieValue == null) {
cookieValue = "";
} else {
cookieValue = URLEncoder.encode(cookieValue, encodeString);
}
Cookie cookie = new Cookie(cookieName, cookieValue);
if (cookieMaxage > 0) {
cookie.setMaxAge(cookieMaxage);
}
if (null != request){
// 设置域名的cookie
cookie.setDomain(getDomainName(request));
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
logger.error("Cookie Encode Error.", e);
}
}
/**
* cookie
*/
private static final String getDomainName(HttpServletRequest request) {
String domainName = null;
String serverName = request.getRequestURL().toString();
if (serverName == null || serverName.equals("")) {
domainName = "";
} else {
serverName = serverName.toLowerCase();
serverName = serverName.substring(7);
final int end = serverName.indexOf("/");
serverName = serverName.substring(0, end);
final String[] domains = serverName.split("\\.");
int len = domains.length;
if (len > 3) {
// www.xxx.com.cn
domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
} else if (len <= 3 && len > 1) {
// xxx.com or xxx.cn
domainName = domains[len - 2] + "." + domains[len - 1];
} else {
domainName = serverName;
}
}
if (domainName != null && domainName.indexOf(":") > 0) {
String[] ary = domainName.split("\\:");
domainName = ary[0];
}
return domainName;
}
}

@ -0,0 +1,187 @@
package com.leyou.utils;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
/**
* <p>IdWorker.java</p>
* <p>ID</p>
* <pre>
* Twitter Snowflake JAVA
* </pre>
* IdWorker0
* 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
* 使long41
* 5datacenter5ID线
* 1264Long
* IDdatacenterID
* snowflake26ID
* <p>
* 64ID (42()+5(ID)+5()+12())
*
* @author Polim
*/
public class IdWorker {
/**
*
*/
private final static long twepoch = 1288834974657L;
/**
*
*/
private final static long workerIdBits = 5L;
/**
*
*/
private final static long datacenterIdBits = 5L;
/**
* ID
*/
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
/**
* ID
*/
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
/**
*
*/
private final static long sequenceBits = 12L;
/**
* ID12
*/
private final static long workerIdShift = sequenceBits;
/**
* ID17
*/
private final static long datacenterIdShift = sequenceBits + workerIdBits;
/**
* 22
*/
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
/**
* id
*/
private static long lastTimestamp = -1L;
/**
*
*/
private long sequence = 0L;
private final long workerId;
/**
* id
*/
private final long datacenterId;
public IdWorker(){
this.datacenterId = getDatacenterId(maxDatacenterId);
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}
/**
* @param workerId
* ID
* @param datacenterId
*
*/
public IdWorker(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* ID
*
* @return
*/
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
// 当前毫秒内,则+1
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 当前毫秒内计数满了,则等待下一秒
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
// ID偏移组合生成最终的ID并返回ID
long nextId = ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift) | sequence;
return nextId;
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
/**
* <p>
* maxWorkerId
* </p>
*/
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
StringBuffer mpid = new StringBuffer();
mpid.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (!name.isEmpty()) {
/*
* GET jvmPid
*/
mpid.append(name.split("@")[0]);
}
/*
* MAC + PID hashcode 16
*/
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}
/**
* <p>
* id
* </p>
*/
protected static long getDatacenterId(long maxDatacenterId) {
long id = 0L;
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
id = ((0x000000FF & (long) mac[mac.length - 1])
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
} catch (Exception e) {
System.out.println(" getDatacenterId: " + e.getMessage());
}
return id;
}
}

@ -0,0 +1,79 @@
package com.leyou.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.istack.internal.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author: li
* @create: 2018-04-24 17:20
**/
public class JsonUtils {
public static final ObjectMapper mapper = new ObjectMapper();
private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
@Nullable
public static String serialize(Object obj) {
if (obj == null) {
return null;
}
if (obj.getClass() == String.class) {
return (String) obj;
}
try {
return mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
logger.error("json序列化出错" + obj, e);
return null;
}
}
@Nullable
public static <T> T parse(String json, Class<T> tClass) {
try {
return mapper.readValue(json, tClass);
} catch (IOException e) {
logger.error("json解析出错" + json, e);
return null;
}
}
@Nullable
public static <E> List<E> parseList(String json, Class<E> eClass) {
try {
return mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, eClass));
} catch (IOException e) {
logger.error("json解析出错" + json, e);
return null;
}
}
@Nullable
public static <K, V> Map<K, V> parseMap(String json, Class<K> kClass, Class<V> vClass) {
try {
return mapper.readValue(json, mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass));
} catch (IOException e) {
logger.error("json解析出错" + json, e);
return null;
}
}
@Nullable
public static <T> T nativeRead(String json, TypeReference<T> type) {
try {
return mapper.readValue(json, type);
} catch (IOException e) {
logger.error("json解析出错" + json, e);
return null;
}
}
}

@ -0,0 +1,75 @@
package com.leyou.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author: 98050
* @create: 2018-04-25 09:13
**/
public class NumberUtils {
public static boolean isInt(Double num) {
return num.intValue() == num;
}
/**
*
* @param str
* @return
*/
public static boolean isDigit(String str){
if(str == null || str.trim().equals("")){
return false;
}
return str.matches("^\\d+$");
}
/**
*
* @param num
* @param scale
* @return
*/
public static double scale(double num, int scale) {
BigDecimal bd = new BigDecimal(num);
return bd.setScale(scale, RoundingMode.HALF_UP).doubleValue();
}
/**
*
* @param value
* @param regex
* @return
*/
public static Double[] searchNumber(String value, String regex){
List<Double> doubles = new ArrayList<>();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(value);
if(matcher.find()) {
MatchResult result = matcher.toMatchResult();
for (int i = 1; i <= result.groupCount(); i++) {
doubles.add(Double.valueOf(result.group(i)));
}
}
return doubles.toArray(new Double[doubles.size()]);
}
/**
*
* @param len
* @return
*/
public static String generateCode(int len){
len = Math.min(len, 8);
int min = Double.valueOf(Math.pow(10, len - 1)).intValue();
int num = new Random().nextInt(Double.valueOf(Math.pow(10, len + 1)).intValue() - 1) + min;
return String.valueOf(num).substring(0,len);
}
}

@ -0,0 +1,16 @@
package com.leyou.utils;
import java.util.Arrays;
import java.util.List;
/**
* Author: 98050
* Time: 2018-08-05 15:58
* Feature:
*/
public class Test {
public static void main(String[] args) {
List<Integer> lis = Arrays.asList(1, 2, 3);
lis.forEach(num -> System.out.println(num));
}
}

@ -0,0 +1,65 @@
<?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">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.config</groupId>
<artifactId>leyou-config</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- docker的maven插件官网 https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>47.104.175.20:5000/${project.artifactId}:${project.version}</imageName>
<baseImage>jdk1.8</baseImage>
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://47.104.175.20:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,19 @@
package com.leyou.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
/**
* @Author: 98050
* @Time: 2018-11-28 16:39
* @Feature:
*/
@EnableConfigServer
@SpringBootApplication
public class LyConfigApplication {
public static void main(String[] args) {
SpringApplication.run(LyConfigApplication.class,args);
}
}

@ -0,0 +1,27 @@
package com.leyou.config.myconfig;
import come.leyou.config.filter.MyFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author: 98050
* @Time: 2018-11-30 20:56
* @Feature:
*/
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Bean
public FilterRegistrationBean someFilterRegistration1() {
//新建过滤器注册类
FilterRegistrationBean registration = new FilterRegistrationBean();
// 添加我们写好的过滤器
registration.setFilter( new MyFilter());
// 设置过滤器的URL模式
registration.addUrlPatterns("/*");
return registration;
}
}

@ -0,0 +1,44 @@
package come.leyou.config.filter;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/**
* @author 98050
*/
public class CustometRequestWrapper extends HttpServletRequestWrapper {
public CustometRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
byte[] bytes = new byte[0];
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return byteArrayInputStream.read() == -1 ? true:false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
}

@ -0,0 +1,47 @@
package come.leyou.config.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: 98050
* @Time: 2018-11-30 20:59
* @Feature:
*/
public class MyFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(MyFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("过滤器启动");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
String url = httpServletRequest.getRequestURI();
//过滤/actuator/bus-refresh请求
String suffix = "/bus-refresh";
if (!url.endsWith(suffix)){
filterChain.doFilter(servletRequest,servletResponse);
return;
}
CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);
filterChain.doFilter(requestWrapper,servletResponse);
}
@Override
public void destroy() {
logger.info("过滤器销毁");
}
}

@ -0,0 +1,22 @@
server:
port: 10011
spring:
application:
name: leyou-config
cloud:
config:
server:
git:
uri: https://github.com/lyj8330328/leyou-config.git
rabbitmq:
host: 192.168.19.121
username: /leyou
password: leyou
virtual-host: /leyou
management: #暴露触发消息总线的地址
endpoints:
web:
exposure:
include: bus-refresh

@ -0,0 +1,108 @@
<?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">
<parent>
<artifactId>leyou</artifactId>
<groupId>com.leyou.parent</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.leyou.goods</groupId>
<artifactId>leyou-goods-web</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.leyou.item.interface</groupId>
<artifactId>leyou-item-interface</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!--配置管理依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<build>
<finalName>app</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- docker的maven插件官网 https://github.com/spotify/docker-maven-plugin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<imageName>47.104.175.20:5000/${project.artifactId}:${project.version}</imageName>
<baseImage>jdk1.8</baseImage>
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<dockerHost>http://47.104.175.20:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,22 @@
package com.leyou;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @Author: 98050
* Time: 2018-10-17 11:10
* Feature: fegin
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class LyGoodsWebApplication {
public static void main(String[] args) {
SpringApplication.run(LyGoodsWebApplication.class,args);
}
}

@ -0,0 +1,14 @@
package com.leyou.client;
/**
* @Author: 98050
* Time: 2018-10-17 18:59
* Feature:FeignClient
*/
import com.leyou.item.api.BrandApi;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(value = "item-service")
public interface BrandClient extends BrandApi {
}

@ -0,0 +1,13 @@
package com.leyou.client;
import com.leyou.item.api.CategoryApi;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @Author: 98050
* Time: 2018-10-17 19:01
* Feature:FeignClient
*/
@FeignClient(value = "item-service")
public interface CategoryClient extends CategoryApi {
}

@ -0,0 +1,13 @@
package com.leyou.client;
import com.leyou.item.api.GoodsApi;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @Author: 98050
* Time: 2018-10-17 18:55
* Feature:FeignClient
*/
@FeignClient(value = "item-service")
public interface GoodsClient extends GoodsApi {
}

@ -0,0 +1,13 @@
package com.leyou.client;
import com.leyou.item.api.SpecApi;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @Author: 98050
* Time: 2018-10-17 19:01
* Feature:spec FeignClient
*/
@FeignClient(value = "item-service")
public interface SpecClient extends SpecApi {
}

@ -0,0 +1,13 @@
package com.leyou.client;
import com.leyou.item.api.SpuApi;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @Author: 98050
* Time: 2018-10-17 19:02
* Feature:
*/
@FeignClient(value = "item-service")
public interface SpuClient extends SpuApi {
}

@ -0,0 +1,79 @@
package com.leyou.controller;
import com.leyou.service.GoodsHtmlService;
import com.leyou.service.GoodsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.spring5.context.webflux.SpringWebFluxContext;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* @Author: 98050
* Time: 2018-10-17 16:06
* Feature:
*/
@Controller
@RequestMapping("item")
public class GoodsController {
@Autowired
private GoodsService goodsService;
@Autowired
private GoodsHtmlService goodsHtmlService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private ThymeleafViewResolver thymeleafViewResolver;
private static String KEY_PREFIX = "leyou:goods:detail:";
@GetMapping(value = "{id}.html",produces = "text/html")
@ResponseBody
public String toItemPage(HttpServletRequest request, HttpServletResponse response, Model model, @PathVariable("id")String id) throws InterruptedException, ExecutionException {
Long idN = Long.parseLong(id);
//加载数据
Map<String, Object> modelMap = this.goodsService.loadModel(idN);
//把数据放入模型中
model.addAllAttributes(modelMap);
//页面静态化
// this.goodsHtmlService.asyncExecute(idN);
// return "item";
BoundHashOperations<String,Object,Object> hashOperations = this.stringRedisTemplate.boundHashOps(KEY_PREFIX+id);
String html = (String) hashOperations.get(id);
/**
*
*/
if (StringUtils.isNotEmpty(html)){
//不空,则返回
return html;
}
//手动渲染模板
WebContext context = new WebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap());
html = thymeleafViewResolver.getTemplateEngine().process("item",context);
if (StringUtils.isNotEmpty(html)){
//不空,放入缓存
//设置有效期60秒
hashOperations.put(id,html);
hashOperations.expire(60, TimeUnit.SECONDS);
}
return html;
}
}

@ -0,0 +1,64 @@
package com.leyou.listener;
import com.leyou.service.GoodsHtmlService;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Author: 98050
* @Time: 2018-10-21 14:45
* @Feature: mq
*/
@Component
public class GoodsListener {
@Autowired
private GoodsHtmlService goodsHtmlService;
/**
* insertupdate
* @param id
* @throws Exception
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "leyou.create.web.queue",durable = "true"), //队列持久化
exchange = @Exchange(
value = "leyou.item.exchange",
ignoreDeclarationExceptions = "true",
type = ExchangeTypes.TOPIC
),
key = {"item.insert","item.update"}
))
public void listenCreate(Long id) throws Exception{
if (id == null){
return;
}
//创建或更新索引
this.goodsHtmlService.createHtml(id);
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "leyou.delete.web.queue",durable = "true"), //队列持久化
exchange = @Exchange(
value = "leyou.item.exchange",
ignoreDeclarationExceptions = "true",
type = ExchangeTypes.TOPIC
),
key = {"item.delete"}
))
public void listenDelete(Long id){
if (id == null){
return;
}
//删除索引
this.goodsHtmlService.deleteHtml(id);
}
}

@ -0,0 +1,29 @@
package com.leyou.service;
import java.util.concurrent.ExecutionException;
/**
* @Author: 98050
* @Time: 2018-10-19 09:40
* @Feature:
*/
public interface GoodsHtmlService {
/**
* html
* @param spuId
*/
void createHtml(Long spuId) throws InterruptedException, ExecutionException;
/**
* 线Controller
* @param spuId
*/
void asyncExecute(Long spuId);
/**
* html
* @param id
*/
void deleteHtml(Long id);
}

@ -0,0 +1,18 @@
package com.leyou.service;
import java.util.Map;
import java.util.concurrent.ExecutionException;
/**
* @Author: 98050
* Time: 2018-10-17 19:27
* Feature:
*/
public interface GoodsService {
/**
*
* @param spuId
* @return
*/
Map<String,Object> loadModel(Long spuId) throws InterruptedException, ExecutionException;
}

@ -0,0 +1,86 @@
package com.leyou.service.impl;
import com.leyou.service.GoodsHtmlService;
import com.leyou.service.GoodsService;
import com.leyou.utils.ThreadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.ExecutionException;
/**
* @Author: 98050
* @Time: 2018-10-19 09:46
* @Feature:
*/
@Service
public class GoodsHtmlServiceImpl implements GoodsHtmlService {
@Autowired
private GoodsService goodsService;
@Autowired
private TemplateEngine templateEngine;
private static final Logger LOGGER = LoggerFactory.getLogger(GoodsHtmlService.class);
@Override
public void createHtml(Long spuId) throws InterruptedException, ExecutionException {
PrintWriter writer = null;
//获取页面数据
Map<String,Object> spuMap = this.goodsService.loadModel(spuId);
//创建Thymeleaf上下文对象
Context context = new Context();
//把数据放入上下文对象
context.setVariables(spuMap);
//创建输出流
File file = new File("D:\\nginx-1.12.2\\html\\item\\"+spuId+".html");
try {
writer = new PrintWriter(file);
//执行页面静态化方法
templateEngine.process("item",context,writer);
} catch (FileNotFoundException e) {
LOGGER.error("页面静态化出错:{}"+e,spuId);
}finally {
if (writer != null){
writer.close();
}
}
}
/**
* 线
* @param spuId
*/
@Override
public void asyncExecute(Long spuId) {
ThreadUtils.execute(() -> {
try {
createHtml(spuId);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
}
@Override
public void deleteHtml(Long id) {
File file = new File("D:\\nginx-1.12.2\\html\\item\\"+id+".html");
file.deleteOnExit();
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save