瀏覽代碼

初始化

詹子聪 5 年之前
當前提交
24bf3f4f07
共有 62 個文件被更改,包括 3931 次插入0 次删除
  1. 7 0
      .gitignore
  2. 2 0
      META-INF/MANIFEST.MF
  3. 194 0
      libs/UnlimitedJCEPolicy/README.txt
  4. 二進制
      libs/UnlimitedJCEPolicy/US_export_policy.jar
  5. 二進制
      libs/UnlimitedJCEPolicy/local_policy.jar
  6. 二進制
      libs/jsoup-1.13.1.jar
  7. 二進制
      libs/mail-1.5.0-b01.jar
  8. 150 0
      pom.xml
  9. 5 0
      src/main/java/com/miekir/shibei/ToDo.java
  10. 81 0
      src/main/java/com/miekir/shibei/bean/CouponBean.java
  11. 57 0
      src/main/java/com/miekir/shibei/bean/Feedback.java
  12. 161 0
      src/main/java/com/miekir/shibei/bean/GoodsBean.java
  13. 28 0
      src/main/java/com/miekir/shibei/bean/JsonBean.java
  14. 40 0
      src/main/java/com/miekir/shibei/bean/ResponseResult.java
  15. 17 0
      src/main/java/com/miekir/shibei/bean/ResultCode.java
  16. 25 0
      src/main/java/com/miekir/shibei/bean/SystemBean.java
  17. 32 0
      src/main/java/com/miekir/shibei/bean/UpgradeBean.java
  18. 217 0
      src/main/java/com/miekir/shibei/bean/User.java
  19. 25 0
      src/main/java/com/miekir/shibei/bean/WeatherBean.java
  20. 22 0
      src/main/java/com/miekir/shibei/bean/YijiBean.java
  21. 5 0
      src/main/java/com/miekir/shibei/constants/ServerConstants.java
  22. 144 0
      src/main/java/com/miekir/shibei/controller/api/CouponController.java
  23. 178 0
      src/main/java/com/miekir/shibei/controller/api/GoodsController.java
  24. 197 0
      src/main/java/com/miekir/shibei/controller/api/JsonController.java
  25. 166 0
      src/main/java/com/miekir/shibei/controller/api/SystemController.java
  26. 383 0
      src/main/java/com/miekir/shibei/controller/api/UserController.java
  27. 18 0
      src/main/java/com/miekir/shibei/controller/web/ShibeiController.java
  28. 43 0
      src/main/java/com/miekir/shibei/interceptor/AuthInterceptor.java
  29. 77 0
      src/main/java/com/miekir/shibei/model/BlogEntity.java
  30. 91 0
      src/main/java/com/miekir/shibei/model/UserEntity.java
  31. 42 0
      src/main/java/com/miekir/shibei/repository/CouponRepository.java
  32. 14 0
      src/main/java/com/miekir/shibei/repository/FeedbackRepository.java
  33. 47 0
      src/main/java/com/miekir/shibei/repository/GoodsRepository.java
  34. 20 0
      src/main/java/com/miekir/shibei/repository/JsonRepository.java
  35. 21 0
      src/main/java/com/miekir/shibei/repository/SystemRepository.java
  36. 21 0
      src/main/java/com/miekir/shibei/repository/UpgradeRepository.java
  37. 49 0
      src/main/java/com/miekir/shibei/repository/UserRepository.java
  38. 33 0
      src/main/java/com/miekir/shibei/tool/CodeGenerator.java
  39. 14 0
      src/main/java/com/miekir/shibei/tool/DateTool.java
  40. 43 0
      src/main/java/com/miekir/shibei/tool/MD5Tool.java
  41. 62 0
      src/main/java/com/miekir/shibei/tool/RequestTool.java
  42. 31 0
      src/main/java/com/miekir/shibei/tool/StringTool.java
  43. 24 0
      src/main/java/com/miekir/shibei/tool/TextUtils.java
  44. 38 0
      src/main/java/com/miekir/shibei/tool/TokenGenerator.java
  45. 278 0
      src/main/java/com/miekir/shibei/tool/WebTool.java
  46. 17 0
      src/main/java/com/miekir/shibei/tool/email/EmailAuthenticator.java
  47. 154 0
      src/main/java/com/miekir/shibei/tool/email/EmailTool.java
  48. 109 0
      src/main/java/com/miekir/shibei/tool/secure/SecureManager.java
  49. 37 0
      src/main/resources/META-INF/persistence.xml
  50. 0 0
      src/main/resources/application.properties
  51. 39 0
      src/main/resources/spring_mvc_user.sql
  52. 105 0
      src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
  53. 41 0
      src/main/webapp/WEB-INF/web.xml
  54. 5 0
      src/main/webapp/css/bootstrap.min.css
  55. 59 0
      src/main/webapp/html/addUser.jsp
  56. 39 0
      src/main/webapp/html/index.jsp
  57. 66 0
      src/main/webapp/html/updateUser.jsp
  58. 60 0
      src/main/webapp/html/userDetail.jsp
  59. 78 0
      src/main/webapp/html/userManage.jsp
  60. 7 0
      src/main/webapp/js/bootstrap.min.js
  61. 6 0
      src/main/webapp/js/jquery.min.js
  62. 7 0
      注意.txt

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+target/
+
+
+# Intellij
+.idea/
+*.iml
+*.iws

+ 2 - 0
META-INF/MANIFEST.MF

@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+

+ 194 - 0
libs/UnlimitedJCEPolicy/README.txt

@@ -0,0 +1,194 @@
+
+   Unlimited Strength Java(TM) Cryptography Extension Policy Files
+  for the Java(TM) Platform, Standard Edition Runtime Environment 7
+
+                               README
+
+----------------------------------------------------------------------
+CONTENTS
+----------------------------------------------------------------------
+
+     o Introduction
+     o License and Terms
+     o Understanding The Export/Import Issues
+     o Where To Find Documentation
+     o Installation
+     o Questions, Support, Reporting Bugs
+
+
+----------------------------------------------------------------------
+Introduction
+----------------------------------------------------------------------
+
+Thank you for downloading the Unlimited Strength Java(TM) Cryptography
+Extension (JCE) Policy Files for the Java(TM) Platform, Standard
+Edition (Java SE) Runtime Environment 7.
+
+Due to import control restrictions of some countries, the version of
+the JCE policy files that are bundled in the Java Runtime Environment,
+or JRE(TM), 7 environment allow "strong" but limited cryptography to be
+used. This download bundle (the one including this README file)
+provides "unlimited strength" policy files which contain no
+restrictions on cryptographic strengths.
+
+Please note that this download file does NOT contain any encryption
+functionality as all such functionality is contained within Oracle's
+JRE 7. This bundles assumes that the JRE 7 has already been installed.
+
+
+----------------------------------------------------------------------
+License and Terms
+----------------------------------------------------------------------
+
+This download bundle is part of the Java SE Platform products and is
+governed by same License and Terms notices. These notices can be found
+on the Java SE download site:
+
+    http://www.oracle.com/technetwork/java/javase/documentation/index.html
+
+
+----------------------------------------------------------------------
+Understanding The Export/Import Issues
+----------------------------------------------------------------------
+
+JCE for Java SE 7 has been through the U.S. export review process.  The
+JCE framework, along with the various JCE providers that come standard
+with it (SunJCE, SunEC, SunPKCS11, SunMSCAPI, etc), is exportable.
+
+The JCE architecture allows flexible cryptographic strength to be
+configured via jurisdiction policy files. Due to the import
+restrictions of some countries, the jurisdiction policy files
+distributed with the Java SE 7 software have built-in restrictions on
+available cryptographic strength. The jurisdiction policy files in this
+download bundle (the bundle including this README file) contain no
+restrictions on cryptographic strengths.  This is appropriate for most
+countries. Framework vendors can create download bundles that include
+jurisdiction policy files that specify cryptographic restrictions
+appropriate for countries whose governments mandate restrictions. Users
+in those countries can download an appropriate bundle, and the JCE
+framework will enforce the specified restrictions.
+
+You are advised to consult your export/import control counsel or
+attorney to determine the exact requirements.
+
+
+----------------------------------------------------------------------
+Where To Find Documentation
+----------------------------------------------------------------------
+
+The following documents may be of interest to you:
+
+    o  The Java(TM) Cryptography Architecture (JCA) Reference Guide at:
+
+       http://download.oracle.com/javase/7/docs/technotes/guides/security
+
+    o  The Java SE Security web site has more information about JCE,
+       plus additional information about the Java SE Security Model.
+       Please see:
+
+       http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136007.html
+
+
+----------------------------------------------------------------------
+Installation
+----------------------------------------------------------------------
+
+Notes:
+
+  o Unix (Solaris/Linux) and Windows use different pathname separators,
+    so please use the appropriate one ("\", "/") for your environment.
+
+  o <java-home> (below) refers to the directory where the JRE was
+    installed. It is determined based on whether you are running JCE
+    on a JRE or a JRE contained within the Java Development Kit, or
+    JDK(TM). The JDK contains the JRE, but at a different level in the
+    file hierarchy. For example, if the JDK is installed in
+    /home/user1/jdk1.7.0 on Unix or in C:\jdk1.7.0 on Windows, then
+    <java-home> is:
+
+        /home/user1/jdk1.7.0/jre           [Unix]
+        C:\jdk1.7.0\jre                    [Windows]
+
+    If on the other hand the JRE is installed in /home/user1/jre1.7.0
+    on Unix or in C:\jre1.7.0 on Windows, and the JDK is not
+    installed, then <java-home> is:
+
+        /home/user1/jre1.7.0               [Unix]
+        C:\jre1.7.0                        [Windows]
+
+  o On Windows, for each JDK installation, there may be additional
+    JREs installed under the "Program Files" directory. Please make
+    sure that you install the unlimited strength policy JAR files
+    for all JREs that you plan to use.
+
+
+Here are the installation instructions:
+
+1)  Download the unlimited strength JCE policy files.
+
+2)  Uncompress and extract the downloaded file.
+
+    This will create a subdirectory called jce.
+    This directory contains the following files:
+
+        README.txt                   This file
+        local_policy.jar             Unlimited strength local policy file
+        US_export_policy.jar         Unlimited strength US export policy file
+
+3)  Install the unlimited strength policy JAR files.
+
+    In case you later decide to revert to the original "strong" but
+    limited policy versions, first make a copy of the original JCE
+    policy files (US_export_policy.jar and local_policy.jar). Then
+    replace the strong policy files with the unlimited strength
+    versions extracted in the previous step.
+
+    The standard place for JCE jurisdiction policy JAR files is:
+
+        <java-home>/lib/security           [Unix]
+        <java-home>\lib\security           [Windows]
+
+
+-----------------------------------------------------------------------
+Questions, Support, Reporting Bugs
+-----------------------------------------------------------------------
+
+Questions
+---------
+
+For miscellaneous questions about JCE usage and deployment, we
+encourage you to read:
+
+    o Information on the Java SE Security web site
+
+      http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136007.html
+
+    o The Oracle Online Community Forums, specifically the Java
+      Cryptography forum. The forums allow you to tap into the
+      experience of other users, ask questions, or offer tips to others
+      on a variety of Java-related topics, including JCE. There is no
+      fee to participate.
+
+      http://forums.oracle.com/
+      http://forums.oracle.com/forums/forum.jspa?forumID=964  (JCE
+      forum)
+
+
+Support
+-------
+
+For more extensive JCE questions or deployment issues, please contact
+our Technical Support staff at:
+
+    http://support.oracle.com
+
+
+Reporting Bugs
+--------------
+
+To report bugs (with sample code) or request a feature, please see:
+
+    http://bugreport.sun.com/bugreport/
+
+Bug reports with specific, reproducible test cases are greatly
+appreciated!

二進制
libs/UnlimitedJCEPolicy/US_export_policy.jar


二進制
libs/UnlimitedJCEPolicy/local_policy.jar


二進制
libs/jsoup-1.13.1.jar


二進制
libs/mail-1.5.0-b01.jar


+ 150 - 0
pom.xml

@@ -0,0 +1,150 @@
+<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/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.cenyol</groupId>
+    <artifactId>shibei</artifactId>
+    <packaging>war</packaging>
+    <version>1.0-SNAPSHOT</version>
+    <name>example Maven Webapp</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <spring.version>4.2.5.RELEASE</spring.version>
+        <spring-data.version>1.2.0.RELEASE</spring-data.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet.jsp</groupId>
+            <artifactId>jsp-api</artifactId>
+            <version>2.1</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <version>${spring.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>jstl</groupId>
+            <artifactId>jstl</artifactId>
+            <version>1.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-jpa</artifactId>
+            <version>${spring-data.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+            <version>1.0.0.Final</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+            <version>3.6.10.Final</version>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.34</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>20080701</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-nop</artifactId>
+            <version>1.8.0-alpha2</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.73</version>
+        </dependency>
+
+        <!--发邮件-->
+        <!-- https://mvnrepository.com/artifact/javax.mail/javax.mail-api -->
+        <!--<dependency>
+          <groupId>javax.mail</groupId>
+          <artifactId>javax.mail-api</artifactId>
+          <version>1.5.0</version>
+        </dependency>-->
+
+        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.3.3</version>
+        </dependency>
+
+
+        <!--解析接收到的json-->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.1.4</version>
+        </dependency>
+
+
+    </dependencies>
+
+    <build>
+        <finalName>shibei</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>6</source>
+                    <target>6</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 5 - 0
src/main/java/com/miekir/shibei/ToDo.java

@@ -0,0 +1,5 @@
+package com.miekir.shibei;
+
+public interface ToDo {
+    // 权限拦截 YES
+}

+ 81 - 0
src/main/java/com/miekir/shibei/bean/CouponBean.java

@@ -0,0 +1,81 @@
+package com.miekir.shibei.bean;
+
+
+import javax.persistence.*;
+
+/**
+ *
+ *
+ * @author Miekir
+ * @date 2020/7/7 19:37
+ * Description: 优惠券实体
+ */
+@Entity
+@Table(name = "t_coupon", schema = "shibei", catalog = "")
+public class CouponBean {
+    /**
+     * 模板Id
+     */
+    @Id
+    @GeneratedValue(strategy= GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = false)
+    public long id;
+
+    /**
+     * 模板类型
+     */
+    @Basic
+    @Column(name = "couponType", nullable = true, insertable = true, updatable = true)
+    public int couponType;
+
+    /**
+     * 模板名称
+     */
+    @Basic
+    @Column(name = "couponName", nullable = true, insertable = true, updatable = true)
+    public String couponName;
+
+    /**
+     * 点击之后跳转的链接
+     */
+    @Basic
+    @Column(columnDefinition = "MEDIUMTEXT", name = "jumpUrl", nullable = true, insertable = true, updatable = true)
+    public String jumpUrl;
+
+    /**
+     * 封面图片URL
+     */
+    @Basic
+    @Column(columnDefinition = "MEDIUMTEXT", name = "coverUrl", nullable = true, insertable = true, updatable = true)
+    public String coverUrl;
+
+    /**
+     * 是否可以响应点击
+     */
+    @Basic
+    @Column(name = "actionEnable", nullable = true, insertable = true, updatable = true)
+    public boolean actionEnable;
+
+    /**是否是本地写死的数据*/
+    @Basic
+    @Column(name = "isLocal", nullable = true, insertable = true, updatable = true)
+    public boolean isLocal;
+
+    /**
+     * 创建时间
+     */
+    @Basic
+    @Column(name = "createTimeMillis", nullable = true, insertable = true, updatable = true)
+    public long createTimeMillis;
+
+    /**
+     * 更新时间
+     */
+    @Basic
+    @Column(name = "updateTimeMillis", nullable = true, insertable = true, updatable = true)
+    public long updateTimeMillis;
+
+    /*columnDefinition = "MEDIUMTEXT"可以解决文字太长保存不进去的bug
+    @Basic
+    @Column(columnDefinition = "MEDIUMTEXT", name = "content", nullable = true, insertable = true, updatable = true)*/
+}

+ 57 - 0
src/main/java/com/miekir/shibei/bean/Feedback.java

@@ -0,0 +1,57 @@
+package com.miekir.shibei.bean;
+
+import javax.persistence.*;
+
+/**
+ * Created by Jason on 2018/8/26.
+ */
+@Entity
+@Table(name = "t_feedback", schema = "shibei", catalog = "")
+public class Feedback {
+    private Integer id;
+    private String email;
+    private String feedback;
+    private Long time;
+
+    // Id自增,注意,一个表只能有一个主键,否则服务器会报500错误,启动失败
+    @Id
+    @GeneratedValue(strategy=GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = true)
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+
+    @Column(name = "email", nullable = false, insertable = true, updatable = true, length = 50)
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    @Basic
+    @Column(name = "feedback", nullable = true, insertable = true, updatable = true)
+    public String getFeedback() {
+        return feedback;
+    }
+
+    public void setFeedback(String feedback) {
+        this.feedback = feedback;
+    }
+
+    @Basic
+    @Column(name = "time", nullable = true, insertable = true, updatable = true)
+    public Long getTime() {
+        return time;
+    }
+
+    public void setTime(Long time) {
+        this.time = time;
+    }
+}

+ 161 - 0
src/main/java/com/miekir/shibei/bean/GoodsBean.java

@@ -0,0 +1,161 @@
+package com.miekir.shibei.bean;
+
+import javax.persistence.*;
+
+/**
+ *
+ *
+ * @author Miekir
+ * @date 2020/7/5 21:50
+ * Description: 商品实体
+ */
+@Entity
+@Table(name = "t_goods", schema = "shibei", catalog = "")
+public class GoodsBean {
+    public static final int TYPE_RECOMMEND = 0;
+    public static final int TYPE_TECHNOLOGY = 1;
+    public static final int TYPE_LIFE = 2;
+    public static final int TYPE_NETWORK = 3;
+
+    @Id
+    @GeneratedValue(strategy= GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = false)
+    public long id;
+
+
+    /**
+     * 封面图片地址
+     */
+    @Basic
+    @Column(columnDefinition = "MEDIUMTEXT", name = "coverImageUrl", nullable = true, insertable = true, updatable = true)
+    public String coverImageUrl;
+
+    /**
+     * 视频地址
+     */
+    @Basic
+    @Column(columnDefinition = "MEDIUMTEXT", name = "videoUrl", nullable = true, insertable = true, updatable = true)
+    public String videoUrl;
+
+    /**
+     * 标题
+     */
+    @Basic
+    @Column(name = "title", nullable = true, insertable = true, updatable = true)
+    public String title;
+    /**
+     * 商品描述
+     */
+    @Basic
+    @Column(name = "description", nullable = true, insertable = true, updatable = true)
+    public String description;
+    /**
+     * 商品推荐理由(一句话推荐、推荐者心声)
+     */
+    @Basic
+    @Column(name = "reason", nullable = true, insertable = true, updatable = true)
+    public String reason;
+    /**
+     * 原价
+     */
+    @Basic
+    @Column(name = "oldPrice", nullable = true, insertable = true, updatable = true)
+    public long oldPrice;
+    /**
+     * 现价
+     */
+    @Basic
+    @Column(name = "nowPrice", nullable = true, insertable = true, updatable = true)
+    public long nowPrice;
+    /**
+     * 返利
+     */
+    @Basic
+    @Column(name = "rebate", nullable = true, insertable = true, updatable = true)
+    public long rebate;
+    /**
+     * 店名
+     */
+    @Basic
+    @Column(name = "shopName", nullable = true, insertable = true, updatable = true)
+    public String shopName;
+    /**
+     * 商店所属省份
+     */
+    @Basic
+    @Column(name = "province", nullable = true, insertable = true, updatable = true)
+    public String province;
+    /**
+     * 是否自营
+     */
+    @Basic
+    @Column(name = "isSelfBusiness", nullable = true, insertable = true, updatable = true)
+    public boolean isSelfBusiness;
+    /**
+     * 是否有券
+     */
+    @Basic
+    @Column(name = "hasCoupon", nullable = true, insertable = true, updatable = true)
+    public boolean hasCoupon;
+    /**
+     * 优惠券信息
+     */
+    @Basic
+    @Column(name = "couponInfo", nullable = true, insertable = true, updatable = true)
+    public String couponInfo;
+    /**
+     * 所属类型
+     */
+    @Basic
+    @Column(name = "goodsType", nullable = true, insertable = true, updatable = true)
+    public int goodsType;
+    /**
+     * 商品链接
+     */
+    @Basic
+    @Column(columnDefinition = "MEDIUMTEXT", name = "goodsUrl", nullable = true, insertable = true, updatable = true)
+    public String goodsUrl;
+    /**
+     * 月销量
+     */
+    @Basic
+    @Column(name = "salesPerMonth", nullable = true, insertable = true, updatable = true)
+    public long salesPerMonth;
+
+    /**
+     * 评论条数
+     */
+    @Basic
+    @Column(name = "commentNum", nullable = true, insertable = true, updatable = true)
+    public long commentNum;
+
+    /**
+     * 好评率
+     */
+    @Basic
+    @Column(name = "goodCommentPercent", nullable = true, insertable = true, updatable = true)
+    public double goodCommentPercent;
+
+    /**
+     * 创建时间
+     */
+    @Basic
+    @Column(name = "createTimeMillis", nullable = true, insertable = true, updatable = true)
+    public long createTimeMillis;
+
+    /**
+     * 更新时间
+     */
+    @Basic
+    @Column(name = "updateTimeMillis", nullable = true, insertable = true, updatable = true)
+    public long updateTimeMillis;
+
+    @Basic
+    @Column(name = "enable", nullable = true, insertable = true, updatable = true)
+    public boolean enable;
+
+    /**是否是本地写死的数据*/
+    @Basic
+    @Column(name = "isLocal", nullable = true, insertable = true, updatable = true)
+    public boolean isLocal;
+}

+ 28 - 0
src/main/java/com/miekir/shibei/bean/JsonBean.java

@@ -0,0 +1,28 @@
+package com.miekir.shibei.bean;
+
+import javax.persistence.*;
+
+/**
+ * Copyright (C), 2019-2020, Miekir
+ *
+ * @author Miekir
+ * @date 2020/8/13 20:20
+ * Description: json
+ */
+@Entity
+@Table(name = "t_json", schema = "shibei", catalog = "")
+public class JsonBean {
+
+    @Id
+    @GeneratedValue(strategy= GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = false)
+    public long id;
+
+    @Basic
+    @Column(name = "email", nullable = true, insertable = true, updatable = true)
+    public String email;
+
+    @Basic
+    @Column(columnDefinition = "MEDIUMTEXT", name = "json", nullable = true, insertable = true, updatable = true)
+    public String json;
+}

+ 40 - 0
src/main/java/com/miekir/shibei/bean/ResponseResult.java

@@ -0,0 +1,40 @@
+package com.miekir.shibei.bean;
+
+public class ResponseResult<T> {
+    private int code = ResultCode.FAILED_COMMON;
+    private String message;
+    private String extra;
+    private T content;
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public T getContent() {
+        return content;
+    }
+
+    public void setContent(T content) {
+        this.content = content;
+    }
+
+    public String getExtra() {
+        return extra;
+    }
+
+    public void setExtra(String extra) {
+        this.extra = extra;
+    }
+}

+ 17 - 0
src/main/java/com/miekir/shibei/bean/ResultCode.java

@@ -0,0 +1,17 @@
+package com.miekir.shibei.bean;
+
+public class ResultCode {
+    public static final int SUCCESS = 0;
+    public static final int FAILED_COMMON = -1;
+
+    /**
+     * 用户已存在
+     */
+    public static final int FAILED_USER_ALREADY_EXIST = -2;
+    /**
+     * 用户不存在
+     */
+    public static final int FAILED_USER_NOT_EXIST = -3;
+
+    public static final int FAILED_NEED_RE_LOGIN = -99;
+}

+ 25 - 0
src/main/java/com/miekir/shibei/bean/SystemBean.java

@@ -0,0 +1,25 @@
+package com.miekir.shibei.bean;
+
+import javax.persistence.*;
+
+/**
+ * 系统控制类
+ */
+@Entity
+@Table(name = "t_system", schema = "shibei", catalog = "")
+public class SystemBean {
+    /**
+     * 模板Id
+     */
+    @Id
+    @GeneratedValue(strategy= GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = false)
+    public long id;
+
+    /**
+     * 是否有VIP限制,true表示必须要VIP才能使用特殊服务,false表示免费开放中...
+     */
+    @Basic
+    @Column(name = "isVipLimit", nullable = true, insertable = true, updatable = true)
+    public boolean isVipLimit;
+}

+ 32 - 0
src/main/java/com/miekir/shibei/bean/UpgradeBean.java

@@ -0,0 +1,32 @@
+package com.miekir.shibei.bean;
+
+import javax.persistence.*;
+
+/**
+ * Created by Jason on 2019/09/29.
+ */
+@Entity
+@Table(name = "t_upgrade", schema = "shibei", catalog = "")
+public class UpgradeBean {
+    // Id自增,注意,一个表只能有一个主键,否则服务器会报500错误,启动失败
+    @Id
+    @GeneratedValue(strategy=GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = true)
+    public int id;
+
+    @Basic
+    @Column(name = "versionCode", nullable = true, insertable = true, updatable = true)
+    public int versionCode;
+
+    @Basic
+    @Column(name = "versionName", nullable = true, insertable = true, updatable = true)
+    public String versionName;
+    
+    @Basic
+    @Column(name = "content", nullable = true, insertable = true, updatable = true)
+    public String content;
+
+    @Basic
+    @Column(name = "url", nullable = true, insertable = true, updatable = true)
+    public String url;
+}

+ 217 - 0
src/main/java/com/miekir/shibei/bean/User.java

@@ -0,0 +1,217 @@
+package com.miekir.shibei.bean;
+
+import javax.persistence.*;
+
+/**
+ * Created by Jason on 2018/8/26.
+ */
+@Entity
+@Table(name = "t_user", schema = "shibei", catalog = "")
+public class User {
+    //private Integer id;
+    private String email;
+    private String nickName;
+    private String autograph;
+    private String password;
+    private String headIcon;
+    private Integer sex;
+    private String token;
+    private Long registerTimeMillis;
+    private Long lastLoginTimeMillis;
+    private boolean isVip;
+    private String deviceId;
+    private String lastIp;
+    private Integer themeMode;
+    /**当前余额,单位:分*/
+    private long currentMoney;
+    /**历史提现,单位:分*/
+    private long historyCash;
+
+    /**提现支付宝账号*/
+    private String cashAccount;
+
+    /**是否被禁用*/
+    private boolean isLimit;
+
+    // Id自增
+    /*@Id
+    @GeneratedValue(strategy=GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = true)
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }*/
+
+    @Basic
+    @Column(name = "autograph", nullable = true, insertable = true, updatable = true, length = 50)
+    public String getAutograph() {
+        return autograph;
+    }
+
+    public void setAutograph(String autograph) {
+        this.autograph = autograph;
+    }
+
+    @Id
+    @Column(name = "email", unique = true, nullable = false, insertable = true, updatable = true, length = 50)
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    @Basic
+    @Column(name = "nickName", nullable = true, insertable = true, updatable = true, length = 50)
+    public String getNickName() {
+        return nickName;
+    }
+
+    public void setNickName(String nickName) {
+        this.nickName = nickName;
+    }
+
+    @Basic
+    @Column(name = "password", nullable = false, insertable = true, updatable = true, length = 50)
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    @Basic
+    @Column(name = "headIcon", nullable = true, insertable = true, updatable = true, length = 100)
+    public String getHeadIcon() {
+        return headIcon;
+    }
+
+    public void setHeadIcon(String headIcon) {
+        this.headIcon = headIcon;
+    }
+
+    @Basic
+    @Column(name = "sex", nullable = true, insertable = true, updatable = true)
+    public Integer getSex() {
+        return sex;
+    }
+
+    public void setSex(Integer sex) {
+        this.sex = sex;
+    }
+
+    @Basic
+    @Column(name = "token", nullable = true, insertable = true, updatable = true, length = 100)
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    @Basic
+    @Column(name = "registerTimeMillis", nullable = true, insertable = true, updatable = true)
+    public Long getRegisterTimeMillis() {
+        return registerTimeMillis;
+    }
+
+    public void setRegisterTimeMillis(Long registerTimeMillis) {
+        this.registerTimeMillis = registerTimeMillis;
+    }
+
+    @Basic
+    @Column(name = "lastLoginTimeMillis", nullable = true, insertable = true, updatable = true)
+    public Long getLastLoginTimeMillis() {
+        return lastLoginTimeMillis;
+    }
+
+    public void setLastLoginTimeMillis(Long lastLoginTimeMillis) {
+        this.lastLoginTimeMillis = lastLoginTimeMillis;
+    }
+
+    @Basic
+    @Column(name = "vip", nullable = true, insertable = true, updatable = true)
+    public boolean isVip() {
+        return isVip;
+    }
+
+    public void setVip(boolean vip) {
+        isVip = vip;
+    }
+
+    @Basic
+    @Column(name = "deviceId", nullable = true, insertable = true, updatable = true, length = 100)
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    @Basic
+    @Column(name = "lastIp", nullable = true, insertable = true, updatable = true, length = 100)
+    public String getLastIp() {
+        return lastIp;
+    }
+
+    public void setLastIp(String lastIp) {
+        this.lastIp = lastIp;
+    }
+
+    @Basic
+    @Column(name = "themeMode", nullable = true, insertable = true, updatable = true)
+    public Integer getThemeMode() {
+        return themeMode;
+    }
+
+    public void setThemeMode(Integer themeMode) {
+        this.themeMode = themeMode;
+    }
+
+    @Basic
+    @Column(name = "currentMoney", nullable = true, insertable = true, updatable = true)
+    public long getCurrentMoney() {
+        return currentMoney;
+    }
+
+    public void setCurrentMoney(long currentMoney) {
+        this.currentMoney = currentMoney;
+    }
+
+    @Basic
+    @Column(name = "historyCash", nullable = true, insertable = true, updatable = true)
+    public long getHistoryCash() {
+        return historyCash;
+    }
+
+    public void setHistoryCash(long historyCash) {
+        this.historyCash = historyCash;
+    }
+
+    @Basic
+    @Column(name = "cashAccount", nullable = true, insertable = true, updatable = true)
+    public String getCashAccount() {
+        return cashAccount;
+    }
+
+    public void setCashAccount(String cashAccount) {
+        this.cashAccount = cashAccount;
+    }
+
+    @Basic
+    @Column(name = "isLimit", nullable = true, insertable = true, updatable = true)
+    public boolean isLimit() {
+        return isLimit;
+    }
+
+    public void setLimit(boolean limit) {
+        isLimit = limit;
+    }
+}

+ 25 - 0
src/main/java/com/miekir/shibei/bean/WeatherBean.java

@@ -0,0 +1,25 @@
+package com.miekir.shibei.bean;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson.annotation.JSONType;
+
+/**
+ * Copyright (C), 2019-2020, Miekir
+ *
+ * @author Miekir
+ * @date 2020/8/14 20:44
+ * Description: 天气实体
+ * JSON按顺序输出有三种方法(alphabetic=false似乎不起作用)
+ */
+//@JSONType(alphabetic=false)
+@JSONType(orders={"code","msg","temperatureRange","temperatureNow","wind","air","desc"})
+public class WeatherBean {
+    //@JSONField(ordinal = 1, name = "code")
+    public int code = -1;
+    public String msg;
+    public String temperatureRange;
+    public String temperatureNow;
+    public String wind;
+    public String air;
+    public String desc;
+}

+ 22 - 0
src/main/java/com/miekir/shibei/bean/YijiBean.java

@@ -0,0 +1,22 @@
+package com.miekir.shibei.bean;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson.annotation.JSONType;
+
+/**
+ * Copyright (C), 2019-2020, Miekir
+ *
+ * @author Miekir
+ * @date 2020/8/14 22:16
+ * Description: 宜忌实体
+ */
+@JSONType(orders={"code","msg","newDate","oldDate","hsDate","yi","ji"})
+public class YijiBean {
+    public int code = -1;
+    public String msg;
+    public String newDate;
+    public String oldDate;
+    public String hsDate;
+    public String yi;
+    public String ji;
+}

+ 5 - 0
src/main/java/com/miekir/shibei/constants/ServerConstants.java

@@ -0,0 +1,5 @@
+package com.miekir.shibei.constants;
+
+public interface ServerConstants {
+    String EMAIL_ADMIN = "[email protected]";
+}

+ 144 - 0
src/main/java/com/miekir/shibei/controller/api/CouponController.java

@@ -0,0 +1,144 @@
+package com.miekir.shibei.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.CouponBean;
+import com.miekir.shibei.bean.GoodsBean;
+import com.miekir.shibei.bean.ResponseResult;
+import com.miekir.shibei.bean.ResultCode;
+import com.miekir.shibei.repository.CouponRepository;
+import com.miekir.shibei.repository.UserRepository;
+import com.miekir.shibei.tool.RequestTool;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Controller
+public class CouponController {
+    // 自动装配
+    @Autowired
+    private CouponRepository couponRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    /**
+     * 新增和更新优惠券
+     */
+    @RequestMapping(value = "/api/addCoupon", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String addCoupon(@RequestHeader HttpHeaders header, @RequestBody CouponBean couponBean) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("操作失败");
+
+        if (couponBean == null || !RequestTool.isRequestAdminValid(header, userRepository)) {
+            responseResult.setMessage("登录过期或没有权限");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 查找对应的商品
+        CouponBean dbCouponBean = null;
+        try {
+            dbCouponBean = couponRepository.findCouponById(couponBean.id);
+        } catch (Exception e) {
+            e.printStackTrace();
+            responseResult.setMessage("请重新登录");
+        }
+
+        // 找不到对应商品,说明是新增
+        if (dbCouponBean == null) {
+            couponBean.createTimeMillis = System.currentTimeMillis();
+        }
+
+        couponBean.updateTimeMillis = System.currentTimeMillis();
+        couponBean.isLocal = false;
+
+        try {
+            couponRepository.save(couponBean);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setContent("操作成功");
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("操作成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 删除优惠券
+     */
+    @RequestMapping(value = "/api/deleteCouponById", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String deleteCoupon(@RequestHeader HttpHeaders header, long couponId) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("删除失败");
+
+        if (!RequestTool.isRequestAdminValid(header, userRepository)) {
+            responseResult.setMessage("登录过期或没有权限");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 查找对应的商品
+        CouponBean dbCouponBean;
+        try {
+            dbCouponBean = couponRepository.findCouponById(couponId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            responseResult.setMessage("请重新登录");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 找不到对应商品
+        if (dbCouponBean == null) {
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            couponRepository.delete(dbCouponBean);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("删除成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 查询优惠券
+     */
+    @RequestMapping(value = "/api/getCouponList", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getCouponList(int pageNum, int pageSize) {
+        ResponseResult<List<CouponBean>> responseResult = new ResponseResult<List<CouponBean>>();
+        responseResult.setMessage("获取失败");
+
+        // 自带的分页查询
+        List<CouponBean> couponBeanList;
+        try {
+            Sort sort = new Sort(Sort.Direction.DESC,"updateTimeMillis");
+            couponBeanList = couponRepository.findAll(new PageRequest(pageNum, pageSize, sort)).getContent();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setContent(couponBeanList);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+}

+ 178 - 0
src/main/java/com/miekir/shibei/controller/api/GoodsController.java

@@ -0,0 +1,178 @@
+package com.miekir.shibei.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.*;
+import com.miekir.shibei.repository.GoodsRepository;
+import com.miekir.shibei.repository.UserRepository;
+import com.miekir.shibei.tool.RequestTool;
+import com.miekir.shibei.tool.StringTool;
+import com.miekir.shibei.tool.TextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map;
+
+@Controller
+public class GoodsController {
+    // 自动装配
+    @Autowired
+    private GoodsRepository goodsRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    /**
+     * 新增和更新京东商品
+     */
+    @RequestMapping(value = "/api/addGoods", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String addGoods(@RequestHeader HttpHeaders header, @RequestBody GoodsBean goodsBean) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("操作失败");
+
+        if (goodsBean == null || !RequestTool.isRequestAdminValid(header, userRepository)) {
+            responseResult.setMessage("登录过期或没有权限");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 查找对应的商品
+        GoodsBean dbGoodsBean = null;
+        try {
+            dbGoodsBean = goodsRepository.findGoodsById(goodsBean.id);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        // 找不到对应商品,说明是新增
+        if (dbGoodsBean == null) {
+            goodsBean.createTimeMillis = System.currentTimeMillis();
+        }
+
+        goodsBean.updateTimeMillis = System.currentTimeMillis();
+        goodsBean.isLocal = false;
+
+        try {
+            goodsRepository.save(goodsBean);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setContent("操作成功");
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("操作成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 删除京东商品
+     */
+    @RequestMapping(value = "/api/deleteGoodsById", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String deleteGoods(@RequestHeader HttpHeaders header, long goodsId) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("删除失败");
+
+        if (!RequestTool.isRequestAdminValid(header, userRepository)) {
+            responseResult.setMessage("登录过期或没有权限");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 查找对应的商品
+        GoodsBean dbGoodsBean;
+        try {
+            dbGoodsBean = goodsRepository.findGoodsById(goodsId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 找不到对应商品
+        if (dbGoodsBean == null) {
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            goodsRepository.delete(dbGoodsBean);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("删除成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 查询京东商品
+     */
+    @RequestMapping(value = "/api/getGoodsList", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getGoodsList(int pageNum, int pageSize) {
+        ResponseResult<List<GoodsBean>> responseResult = new ResponseResult<List<GoodsBean>>();
+        responseResult.setMessage("获取失败");
+
+        // 自带的分页查询
+        List<GoodsBean> goodsBeanList;
+        try {
+            Sort sort = new Sort(Sort.Direction.DESC,"updateTimeMillis");
+            goodsBeanList = goodsRepository.findAll(new PageRequest(pageNum, pageSize, sort)).getContent();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setContent(goodsBeanList);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 根据关键字查询京东商品
+     */
+    @RequestMapping(value = "/api/getGoodsListByKeyword", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getGoodsListByKeyword(String keywords, int pageNum, int pageSize) {
+        String keywordsUtf8 = StringTool.getUtf8String(keywords);
+
+        ResponseResult<List<GoodsBean>> responseResult = new ResponseResult<List<GoodsBean>>();
+        responseResult.setMessage("获取失败");
+
+        // 自带的分页查询
+        List<GoodsBean> goodsBeanList;
+        try {
+            // 如果pageNum为1,pageSize为20,则查询第1*20条到第1*20+20-1(这里的第几条是从0开始的)
+            // 模糊查询,要拼上%%
+            keywordsUtf8 = "%"+keywordsUtf8+"%";
+            goodsBeanList = goodsRepository.getGoodsListByKeyword(keywordsUtf8, pageNum*pageSize, pageSize);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setContent(goodsBeanList);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+}

+ 197 - 0
src/main/java/com/miekir/shibei/controller/api/JsonController.java

@@ -0,0 +1,197 @@
+package com.miekir.shibei.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.parser.Feature;
+import com.alibaba.fastjson.serializer.SerializeConfig;
+import com.miekir.shibei.bean.*;
+import com.miekir.shibei.repository.JsonRepository;
+import com.miekir.shibei.repository.SystemRepository;
+import com.miekir.shibei.repository.UserRepository;
+import com.miekir.shibei.tool.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+@Controller
+public class JsonController {
+    // 自动装配
+    @Autowired
+    private JsonRepository jsonRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    @Autowired
+    private SystemRepository systemRepository;
+
+    //private String mLastWeatherDate = "";
+    //private WeatherBean mWeatherBean;
+    private String mLastYijiDate = "";
+    private YijiBean mYijiBean;
+
+    /**
+     * 获取天气信息
+     */
+    @RequestMapping(value = "/api/getWeather", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getWeather(String s, String city) {
+        String token = StringTool.getRawToken(s);
+        WeatherBean weatherBean = new WeatherBean();
+        // get过来的参数,会乱码
+        String cityUtf8 = StringTool.getUtf8String(city);
+
+        // 根据token查找用户
+        User dbUserBean = RequestTool.getUserByToken(userRepository, token);
+        if (dbUserBean == null) {
+            weatherBean.msg = "请重新登录";
+            return JSON.toJSONString(weatherBean);
+        }
+
+        SystemBean systemBean = systemRepository.findSystemBean();
+        // 以后收费
+        if (systemBean != null && systemBean.isVipLimit && !dbUserBean.isVip()) {
+            return "请更新客户端并开通服务后重试";
+        }
+        WebTool.getWeatherInfo(weatherBean, cityUtf8);
+
+        return JSON.toJSONString(weatherBean);
+    }
+
+    /**
+     * 获取黄历信息
+     */
+    @RequestMapping(value = "/api/getYiji", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getYiji(String s) {
+        String token = StringTool.getRawToken(s);
+        YijiBean yijiBean = new YijiBean();
+
+        // 根据token查找用户
+        User dbUserBean = RequestTool.getUserByToken(userRepository, token);
+        if (dbUserBean == null) {
+            yijiBean.msg = "请重新登录";
+            return JSON.toJSONString(yijiBean);
+        }
+
+        SystemBean systemBean = systemRepository.findSystemBean();
+        // 以后收费
+        if (systemBean != null && systemBean.isVipLimit && !dbUserBean.isVip()) {
+            return "请更新客户端并开通服务后重试";
+        }
+
+        String currentDate = DateTool.getCurrentDate();
+        if (!TextUtils.equals(mLastYijiDate, currentDate) || TextUtils.isEmpty(mYijiBean.newDate)) {
+            mYijiBean = WebTool.getYijiInfo(yijiBean);
+            mLastYijiDate = currentDate;
+        }
+        return JSON.toJSONString(mYijiBean);
+    }
+
+    /**
+     * 新增和更新JSON
+     */
+    @RequestMapping(value = "/api/saveJson", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String saveJson(@RequestHeader HttpHeaders header, @RequestBody JsonBean jsonBean) {
+        ResponseResult<JsonBean> responseResult = new ResponseResult<JsonBean>();
+        responseResult.setMessage("操作失败");
+
+        String email = header.getFirst("email");
+        String token = header.getFirst("token");
+        // 根据email查找用户,查询用户的token是否相同
+        User dbUserBean;
+        try {
+            dbUserBean = userRepository.findUserByEmail(email);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 用户token不一致
+        if (dbUserBean == null || !TextUtils.equals(token, dbUserBean.getToken())) {
+            return JSON.toJSONString(responseResult);
+        }
+
+        JsonBean dbJsonBean = null;
+        try {
+            dbJsonBean = jsonRepository.save(jsonBean);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setContent(dbJsonBean);
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("操作成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 获取保存的JSON Bean
+     */
+    @RequestMapping(value = "/api/getJsonBean", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getJsonBean(@RequestHeader HttpHeaders header) {
+        ResponseResult<JsonBean> responseResult = new ResponseResult<JsonBean>();
+        responseResult.setMessage("获取失败");
+
+        String email = header.getFirst("email");
+        String token = header.getFirst("token");
+        // 根据email查找用户,查询用户的token是否相同
+        User dbUserBean;
+        try {
+            dbUserBean = userRepository.findUserByEmail(email);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 用户token不一致
+        if (dbUserBean == null || !TextUtils.equals(token, dbUserBean.getToken())) {
+            responseResult.setMessage("请重新登录");
+            return JSON.toJSONString(responseResult);
+        }
+
+        JsonBean jsonBean = null;
+        try {
+            jsonBean = jsonRepository.findJsonBeanByEmail(email);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        responseResult.setContent(jsonBean);
+
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 通过Get方法获取保存的JSON字符串
+     */
+    @RequestMapping(value = "/api/getJson", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getJson(String s) {
+        // 根据token查找用户
+        String token = StringTool.getRawToken(s);
+        User dbUserBean = RequestTool.getUserByToken(userRepository, token);
+        if (dbUserBean == null) {
+            return "请重新登录";
+        }
+
+        JsonBean jsonBean = null;
+        try {
+            jsonBean = jsonRepository.findJsonBeanByEmail(dbUserBean.getEmail());
+        } catch (Exception exception) {
+            exception.printStackTrace();
+            return "请重新登录";
+        }
+        return jsonBean.json;
+    }
+}

+ 166 - 0
src/main/java/com/miekir/shibei/controller/api/SystemController.java

@@ -0,0 +1,166 @@
+package com.miekir.shibei.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.*;
+import com.miekir.shibei.constants.ServerConstants;
+import com.miekir.shibei.repository.FeedbackRepository;
+import com.miekir.shibei.repository.SystemRepository;
+import com.miekir.shibei.repository.UpgradeRepository;
+import com.miekir.shibei.repository.UserRepository;
+import com.miekir.shibei.tool.RequestTool;
+import com.miekir.shibei.tool.email.EmailTool;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
+
+@Controller
+public class SystemController {
+
+    @Autowired
+    FeedbackRepository feedbackRepository;
+
+    @Autowired
+    UpgradeRepository upgradeRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    @Autowired
+    private SystemRepository systemRepository;
+
+    /**
+     * 意见反馈
+     */
+    @RequestMapping(value = "/api/feedback", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String dealFeedback(String email, String token, String feedback) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("反馈失败");
+
+        Feedback feedbackBean = new Feedback();
+        feedbackBean.setEmail(email);
+        feedbackBean.setFeedback(feedback);
+        feedbackBean.setTime(System.currentTimeMillis());
+
+        // 开始重设密码,插入数据库
+        try {
+            feedbackRepository.save(feedbackBean);
+            responseResult.setCode(ResultCode.SUCCESS);
+            responseResult.setMessage("反馈成功");
+        } catch (Exception e) {
+            responseResult.setMessage("反馈失败");
+            e.printStackTrace();
+        }
+
+        try {
+            // 同时发送邮件
+            new EmailTool().sendEmail("吾记反馈:" + "【From: " + email + "】" + feedback, ServerConstants.EMAIL_ADMIN);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return JSON.toJSONString(responseResult);
+    }
+
+    @RequestMapping(value = "/api/upgrade", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    public ResponseEntity<byte[]> download(HttpServletRequest request) throws IOException {
+        // 放到D:\\software\\apache-tomcat-7.0.90\\webapps\\wuji\\upgrade\\wuji.apk
+        // 获取的时候,就是访问这个URL:http://www.xxx.com/api/upgrade
+        // 需要正式发布才起作用
+        String webPath = request.getSession().getServletContext().getRealPath("upgrade") + File.separator + "wuji.apk";
+        File file = new File(webPath);
+        byte[] body = null;
+        InputStream is = new FileInputStream(file);
+        body = new byte[is.available()];
+        is.read(body);
+        HttpHeaders headers = new HttpHeaders();
+        headers.add("Content-Disposition", "attchement;filename=" + file.getName());
+        HttpStatus statusCode = HttpStatus.OK;
+        ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode);
+        return entity;
+    }
+
+    /**
+     * 查询系统设置
+     */
+    @RequestMapping(value = "/api/getSystemConfig", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getSystemConfig() {
+        ResponseResult<SystemBean> responseResult = new ResponseResult<SystemBean>();
+        SystemBean systemBean = systemRepository.findSystemBean();
+        responseResult.setContent(systemBean);
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 设置API是否为会员专属
+     */
+    @RequestMapping(value = "/api/setApiConfig", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String setApiConfig(@RequestHeader HttpHeaders header, boolean isApiVipOnly) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("设置失败");
+        if (!RequestTool.isRequestAdminValid(header, userRepository)) {
+            responseResult.setMessage("登录过期或没有权限");
+            return JSON.toJSONString(responseResult);
+        }
+
+        SystemBean systemBean = systemRepository.findSystemBean();
+        if (systemBean == null) {
+            systemBean = new SystemBean();
+        }
+        systemBean.isVipLimit = isApiVipOnly;
+        systemRepository.save(systemBean);
+
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("设置成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 查询版本更新信息
+     */
+    @RequestMapping(value = "/api/getUpgradeInfo", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getUpgradeInfo() {
+        ResponseResult<UpgradeBean> responseResult = new ResponseResult<UpgradeBean>();
+        responseResult.setMessage("获取失败");
+
+        UpgradeBean upgradeInfo;
+        try {
+            upgradeInfo = upgradeRepository.findLatestUpgradeInfo();
+            // http://jianjie.life/upgrade/shibei.apk
+            // nginx对应/file/upgrade/shibei.apk
+            /*#静态资源,和静态网站下建目录放文件是一样效果
+            location /upgrade/ {
+                    alias /file/upgrade/;
+            }*/
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setContent(upgradeInfo);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+}

+ 383 - 0
src/main/java/com/miekir/shibei/controller/api/UserController.java

@@ -0,0 +1,383 @@
+package com.miekir.shibei.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.ResponseResult;
+import com.miekir.shibei.bean.ResultCode;
+import com.miekir.shibei.bean.User;
+import com.miekir.shibei.repository.UserRepository;
+import com.miekir.shibei.tool.CodeGenerator;
+import com.miekir.shibei.tool.TextUtils;
+import com.miekir.shibei.tool.TokenGenerator;
+import com.miekir.shibei.tool.email.EmailTool;
+import com.miekir.shibei.tool.secure.SecureManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Controller
+public class UserController {
+    private static final long TIME_MILLIS_CLEAR = 5 * 60 * 1000;
+
+    // email, timeMillis-code
+    private ConcurrentHashMap<String, String> mCodeMap = new ConcurrentHashMap<String, String>();
+    // 自动装配
+    @Autowired
+    private UserRepository userRepository;
+
+
+    @Autowired
+    HttpServletRequest request;
+
+    // 每隔5分钟去清理验证码
+    @Scheduled(cron = "* 0/5 * * * *")
+    public void clearMapTask() {
+        Enumeration<String> keys = mCodeMap.keys();
+        while (keys.hasMoreElements()) {
+            String key = keys.nextElement();
+            String generateMillisCode = mCodeMap.get(key);
+            if (!TextUtils.isEmpty(generateMillisCode)) {
+                long generateMillis = Long.valueOf(generateMillisCode.split("-")[0]);
+                if (System.currentTimeMillis() - generateMillis > TIME_MILLIS_CLEAR) {
+                    // 验证码已过期
+                    mCodeMap.remove(key);
+                }
+            }
+        }
+    }
+
+    // 添加@ResponseBody注解就可以返回json了
+    /**
+     * 获取验证码,返回aes给客户端
+     */
+    @RequestMapping(value = "/api/code", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getAuthCode(String email) {
+        ResponseResult<Boolean> responseResult = new ResponseResult<Boolean>();
+        responseResult.setContent(false);
+        responseResult.setMessage("获取验证码失败");
+        String code = CodeGenerator.getInstance().getRandomCode();
+        int result = new EmailTool().sendEmail("拾贝温馨提醒您,您的6位验证码(5分钟内有效)是:" + code, email);
+        if (result == EmailTool.SUCCESS) {
+            mCodeMap.put(email, System.currentTimeMillis()+"-"+code);
+            responseResult.setCode(ResultCode.SUCCESS);
+            responseResult.setMessage("获取验证码成功");
+            responseResult.setContent(true);
+            responseResult.setExtra(SecureManager.KEY_FOR_CLIENT + "=" + SecureManager.IV_FOR_CLIENT);
+        } else {
+            responseResult.setCode(ResultCode.FAILED_COMMON);
+            responseResult.setMessage("获取验证码失败");
+        }
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 注册
+     */
+    @RequestMapping(value = "/api/register", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String register(@RequestBody Map<String, Object> registerMap) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("注册失败");
+
+        if (registerMap == null) {
+            return JSON.toJSONString(responseResult);
+        }
+
+        String email = String.valueOf(registerMap.get("email"));
+        String code = String.valueOf(registerMap.get("code"));
+        String password = String.valueOf(registerMap.get("password"));
+        String nickname = String.valueOf(registerMap.get("nickname"));
+        String cashAccount = String.valueOf(registerMap.get("cashAccount"));
+
+        // 从数据库查询,如果没有这个email并且不在黑名单里,才可以继续注册
+        User dbUser = userRepository.findUserByEmail(email);
+        if (dbUser != null) {
+            responseResult.setCode(ResultCode.FAILED_USER_ALREADY_EXIST);
+            responseResult.setMessage("该邮箱已被使用");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 查看是否已发送验证码
+        if (!mCodeMap.containsKey(email)) {
+            responseResult.setMessage("请重新获取验证码");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 查看服务器发送的验证码和用户发过来的验证码是否一致
+        String content = mCodeMap.get(email);
+        String realCode = content.substring(content.indexOf("-")+1);
+        if (!code.equals(realCode)) {
+            responseResult.setMessage("验证码错误");
+            return JSON.toJSONString(responseResult);
+
+        }
+
+        // 开始注册,插入数据库
+        User user = new User();
+        user.setEmail(email);
+        user.setNickName(nickname);
+        user.setRegisterTimeMillis(System.currentTimeMillis());
+        user.setPassword(password);
+        user.setCashAccount(cashAccount);
+        try {
+            String token = TokenGenerator.getInstance().getToken(email);
+            if (token == null || token.equals("")) {
+                responseResult.setMessage("注册失败,请检查数据格式");
+                return JSON.toJSONString(responseResult);
+            }
+
+            // 注册成功,生成token给用户
+            user.setToken(token);
+            userRepository.save(user);
+
+            user.setPassword("");
+            responseResult.setCode(ResultCode.SUCCESS);
+            responseResult.setMessage("注册成功");
+            responseResult.setContent(user);
+
+            // 注册成功,从内存中移除相应的验证码,节省资源
+            mCodeMap.remove(email);
+
+        } catch (Exception e) {
+            responseResult.setMessage("注册失败,请检查数据格式");
+            e.printStackTrace();
+        }
+
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 登录之前先获取AES
+     */
+    @RequestMapping(value = "/api/aes", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getAES() {
+        ResponseResult responseResult = new ResponseResult();
+        responseResult.setExtra(SecureManager.KEY_FOR_CLIENT + "=" + SecureManager.IV_FOR_CLIENT);
+        responseResult.setCode(ResultCode.SUCCESS);
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 登录:email+加密的密码
+     */
+    @RequestMapping(value = "/api/login/normal", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String loginNormal(String email, String password) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setMessage("登录失败");
+        User user = userRepository.findUserByEmail(email);
+        if (user == null) {
+            responseResult.setMessage("用户不存在");
+            return JSON.toJSONString(responseResult);
+        }
+
+        String encryptPassword = user.getPassword();
+
+        if (!password.equals(encryptPassword)) {
+            responseResult.setMessage("请检查账号和密码");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 登录成功,生成token给用户
+        String token = TokenGenerator.getInstance().getToken(email);
+        if (token == null || token.equals("")) {
+            responseResult.setMessage("登录失败,请检查数据格式");
+            return JSON.toJSONString(responseResult);
+        }
+        user.setToken(token);
+        userRepository.save(user);
+
+        user.setPassword("");
+        responseResult.setCode(ResultCode.SUCCESS);
+        responseResult.setMessage("登录成功");
+        responseResult.setContent(user);
+
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 登录:email+token
+     */
+    @RequestMapping(value = "/api/login/token", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String loginToken(String email, String token) {
+        ResponseResult responseResult = new ResponseResult();
+        responseResult.setMessage("请重新登录");
+        User user = userRepository.findUserByEmail(email);
+        if (user == null || !TextUtils.equals(token, user.getToken())) {
+            // 拿到token就可以拿到token的有效时间,以后可以做过期校验
+            responseResult.setMessage("请重新登录");
+            responseResult.setCode(ResultCode.FAILED_NEED_RE_LOGIN);
+        }
+
+        responseResult.setMessage("token登录成功");
+        responseResult.setCode(ResultCode.SUCCESS);
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 重置密码
+     */
+    @RequestMapping(value = "/api/password", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String resetPassword(@RequestBody Map<String, Object> forgetMap) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("密码重置失败");
+
+        if (forgetMap == null) {
+            return JSON.toJSONString(responseResult);
+        }
+
+        String email = String.valueOf(forgetMap.get("email"));
+        String code = String.valueOf(forgetMap.get("code"));
+        String password = String.valueOf(forgetMap.get("password"));
+
+        // 从数据库查询,如果有这个email并且不在黑名单里,才可以继续
+        User dbUser = userRepository.findUserByEmail(email);
+        if (dbUser == null) {
+            responseResult.setCode(ResultCode.FAILED_USER_NOT_EXIST);
+            responseResult.setMessage("用户不存在");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 查看是否已发送验证码
+        if (!mCodeMap.containsKey(email)) {
+            responseResult.setMessage("请重新获取验证码");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 查看服务器发送的验证码和用户发过来的验证码是否一致
+        String content = mCodeMap.get(email);
+        String realCode = content.substring(content.indexOf("-")+1);
+        if (!code.equals(realCode)) {
+            responseResult.setMessage("验证码错误");
+            return JSON.toJSONString(responseResult);
+
+        }
+
+        // 开始重设密码,插入数据库
+        try {
+            dbUser.setPassword(password);
+            String token = TokenGenerator.getInstance().getToken(email);
+            if (token == null || token.equals("")) {
+                responseResult.setMessage("重置失败,请检查数据格式");
+                return JSON.toJSONString(responseResult);
+            }
+
+            // 密码重置成功,生成token给用户
+            dbUser.setToken(token);
+            userRepository.save(dbUser);
+
+            // 这种是不是会导致密码被修改为空。答案:不会
+            dbUser.setPassword("");
+            responseResult.setCode(ResultCode.SUCCESS);
+            responseResult.setMessage("密码重置成功");
+            responseResult.setContent(dbUser);
+
+            // 注册成功,从内存中移除相应的验证码,节省资源
+            mCodeMap.remove(email);
+
+        } catch (Exception e) {
+            responseResult.setMessage("重置失败,请检查数据格式");
+            e.printStackTrace();
+        }
+
+        return JSON.toJSONString(responseResult);
+    }
+
+    @RequestMapping(value = "/api/uploadBg", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String saveBgInfo(String email, String token, int mode, MultipartFile file) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("上传背景失败");
+
+        //String bgDir = request.getSession().getServletContext().getRealPath("bg") + File.separator;
+        String currentDir = request.getSession().getServletContext().getRealPath("/");
+        File bgDirFile = new File(new File(currentDir).getParentFile().getAbsolutePath(), "res/wuji/bg/");
+        if (!bgDirFile.exists()) {
+            bgDirFile.mkdirs();
+        }
+
+        if (file != null) {
+            //String fileName = file.getOriginalFilename();
+            //String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
+            String fileSuffix = ".jpg";
+
+            try {
+                BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(bgDirFile, email + fileSuffix)));
+                //System.out.println(file.getName());
+                out.write(file.getBytes());
+                out.flush();
+                out.close();
+
+                responseResult.setCode(ResultCode.SUCCESS);
+                responseResult.setMessage("上传背景成功");
+
+                // 更新用户的theme mode(4为自定义)
+                userRepository.updateUser(mode, email);
+            } catch (Exception e) {
+                responseResult.setMessage("上传背景失败");
+                e.printStackTrace();
+            }
+        }
+
+        return JSON.toJSONString(responseResult);
+    }
+
+    @RequestMapping(value = "/api/downloadBg", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    public ResponseEntity<byte[]> download(String email, String token) throws IOException {
+        //String bgPath = request.getSession().getServletContext().getRealPath("bg") + File.separator + email + ".jpg";
+        String currentDir = request.getSession().getServletContext().getRealPath("/");
+        File file = new File(new File(currentDir).getParentFile().getAbsolutePath(), "res/wuji/bg/" + email + ".jpg");
+        if (!file.exists()) {
+            return null;
+        }
+        byte[] body = null;
+        InputStream is = new FileInputStream(file);
+        body = new byte[is.available()];
+        is.read(body);
+        HttpHeaders headers = new HttpHeaders();
+        headers.add("Content-Disposition", "attchement;filename=" + file.getName());
+        HttpStatus statusCode = HttpStatus.OK;
+        ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode);
+        return entity;
+    }
+
+    /**
+     * 更新主题模式
+     */
+    @RequestMapping(value = "/api/updateTheme", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String updateTheme(String email, String token, int mode) {
+        ResponseResult responseResult = new ResponseResult();
+        responseResult.setMessage("用户模式更新失败");
+
+        try {
+            userRepository.updateUser(mode, email);
+        } catch (Exception e) {
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setMessage("用户模式更新成功");
+        responseResult.setCode(ResultCode.SUCCESS);
+        return JSON.toJSONString(responseResult);
+    }
+}

+ 18 - 0
src/main/java/com/miekir/shibei/controller/web/ShibeiController.java

@@ -0,0 +1,18 @@
+package com.miekir.shibei.controller.web;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+@Controller
+public class ShibeiController {
+
+    // 首页(会和文件上传的mapping冲突)
+    @RequestMapping(value = "/", method = RequestMethod.GET)
+    public String index() {
+        return "index";
+    }
+}

+ 43 - 0
src/main/java/com/miekir/shibei/interceptor/AuthInterceptor.java

@@ -0,0 +1,43 @@
+package com.miekir.shibei.interceptor;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.ResponseResult;
+import com.miekir.shibei.bean.ResultCode;
+import com.miekir.shibei.bean.User;
+import com.miekir.shibei.repository.UserRepository;
+import com.miekir.shibei.tool.TextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+public class AuthInterceptor extends HandlerInterceptorAdapter {
+    @Autowired
+    UserRepository userRepository;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setCode(ResultCode.FAILED_NEED_RE_LOGIN);
+        responseResult.setMessage("请重新登录");
+
+        //HttpSession session = request.getSession();
+        String email = request.getParameter("email");
+        String token = request.getParameter("token");
+        User user = userRepository.findUserByEmail(email);
+        if (user == null || !TextUtils.equals(user.getToken(), token)) {
+            response.setContentType("text/html; charset=utf-8");
+            PrintWriter out = response.getWriter();
+            out.write(JSON.toJSONString(responseResult));
+            out.flush();
+            out.close();
+
+            return false;
+        }
+
+        // 让其通行
+        return true;
+    }
+}

+ 77 - 0
src/main/java/com/miekir/shibei/model/BlogEntity.java

@@ -0,0 +1,77 @@
+package com.miekir.shibei.model;
+
+import javax.persistence.*;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+@Entity
+@Table(name = "blog", schema = "shibei", catalog = "")
+public class BlogEntity {
+    private int id;
+    private String title;
+    private String content;
+    private UserEntity userByUserid;
+
+    @Id
+    @Column(name = "id", nullable = false, insertable = true, updatable = true)
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    @Basic
+    @Column(name = "title", nullable = true, insertable = true, updatable = true, length = 100)
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    @Basic
+    @Column(name = "content", nullable = true, insertable = true, updatable = true, length = 255)
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        BlogEntity that = (BlogEntity) o;
+
+        if (id != that.id) return false;
+        if (title != null ? !title.equals(that.title) : that.title != null) return false;
+        if (content != null ? !content.equals(that.content) : that.content != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id;
+        result = 31 * result + (title != null ? title.hashCode() : 0);
+        result = 31 * result + (content != null ? content.hashCode() : 0);
+        return result;
+    }
+
+    @ManyToOne
+    @JoinColumn(name = "userid", referencedColumnName = "id")
+    public UserEntity getUserByUserid() {
+        return userByUserid;
+    }
+
+    public void setUserByUserid(UserEntity userByUserid) {
+        this.userByUserid = userByUserid;
+    }
+}

+ 91 - 0
src/main/java/com/miekir/shibei/model/UserEntity.java

@@ -0,0 +1,91 @@
+package com.miekir.shibei.model;
+
+import javax.persistence.*;
+import java.util.Collection;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+@Entity
+@Table(name = "spring_mvc_user", schema = "shibei", catalog = "")
+public class UserEntity {
+    private int id;
+    private String firstName;
+    private String lastName;
+    private String password;
+    private Collection<BlogEntity> blogsById;
+
+    @Id
+    @Column(name = "id", nullable = false, insertable = true, updatable = true)
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    @Basic
+    @Column(name = "firstName", nullable = true, insertable = true, updatable = true, length = 45)
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    @Basic
+    @Column(name = "lastName", nullable = true, insertable = true, updatable = true, length = 45)
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    @Basic
+    @Column(name = "password", nullable = true, insertable = true, updatable = true, length = 45)
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        UserEntity that = (UserEntity) o;
+
+        if (id != that.id) return false;
+        if (firstName != null ? !firstName.equals(that.firstName) : that.firstName != null) return false;
+        if (lastName != null ? !lastName.equals(that.lastName) : that.lastName != null) return false;
+        if (password != null ? !password.equals(that.password) : that.password != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id;
+        result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
+        result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
+        result = 31 * result + (password != null ? password.hashCode() : 0);
+        return result;
+    }
+
+    // 外键
+    @OneToMany(mappedBy = "userByUserid")
+    public Collection<BlogEntity> getBlogsById() {
+        return blogsById;
+    }
+
+    public void setBlogsById(Collection<BlogEntity> blogsById) {
+        this.blogsById = blogsById;
+    }
+}

+ 42 - 0
src/main/java/com/miekir/shibei/repository/CouponRepository.java

@@ -0,0 +1,42 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.CouponBean;
+import com.miekir.shibei.bean.GoodsBean;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface CouponRepository extends JpaRepository<CouponBean, Integer> {
+    // 根据密码Id查询密码记事
+    // 说明该方法是事务性操作
+    @Transactional
+    // @Param注解用于提取参数
+    @Query(value="select couponBean from CouponBean couponBean where couponBean.id=:id")
+    public CouponBean findCouponById(@Param("id") Long id);
+
+
+
+//    @Transactional
+//    // 根据邮件查询用户所有密码记事
+//    // @Param注解用于提取参数
+//    @Query(value="select note from NoteBean note where note.userId=:email order by note.updateTime desc")
+//    public List<NoteBean> findNotesByEmail(@Param("email") String email);
+//
+
+
+
+//    // 修改密码记事
+//    @Modifying
+//    // 说明该方法是事务性操作
+//    @Transactional
+//    // @Param注解用于提取参数
+//    @Query("update NoteBean note set note.content=:content, note.updateTime=:updateTime where note.id=:noteId")
+//    public int updateNoteBean(@Param("content") String content, @Param("noteId") Integer noteId, @Param("updateTime") Long updateTime);
+}

+ 14 - 0
src/main/java/com/miekir/shibei/repository/FeedbackRepository.java

@@ -0,0 +1,14 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.Feedback;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface FeedbackRepository extends JpaRepository<Feedback, Integer> {
+
+}

+ 47 - 0
src/main/java/com/miekir/shibei/repository/GoodsRepository.java

@@ -0,0 +1,47 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.GoodsBean;
+import com.miekir.shibei.bean.JsonBean;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface GoodsRepository extends JpaRepository<GoodsBean, Integer> {
+    // 根据密码Id查询密码记事
+    // 说明该方法是事务性操作
+    @Transactional
+    // @Param注解用于提取参数
+    @Query(value="select goodsBean from GoodsBean goodsBean where goodsBean.id=:id")
+    public GoodsBean findGoodsById(@Param("id") Long id);
+
+    // 使用原生SQL MYSQL 不支持TOP,要用连接符号|连接,否则会被当成字符串常量拼成%?1%
+    @Query(value="SELECT * FROM t_goods where title like ?1 limit ?2, ?3", nativeQuery = true)
+    public List<GoodsBean> getGoodsListByKeyword(String keywords, int startNum, int pageSize);
+
+
+//    @Transactional
+//    // 根据邮件查询用户所有密码记事
+//    // @Param注解用于提取参数
+//    @Query(value="select note from NoteBean note where note.userId=:email order by note.updateTime desc")
+//    public List<NoteBean> findNotesByEmail(@Param("email") String email);
+//
+
+
+
+//    // 修改密码记事
+//    @Modifying
+//    // 说明该方法是事务性操作
+//    @Transactional
+//    // @Param注解用于提取参数
+//    @Query("update NoteBean note set note.content=:content, note.updateTime=:updateTime where note.id=:noteId")
+//    public int updateNoteBean(@Param("content") String content, @Param("noteId") Integer noteId, @Param("updateTime") Long updateTime);
+}

+ 20 - 0
src/main/java/com/miekir/shibei/repository/JsonRepository.java

@@ -0,0 +1,20 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.CouponBean;
+import com.miekir.shibei.bean.JsonBean;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+@Repository
+public interface JsonRepository extends JpaRepository<JsonBean, Integer> {
+    // 根据Email查找对应的Json 选择第一条
+    // 使用原生SQL MYSQL 不支持TOP
+    @Query(value="SELECT * FROM t_json where email = ?1 limit 1", nativeQuery = true)
+    public JsonBean findJsonBeanByEmail(String email);
+}

+ 21 - 0
src/main/java/com/miekir/shibei/repository/SystemRepository.java

@@ -0,0 +1,21 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.CouponBean;
+import com.miekir.shibei.bean.SystemBean;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface SystemRepository extends JpaRepository<SystemBean, Integer> {
+
+    @Transactional
+    @Query(value = "SELECT * FROM t_system ORDER BY id DESC LIMIT 1", nativeQuery=true)
+    public SystemBean findSystemBean();
+}

+ 21 - 0
src/main/java/com/miekir/shibei/repository/UpgradeRepository.java

@@ -0,0 +1,21 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.UpgradeBean;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface UpgradeRepository extends JpaRepository<UpgradeBean, Integer> {
+    // 使用原生SQL语句查找最新一条记录
+    @Transactional
+    @Query(value = "SELECT * FROM t_upgrade ORDER BY id DESC LIMIT 1", nativeQuery=true)
+    public UpgradeBean findLatestUpgradeInfo();
+
+
+}

+ 49 - 0
src/main/java/com/miekir/shibei/repository/UserRepository.java

@@ -0,0 +1,49 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface UserRepository extends JpaRepository<User, String> {
+    /*// 说明该方法是修改操作 JPQL
+    @Modifying
+    // 说明该方法是事务性操作
+    @Transactional
+    // 定义查询
+    // @Param注解用于提取参数
+    @Query("update User us set us.firstName=:qFirstName, us.lastName=:qLastName, us.password=:qPassword where us.id=:qId")
+    public void updateUser(@Param("qFirstName") String firstName,
+                           @Param("qLastName") String qLastName,
+                           @Param("qPassword") String password,
+                           @Param("qId") Integer id);*/
+
+
+    // 说明该方法是事务性操作
+    @Transactional
+    // 根据邮件查询用户
+    // @Param注解用于提取参数
+    @Query(value="select user from User user where user.email=:email")
+    public User findUserByEmail(@Param("email") String email);
+
+
+    @Transactional
+    @Query(value="select user from User user where user.token=:token")
+    public List<User> findUserByToken(@Param("token") String token);
+
+    @Modifying
+    @Transactional
+    @Query("update User us set us.themeMode=:themeMode where us.email=:email")
+    public void updateUser(@Param("themeMode") Integer themeMode, @Param("email") String email);
+
+}

+ 33 - 0
src/main/java/com/miekir/shibei/tool/CodeGenerator.java

@@ -0,0 +1,33 @@
+package com.miekir.shibei.tool;
+
+import java.util.Random;
+
+public class CodeGenerator {
+    private static final int LEN_CODE = 6;
+    private Random random;
+    private static CodeGenerator codeGenerator;
+    private CodeGenerator() {
+        random = new Random();
+    }
+
+    public static CodeGenerator getInstance() {
+        if (codeGenerator == null) {
+            init();
+        }
+        return codeGenerator;
+    }
+
+    private static synchronized void init() {
+        if (codeGenerator == null) {
+            codeGenerator = new CodeGenerator();
+        }
+    }
+
+    public String getRandomCode() {
+        StringBuffer buffer = new StringBuffer();
+        for (int i = 0; i < LEN_CODE; i++) {
+            buffer.append(random.nextInt(10));
+        }
+        return buffer.toString();
+    }
+}

+ 14 - 0
src/main/java/com/miekir/shibei/tool/DateTool.java

@@ -0,0 +1,14 @@
+package com.miekir.shibei.tool;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DateTool {
+    private static final String FORMAT = "yyyyMMdd";
+    private DateTool() {}
+
+    public static String getCurrentDate() {
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(FORMAT);
+        return simpleDateFormat.format(new Date());
+    }
+}

+ 43 - 0
src/main/java/com/miekir/shibei/tool/MD5Tool.java

@@ -0,0 +1,43 @@
+package com.miekir.shibei.tool;
+
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * Copyright (C), 2019-2020, Miekir
+ *
+ * @author Miekir
+ * @date 2020/8/7 18:37
+ * Description: md5工具
+ */
+public class MD5Tool {
+    private MD5Tool(){}
+
+    /**
+     * 将字符串转成MD5值
+     * @param string
+     * @return
+     */
+    public static String stringToMD5(String string) {
+        byte[] hash;
+        try {
+            hash = MessageDigest.getInstance("MD5").digest(string.getBytes(Charset.forName("UTF-8")));
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            return null;
+        }
+
+        StringBuilder hex = new StringBuilder(hash.length * 2);
+        for (byte b : hash) {
+            if ((b & 0xFF) < 0x10) {
+                hex.append(0);
+            }
+            hex.append(Integer.toHexString(b & 0xFF));
+        }
+        return hex.toString();
+    }
+
+}

+ 62 - 0
src/main/java/com/miekir/shibei/tool/RequestTool.java

@@ -0,0 +1,62 @@
+package com.miekir.shibei.tool;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.User;
+import com.miekir.shibei.constants.ServerConstants;
+import com.miekir.shibei.repository.UserRepository;
+import org.springframework.http.HttpHeaders;
+
+import java.util.List;
+
+public class RequestTool {
+    private RequestTool() {}
+
+    public static boolean isRequestValid(HttpHeaders header, UserRepository userRepository) {
+        String token = header.getFirst("token");
+        String email = header.getFirst("email");
+
+        if (TextUtils.isEmpty(token) || TextUtils.isEmpty(email)) {
+            return false;
+        }
+
+        // 根据email查找用户,查询用户的token是否相同
+        User dbUserBean;
+        try {
+            dbUserBean = userRepository.findUserByEmail(email);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+
+        // 用户token不一致
+        if (dbUserBean == null || !TextUtils.equals(token, dbUserBean.getToken())) {
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean isRequestAdminValid(HttpHeaders header, UserRepository userRepository) {
+        String email = header.getFirst("email");
+        if (!TextUtils.equals(email, ServerConstants.EMAIL_ADMIN)) {
+            return false;
+        }
+        return isRequestValid(header, userRepository);
+    }
+
+    public static User getUserByToken(UserRepository userRepository, String token) {
+        // 根据email查找用户,查询用户的token是否相同
+        List<User> dbUserBeanList;
+        try {
+            dbUserBeanList = userRepository.findUserByToken(token);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+
+        if (dbUserBeanList == null || dbUserBeanList.size() != 1) {
+            return null;
+        }
+
+        return dbUserBeanList.get(0);
+    }
+}

+ 31 - 0
src/main/java/com/miekir/shibei/tool/StringTool.java

@@ -0,0 +1,31 @@
+package com.miekir.shibei.tool;
+
+import java.io.UnsupportedEncodingException;
+
+public class StringTool {
+    private StringTool() {}
+    public static String getUtf8String(String str8859_1) {
+        String strUtf8 = null;
+        if (!TextUtils.isEmpty(str8859_1)) {
+            try {
+                strUtf8 = new String(str8859_1.getBytes("ISO8859-1"), "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                strUtf8 = str8859_1;
+                e.printStackTrace();
+            }
+        }
+        return strUtf8;
+    }
+
+    public static String getRawToken(String mixToken) {
+        if (TextUtils.isEmpty(mixToken) || mixToken.length() < 2) {
+            return mixToken;
+        }
+        int len = mixToken.length();
+        char[] tokenArray = mixToken.toCharArray();
+        char temp = tokenArray[len-2];
+        tokenArray[len-2] = tokenArray[len-1];
+        tokenArray[len-1] = temp;
+        return new String(tokenArray);
+    }
+}

+ 24 - 0
src/main/java/com/miekir/shibei/tool/TextUtils.java

@@ -0,0 +1,24 @@
+package com.miekir.shibei.tool;
+
+public class TextUtils {
+    public static boolean equals(String left, String right) {
+
+        if (left == null && right == null) {
+            return true;
+        }
+
+        if (left == null) {
+            return false;
+        }
+
+        return left.equals(right);
+    }
+
+    public static boolean isEmpty(String text) {
+        if (text == null || text.length() == 0) {
+            return true;
+        }
+
+        return false;
+    }
+}

+ 38 - 0
src/main/java/com/miekir/shibei/tool/TokenGenerator.java

@@ -0,0 +1,38 @@
+package com.miekir.shibei.tool;
+
+import com.miekir.shibei.tool.secure.SecureManager;
+
+/**
+ * token = (邮件 + 注册|登录时间 --> AES加密),这样拿到一个token之后,可以通过解密,知道原来的账号和token产生时间,看token是否过期
+ */
+public class TokenGenerator {
+    private static TokenGenerator tokenGenerator;
+    private TokenGenerator() {
+
+    }
+
+    public static TokenGenerator getInstance() {
+        if (tokenGenerator == null) {
+            init();
+        }
+        return tokenGenerator;
+    }
+
+    private static synchronized void init() {
+        if (tokenGenerator == null) {
+            tokenGenerator = new TokenGenerator();
+        }
+    }
+
+    public String getToken(String email) {
+        String token;
+        try {
+            token = SecureManager.getInstance().encrypt(email+System.currentTimeMillis());
+            token = MD5Tool.stringToMD5(token);
+        } catch (Exception e) {
+            token = "";
+            e.printStackTrace();
+        }
+        return token;
+    }
+}

File diff suppressed because it is too large
+ 278 - 0
src/main/java/com/miekir/shibei/tool/WebTool.java


+ 17 - 0
src/main/java/com/miekir/shibei/tool/email/EmailAuthenticator.java

@@ -0,0 +1,17 @@
+package com.miekir.shibei.tool.email;
+import javax.mail.Authenticator;
+import javax.mail.PasswordAuthentication;
+public class EmailAuthenticator extends Authenticator {
+    String userName = null;
+    String password = null;
+    public EmailAuthenticator() {
+    }
+    public EmailAuthenticator(String username, String password) {
+        this.userName = username;
+        this.password = password;
+    }
+    protected PasswordAuthentication getPasswordAuthentication() {
+        return new PasswordAuthentication(userName, password);
+    }
+}
+

+ 154 - 0
src/main/java/com/miekir/shibei/tool/email/EmailTool.java

@@ -0,0 +1,154 @@
+package com.miekir.shibei.tool.email;
+
+import com.sun.mail.util.MailSSLSocketFactory;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.util.Properties;
+
+import javax.mail.*;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+
+/**
+ * JavaMail发送邮件:前提是QQ邮箱里帐号设置要开启POP3/SMTP协议
+ * 为了避免发布项目时,依赖的jar包总是要拷贝到Tomcat的lib目录下这种情况:
+ * File --> Project Structure --> Artifacts --> war/war exploded
+ * --> Output Layout下左侧Add并选中要导入的jar,然后右侧邮件 --> pack into --> apply
+ */
+public class EmailTool {
+
+    public static final int SUCCESS = 0;
+    public static final int FAILED = -1;
+
+    /**
+     * 发邮件 25端口
+     * @throws Exception
+     */
+    public int sendEmail25(String content, String toEmailAddress) {
+        String subject = "验证码";
+        Properties properties = new Properties();
+        properties.put("mail.smtp.host", "smtp.qq.com");
+        properties.put("mail.smtp.port", "25");
+        properties.put("mail.smtp.auth", "true");
+        Authenticator authenticator = new EmailAuthenticator("[email protected]", "svbykovbevxjbdcg");
+        javax.mail.Session sendMailSession = javax.mail.Session.getDefaultInstance(properties, authenticator);
+        MimeMessage mailMessage = new MimeMessage(sendMailSession);
+        try {
+            // 自定义发件人为中文名
+            String nickName = "";
+            try {
+                nickName = javax.mail.internet.MimeUtility.encodeText("吾记科技");
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
+            // 添加了中文,必须要用尖括号把邮箱括起来,否则会发送失败
+            mailMessage.setFrom(new InternetAddress(nickName + " <[email protected]>"));
+
+            //mailMessage.setFrom(new InternetAddress("[email protected]"));
+            // Message.RecipientType.TO属性表示接收者的类型为TO
+            mailMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(toEmailAddress));
+            mailMessage.setSubject(subject, "UTF-8");
+            mailMessage.setSentDate(new Date());
+            // MiniMultipart类是一个容器类,包含MimeBodyPart类型的对象
+            Multipart mainPart = new MimeMultipart();
+            // 创建一个包含HTML内容的MimeBodyPart
+            BodyPart html = new MimeBodyPart();
+            html.setContent(content.trim(), "text/html; charset=utf-8");
+            mainPart.addBodyPart(html);
+            mailMessage.setContent(mainPart);
+            Transport.send(mailMessage);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return FAILED;
+        }
+
+        return SUCCESS;
+    }
+
+    /**
+     * 465端口
+     * @param content
+     * @param toEmailAddress
+     * @return
+     */
+    public int sendEmail(String content, String toEmailAddress) {
+        Properties prop = new Properties();
+        // 开启debug调试,以便在控制台查看
+        prop.setProperty("mail.debug", "true");
+        // 设置邮件服务器主机名
+        prop.setProperty("mail.host", "smtp.qq.com");
+        // 发送服务器需要身份验证
+        prop.setProperty("mail.smtp.auth", "true");
+        // 发送邮件协议名称
+        prop.setProperty("mail.transport.protocol", "smtp");
+
+        try {
+            // 开启SSL加密,否则会失败
+            MailSSLSocketFactory sf = new MailSSLSocketFactory();
+            sf.setTrustAllHosts(true);
+            prop.put("mail.smtp.ssl.enable", "true");
+            prop.put("mail.smtp.ssl.socketFactory", sf);
+
+            // 创建session
+            Session session = Session.getInstance(prop);
+            // 通过session得到transport对象
+            Transport ts = session.getTransport();
+            // 连接邮件服务器:邮箱类型,帐号,授权码代替密码(更安全),自行修改账号和授权码
+            ts.connect("smtp.qq.com", "[email protected]", "svbykovbevxjbdcg");// 后面的字符是授权码
+            // 创建邮件
+            Message message = createSimpleMail(session, toEmailAddress, content);
+            // 发送邮件
+            ts.sendMessage(message, message.getAllRecipients());
+            ts.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return FAILED;
+        }
+        return SUCCESS;
+    }
+
+
+
+
+    /**
+     * @Method: createSimpleMail
+     * @Description: 创建一封只包含文本的邮件
+     */
+    public static MimeMessage createSimpleMail(Session session, String to, String content) throws Exception {
+        String subject = "验证码";
+        // 创建邮件对象
+        MimeMessage message = new MimeMessage(session);
+        // 指明邮件的发件人
+        //message.setFrom(new InternetAddress("[email protected]"));
+        // 自定义发件人为中文名
+        String nickName = "";
+        try {
+            nickName = javax.mail.internet.MimeUtility.encodeText("吾记科技");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        // 添加了中文,必须要用尖括号把邮箱括起来,否则会发送失败
+        message.setFrom(new InternetAddress(nickName + " <[email protected]>"));
+        // 指明邮件的收件人,现在发件人和收件人是一样的,那就是自己给自己发
+        message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
+        // 邮件的标题
+        //message.setSubject("JavaMail测试");
+        // 邮件的文本内容
+        //message.setContent("<font style='color:red'>JavaMail发送邮件成功!</font>", "text/html;charset=UTF-8");
+        // 返回创建好的邮件对象
+        message.setSubject(subject, "UTF-8");
+        message.setSentDate(new Date());
+        // MiniMultipart类是一个容器类,包含MimeBodyPart类型的对象
+        Multipart mainPart = new MimeMultipart();
+        // 创建一个包含HTML内容的MimeBodyPart
+        BodyPart html = new MimeBodyPart();
+        html.setContent(content.trim(), "text/html; charset=utf-8");
+        mainPart.addBodyPart(html);
+        message.setContent(mainPart);
+        return message;
+    }
+}

+ 109 - 0
src/main/java/com/miekir/shibei/tool/secure/SecureManager.java

@@ -0,0 +1,109 @@
+package com.miekir.shibei.tool.secure;
+
+import java.security.Key;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Created by Jason on 2018/8/20.
+ */
+
+public class SecureManager {
+    public static final String KEY_REAL = "rzxlszyYwpbgQczZ";
+    public static final String KEY_FOR_CLIENT = "zrZsyQwplYzxbcgz";
+    public static final String IV_REAL = "cHxlqqxMbdwwlccc";
+    public static final String IV_FOR_CLIENT = "lqbwxlqccMccxdwH";
+
+    private static SecureManager secureManager;
+    private SecureManager() {}
+
+    public static SecureManager getInstance() {
+        if (secureManager == null) {
+            init();
+        }
+
+        return secureManager;
+    }
+
+    private static synchronized void init() {
+        if (secureManager == null) {
+            secureManager = new SecureManager();
+        }
+    }
+
+    public String encrypt(String text) throws Exception {
+        return encrypt(text, KEY_REAL, IV_REAL);
+    }
+
+    public String encrypt(String text, String key, String iv) throws Exception {
+        // 私钥 AES固定格式为128/192/256bits.即:16/24/32bytes。DES固定格式为128bits,即8bytes。
+        // 初始化向量参数,AES 为16bytes. DES 为8bytes
+
+        // 两个参数,第一个为私钥字节数组, 第二个为加密方式AES或者DES
+        Key keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
+
+        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes("UTF-8"));
+        // 实例化加密类,参数为加密方式,要写全
+        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+        // 初始化,此方法可以采用三种方式,按服务器要求来添加。(1)无第三个参数(2)第三个参数为SecureRandom
+        //(3)采用此代码中的IVParameterSpec
+        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
+
+        // random = new SecureRandom();中random对象,随机数。(AES不可采用这种方法)
+        // cipher.init(Cipher.ENCRYPT_MODE, keySpec);
+        // SecureRandom random = new SecureRandom();
+        // cipher.init(Cipher.ENCRYPT_MODE, keySpec, random);
+        byte[] bytes = cipher.doFinal(text.getBytes("UTF-8"));// 加密操作,返回加密后的字节数组,然后需要编码。主要编解码方式有Base64, HEX, UUE,
+        // 7bit等等。此处看服务器需要什么编码方式
+        return parseByte2HexStr(bytes);
+    }
+
+    public String decrypt(String text) throws Exception {
+
+        return decrypt(text, KEY_REAL, IV_REAL);
+    }
+
+    public String decrypt(String text, String keySpec, String iv) throws Exception {
+        byte[] bytes = parseHexStr2Byte(text);
+        //byte[] textBytes = Base64.decode(bytes, Base64.DEFAULT);
+        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes("UTF-8"));
+        Key key = new SecretKeySpec(keySpec.getBytes("UTF-8"), "AES");
+        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+        cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); // 与加密时不同MODE:Cipher.DECRYPT_MODE
+        return new String(cipher.doFinal(bytes), "UTF-8");
+    }
+
+    /**将二进制转换成16进制
+     * @param buf
+     * @return
+     */
+    private String parseByte2HexStr(byte buf[]) {
+        StringBuffer sb = new StringBuffer();
+        for (byte aBuf : buf) {
+            String hex = Integer.toHexString(aBuf & 0xFF);
+            if (hex.length() == 1) {
+                hex = '0' + hex;
+            }
+            sb.append(hex.toUpperCase());
+        }
+        return sb.toString();
+    }
+
+    /**将16进制转换为二进制
+     * @param hexStr
+     * @return
+     */
+    private byte[] parseHexStr2Byte(String hexStr) {
+        if (hexStr.length() < 1)
+            return null;
+        byte[] result = new byte[hexStr.length()/2];
+        for (int i = 0;i< hexStr.length()/2; i++) {
+            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
+            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
+            result[i] = (byte) (high * 16 + low);
+        }
+        return result;
+    }
+}

+ 37 - 0
src/main/resources/META-INF/persistence.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
+    <persistence-unit name="defaultPersistenceUnit"  transaction-type="RESOURCE_LOCAL">
+        <provider>org.hibernate.ejb.HibernatePersistence</provider>
+        <properties>
+            <!-- 使用MySQL方言 -->
+            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
+            <!-- 数据库连接的URL地址 -->
+            <!--schema一定要先在MySQL Workbench建好,schema其实相当于真正的数据库,数据库都没有,怎么可能成功呢。
+            MySQL Workbench中新建Schema的时候,一定要选择utf8-utf8_general_ci,否则会乱码,导致插入数据库出错。这里的schema是shibei,如下:-->
+            <property name="hibernate.connection.url"
+                      value="jdbc:mysql://localhost:3306/shibei"/>
+            <!-- 数据库连接的驱动 -->
+            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
+            <!-- 数据库连接的用户名 -->
+            <property name="hibernate.connection.username" value="root"/>
+            <!-- 数据库连接的密码 -->
+            <property name="hibernate.connection.password" value="Away6899458"/>
+            <!-- 显示SQL语句 -->
+            <property name="hibernate.show_sql" value="true"/>
+
+            <property name="hibernate.connection.useUnicode" value="true"/>
+            <property name="hibernate.connection.characterEncoding" value="UTF-8"/>
+
+            <!-- 在显示SQL语句时格式化语句 -->
+            <property name="hibernate.format_sql" value="true"/>
+            <property name="hibernate.use_sql_comments" value="false"/>
+            <!-- 自动输出schema创建DDL语句 -->
+            <property name="hibernate.hbm2ddl.auto" value="update"/>
+
+            <!-- 数据库连接超时后自动重连 -->
+            <property name="hibernate.connection.autoReconnect" value="true"/>
+            <property name="connection.autoReconnectForPools" value="true"/>
+            <property name="connection.is-connection-validation-required" value="true"/>
+        </properties>
+    </persistence-unit>
+</persistence>

+ 0 - 0
src/main/resources/application.properties


+ 39 - 0
src/main/resources/spring_mvc_user.sql

@@ -0,0 +1,39 @@
+/*
+ Navicat MySQL Data Transfer
+
+ Source Server         : Localhost
+ Source Server Type    : MySQL
+ Source Server Version : 50542
+ Source Host           : 127.0.0.1
+ Source Database       : test
+
+ Target Server Type    : MySQL
+ Target Server Version : 50542
+ File Encoding         : utf-8
+
+ Date: 08/04/2017 21:20:53 PM
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+--  Table structure for `spring_mvc_user`
+-- ----------------------------
+DROP TABLE IF EXISTS `spring_mvc_user`;
+CREATE TABLE `spring_mvc_user` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `firstName` varchar(32) DEFAULT NULL,
+  `lastName` varchar(32) DEFAULT NULL,
+  `password` varchar(32) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+--  Records of `spring_mvc_user`
+-- ----------------------------
+BEGIN;
+INSERT INTO `spring_mvc_user` VALUES ('1', 'taylor', 'hanqun', '123456'), ('2', 'Kobe', 'Bryant', '131415');
+COMMIT;
+
+SET FOREIGN_KEY_CHECKS = 1;

File diff suppressed because it is too large
+ 105 - 0
src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml


+ 41 - 0
src/main/webapp/WEB-INF/web.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+         version="3.1">
+
+    <display-name>SpringMVCDemo Web Application</display-name>
+
+    <servlet>
+        <servlet-name>mvc-dispatcher</servlet-name>
+        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>mvc-dispatcher</servlet-name>
+        <url-pattern>/</url-pattern>
+    </servlet-mapping>
+
+    <!--  为了能够处理中文的post请求,再配置一个encodingFilter,以避免post请求中文出现乱码情况,但是没有解决get请求的中文乱码,
+    需要在Tomcat的server.xml增加: -->
+    <!--<Connector port="8080" protocol="HTTP/1.1"
+               connectionTimeout="20000"
+               redirectPort="8443" URIEncoding="UTF-8"/>-->
+    <filter>
+        <filter-name>encodingFilter</filter-name>
+        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
+        <init-param>
+            <param-name>encoding</param-name>
+            <param-value>UTF-8</param-value>
+        </init-param>
+        <init-param>
+            <param-name>forceEncoding</param-name>
+            <param-value>true</param-value>
+        </init-param>
+    </filter>
+    <filter-mapping>
+        <filter-name>encodingFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+</web-app>

File diff suppressed because it is too large
+ 5 - 0
src/main/webapp/css/bootstrap.min.css


+ 59 - 0
src/main/webapp/html/addUser.jsp

@@ -0,0 +1,59 @@
+<%--
+  Created by IntelliJ IDEA.
+  User: sjj
+  Date: 2015/10/24 0024
+  Time: 20:13
+  To change this template use File | Settings | File Templates.
+--%>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
+  <title>SpringMVC 添加用户</title>
+
+  <!-- 新 Bootstrap 核心 CSS 文件 -->
+  <link rel="stylesheet" href="/css/bootstrap.min.css">
+
+  <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+  <!--[if lt IE 9]>
+  <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+  <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
+  <![endif]-->
+</head>
+<body>
+<div class="container">
+  <h1>SpringMVC 添加用户</h1>
+  <hr/>
+  <form:form action="/addUserPost" method="post" commandName="user" role="form">
+    <div class="form-group">
+      <label for="firstName">First Name:</label>
+      <input type="text" class="form-control" id="firstName" name="firstName" placeholder="Enter FirstName:"/>
+    </div>
+    <div class="form-group">
+      <label for="lastName">Last Name:</label>
+      <input type="text" class="form-control" id="lastName" name="lastName" placeholder="Enter LastName:"/>
+    </div>
+    <div class="form-group">
+      <label for="password">Password:</label>
+      <input type="text" class="form-control" id="password" name="password" placeholder="Enter Password:"/>
+    </div>
+    <div class="form-group">
+      <button type="submit" class="btn btn-sm btn-success">提交</button>
+    </div>
+  </form:form>
+</div>
+
+
+<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
+<script src="/js/jquery.min.js"></script>
+
+<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
+<script src="/js/bootstrap.min.js"></script>
+</body>
+</html>

+ 39 - 0
src/main/webapp/html/index.jsp

@@ -0,0 +1,39 @@
+<%--
+  Created by IntelliJ IDEA.
+  User: sjj
+  Date: 2015/10/24 0024
+  Time: 17:02
+  To change this template use File | Settings | File Templates.
+--%>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
+  <title>SpringMVC Demo 首页</title>
+
+  <!-- 新 Bootstrap 核心 CSS 文件 -->
+  <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
+
+  <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+  <!--[if lt IE 9]>
+  <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+  <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
+  <![endif]-->
+</head>
+<body>
+<h1>这里是SpringMVC Demo首页</h1>
+
+<h3>出现此页面,说明配置成功。</h3>
+
+<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
+<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
+
+<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
+<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
+</body>
+</html>

+ 66 - 0
src/main/webapp/html/updateUser.jsp

@@ -0,0 +1,66 @@
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
+<%--
+  Created by IntelliJ IDEA.
+  User: sjj
+  Date: 2015/10/24 0024
+  Time: 20:36
+  To change this template use File | Settings | File Templates.
+--%>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
+  <title>SpringMVC Demo 首页</title>
+
+  <!-- 新 Bootstrap 核心 CSS 文件 -->
+  <link rel="stylesheet" href="/css/bootstrap.min.css">
+
+  <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+  <!--[if lt IE 9]>
+  <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+  <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
+  <![endif]-->
+</head>
+<body>
+<div class="container">
+  <h1>SpringMVC 更新用户信息</h1>
+  <hr/>
+
+  <form:form action="/updateUserPost" method="post" commandName="userP" role="form">
+    <div class="form-group">
+      <label for="firstName">First Name:</label>
+      <input type="text" class="form-control" id="firstName" name="firstName" placeholder="Enter FirstName:"
+             value="${user.firstName}"/>
+    </div>
+    <div class="form-group">
+      <label for="lastName">Last Name:</label>
+      <input type="text" class="form-control" id="lastName" name="lastName" placeholder="Enter LastName:"
+             value="${user.lastName}"/>
+    </div>
+    <div class="form-group">
+      <label for="password">Password:</label>
+      <input type="text" class="form-control" id="password" name="password" placeholder="Enter Password:"
+             value="${user.password}"/>
+    </div>
+    <!-- 把 id 一并写入 userP 中 -->
+    <input type="hidden" id="id" name="id" value="${user.id}"/>
+
+    <div class="form-group">
+      <button type="submit" class="btn btn-sm btn-success">提交</button>
+    </div>
+  </form:form>
+</div>
+
+
+<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
+<script src="/js/jquery.min.js"></script>
+
+<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
+<script src="/js/bootstrap.min.js"></script>
+</body>
+</html>

+ 60 - 0
src/main/webapp/html/userDetail.jsp

@@ -0,0 +1,60 @@
+<%--
+  Created by IntelliJ IDEA.
+  User: sjj
+  Date: 2015/10/24 0024
+  Time: 20:28
+  To change this template use File | Settings | File Templates.
+--%>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
+  <title>SpringMVC 用户详情</title>
+
+  <!-- 新 Bootstrap 核心 CSS 文件 -->
+  <link rel="stylesheet" href="/css/bootstrap.min.css">
+
+  <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+  <!--[if lt IE 9]>
+  <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+  <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
+  <![endif]-->
+</head>
+<body>
+<div class="container">
+  <h1>SpringMVC 用户详情</h1>
+  <hr/>
+
+  <table class="table tavble-bordered table-striped">
+    <tr>
+      <th>ID</th>
+      <td>${user.id}</td>
+    </tr>
+    <tr>
+      <th>First Name</th>
+      <td>${user.firstName}</td>
+    </tr>
+    <tr>
+      <th>Last Name</th>
+      <td>${user.lastName}</td>
+    </tr>
+    <tr>
+      <th>Password</th>
+      <td>${user.password}</td>
+    </tr>
+  </table>
+</div>
+
+
+<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
+<script src="/js/jquery.min.js"></script>
+
+<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
+<script src="/js/bootstrap.min.js"></script>
+</body>
+</html>

+ 78 - 0
src/main/webapp/html/userManage.jsp

@@ -0,0 +1,78 @@
+<%--
+  Created by IntelliJ IDEA.
+  User: sjj
+  Date: 2015/10/24 0024
+  Time: 19:52
+  To change this template use File | Settings | File Templates.
+--%>
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
+  <title>SpringMVC 用户管理</title>
+
+  <!-- 新 Bootstrap 核心 CSS 文件 -->
+  <link rel="stylesheet" href="/css/bootstrap.min.css">
+
+  <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+  <!--[if lt IE 9]>
+  <script src="//cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+  <script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
+  <![endif]-->
+</head>
+<body>
+<div class="container">
+  <h1>SpringMVC 博客系统-用户管理</h1>
+  <hr/>
+
+  <h3>所有用户 <a href="/addUser" type="button" class="btn btn-default btn-sm">添加</a></h3>
+
+  <!-- 如果用户列表为空 -->
+  <c:if test="${empty userList}">
+    <p class="bg-warning">
+      <br/>
+      User表为空,请<a href="/addUser" type="button" class="btn btn-default btn-sm">添加</a>
+      <br/>
+      <br/>
+    </p>
+  </c:if>
+
+  <!-- 如果用户列表非空 -->
+  <c:if test="${!empty userList}">
+    <table class="table table-bordered table-striped">
+      <tr>
+        <th>ID</th>
+        <th>姓名</th>
+        <th>密码</th>
+        <th>操作</th>
+      </tr>
+
+      <c:forEach items="${userList}" var="user">
+        <tr>
+          <td>${user.id}</td>
+          <td>${user.firstName} ${user.lastName}</td>
+          <td>${user.password}</td>
+          <td>
+            <a href="/showUser/${user.id}" type="button" class="btn btn-sm btn-success">详情</a>
+            <a href="/updateUser/${user.id}" type="button" class="btn btn-sm btn-warning">修改</a>
+            <a href="/deleteUser/${user.id}" type="button" class="btn btn-sm btn-danger">删除</a>
+          </td>
+        </tr>
+      </c:forEach>
+    </table>
+  </c:if>
+</div>
+
+<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
+<script src="/js/jquery.min.js"></script>
+
+<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
+<script src="/js/bootstrap.min.js"></script>
+</body>
+</html>

File diff suppressed because it is too large
+ 7 - 0
src/main/webapp/js/bootstrap.min.js


File diff suppressed because it is too large
+ 6 - 0
src/main/webapp/js/jquery.min.js


+ 7 - 0
注意.txt

@@ -0,0 +1,7 @@
+生成的文件名叫什么名字,那么网址就拼上什么。比如,生成的war为:wuji_war.war
+如果不重命名,那么就会由以下网址访问:
+首页:
+http://www.shuiliu520.com:8940/wuji_war
+并且我们build的war默认就是我们平时配置的8080端口。所以,你的服务器如果多开tomcat,并且你使用的不是8080端口的tomcat,那么还要在我们这个项目做相应的改动。
+
+发布的时候注意:要拷贝邮件和html解析的jar包到tomcat目录下