浏览代码

拾贝服务器初始化

詹子聪 5 年之前
当前提交
2984cd6938
共有 47 个文件被更改,包括 2932 次插入0 次删除
  1. 2 0
      META-INF/MANIFEST.MF
  2. 194 0
      libs/UnlimitedJCEPolicy/README.txt
  3. 二进制
      libs/UnlimitedJCEPolicy/US_export_policy.jar
  4. 二进制
      libs/UnlimitedJCEPolicy/local_policy.jar
  5. 二进制
      libs/mail-1.5.0-b01.jar
  6. 132 0
      pom.xml
  7. 5 0
      src/main/java/com/miekir/shibei/ToDo.java
  8. 57 0
      src/main/java/com/miekir/shibei/bean/Feedback.java
  9. 54 0
      src/main/java/com/miekir/shibei/bean/NoteBean.java
  10. 98 0
      src/main/java/com/miekir/shibei/bean/PasswordBean.java
  11. 40 0
      src/main/java/com/miekir/shibei/bean/ResponseResult.java
  12. 17 0
      src/main/java/com/miekir/shibei/bean/ResultCode.java
  13. 167 0
      src/main/java/com/miekir/shibei/bean/User.java
  14. 57 0
      src/main/java/com/miekir/shibei/bean/WuUpgrade.java
  15. 165 0
      src/main/java/com/miekir/shibei/controller/api/NoteController.java
  16. 174 0
      src/main/java/com/miekir/shibei/controller/api/PasswordController.java
  17. 114 0
      src/main/java/com/miekir/shibei/controller/api/SystemController.java
  18. 360 0
      src/main/java/com/miekir/shibei/controller/api/UserController.java
  19. 18 0
      src/main/java/com/miekir/shibei/controller/web/ShibeiController.java
  20. 43 0
      src/main/java/com/miekir/shibei/interceptor/AuthInterceptor.java
  21. 77 0
      src/main/java/com/miekir/shibei/model/BlogEntity.java
  22. 91 0
      src/main/java/com/miekir/shibei/model/UserEntity.java
  23. 14 0
      src/main/java/com/miekir/shibei/repository/FeedbackRepository.java
  24. 40 0
      src/main/java/com/miekir/shibei/repository/NoteRepository.java
  25. 42 0
      src/main/java/com/miekir/shibei/repository/PasswordRepository.java
  26. 22 0
      src/main/java/com/miekir/shibei/repository/UpgradeRepository.java
  27. 46 0
      src/main/java/com/miekir/shibei/repository/UserRepository.java
  28. 33 0
      src/main/java/com/miekir/shibei/tool/CodeGenerator.java
  29. 24 0
      src/main/java/com/miekir/shibei/tool/TextUtils.java
  30. 37 0
      src/main/java/com/miekir/shibei/tool/TokenGenerator.java
  31. 17 0
      src/main/java/com/miekir/shibei/tool/email/EmailAuthenticator.java
  32. 151 0
      src/main/java/com/miekir/shibei/tool/email/EmailTool.java
  33. 109 0
      src/main/java/com/miekir/shibei/tool/secure/SecureManager.java
  34. 37 0
      src/main/resources/META-INF/persistence.xml
  35. 0 0
      src/main/resources/application.properties
  36. 39 0
      src/main/resources/spring_mvc_user.sql
  37. 94 0
      src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
  38. 37 0
      src/main/webapp/WEB-INF/web.xml
  39. 5 0
      src/main/webapp/css/bootstrap.min.css
  40. 59 0
      src/main/webapp/html/addUser.jsp
  41. 39 0
      src/main/webapp/html/index.jsp
  42. 66 0
      src/main/webapp/html/updateUser.jsp
  43. 60 0
      src/main/webapp/html/userDetail.jsp
  44. 78 0
      src/main/webapp/html/userManage.jsp
  45. 7 0
      src/main/webapp/js/bootstrap.min.js
  46. 6 0
      src/main/webapp/js/jquery.min.js
  47. 5 0
      注意.txt

+ 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/mail-1.5.0-b01.jar


+ 132 - 0
pom.xml

@@ -0,0 +1,132 @@
+<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.48</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>
+
+
+  </dependencies>
+
+  <build>
+    <finalName>shibei</finalName>
+  </build>
+</project>

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

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

+ 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;
+    }
+}

+ 54 - 0
src/main/java/com/miekir/shibei/bean/NoteBean.java

@@ -0,0 +1,54 @@
+package com.miekir.shibei.bean;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "t_note", schema = "shibei", catalog = "")
+public class NoteBean {
+    private Integer id;
+    private String content;
+    private String userId;
+    private Long updateTime;
+
+    // Id自增
+    @Id
+    @GeneratedValue(strategy= GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = false)
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    @Column(name = "userId", nullable = true, insertable = true, updatable = true)
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    @Basic
+    @Column(name = "updateTime", nullable = true, insertable = true, updatable = true)
+    public Long getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Long updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    /*columnDefinition = "MEDIUMTEXT"可以解决文字太长保存不进去的bug*/
+    @Basic
+    @Column(columnDefinition = "MEDIUMTEXT", name = "content", nullable = true, insertable = true, updatable = true)
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+}

+ 98 - 0
src/main/java/com/miekir/shibei/bean/PasswordBean.java

@@ -0,0 +1,98 @@
+package com.miekir.shibei.bean;
+
+import javax.persistence.*;
+
+/**
+ * https://segmentfault.com/q/1010000007793692?_ea=1455968
+ * 外键约束主要是在数据库层面上保证数据的一致性,对性能提升没什么帮助,因为插入和更新数据需要检查外键,理论上性能会有所下降,在oralce中外键会增加主从表中主表锁定的竞争,对性能是负面的影响。
+ * 实际的项目,不建议使用外键,一方面是降低开发的复杂度(有外键的话主从表类的操作必须先操作主表),另外是有外键在处理数据的时候非常麻烦。
+ */
+
+@Entity
+@Table(name = "t_password", schema = "shibei", catalog = "")
+public class PasswordBean {
+    private Integer id;
+    private String platform;
+    private String url;
+    private String account;
+    private String password;
+    private String description;
+    private String userId;
+    private Long updateTime;
+
+    // Id自增
+    @Id
+    @GeneratedValue(strategy= GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = false)
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    @Column(name = "platform", nullable = true, insertable = true, updatable = true)
+    public String getPlatform() {
+        return platform;
+    }
+
+    public void setPlatform(String platform) {
+        this.platform = platform;
+    }
+
+    @Column(name = "url", nullable = true, insertable = true, updatable = true)
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    @Column(name = "account", nullable = true, insertable = true, updatable = true)
+    public String getAccount() {
+        return account;
+    }
+
+    public void setAccount(String account) {
+        this.account = account;
+    }
+
+    @Column(name = "password", nullable = true, insertable = true, updatable = true)
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    @Column(name = "description", nullable = true, insertable = true, updatable = true)
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @Column(name = "userId", nullable = true, insertable = true, updatable = true)
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    @Basic
+    @Column(name = "updateTime", nullable = true, insertable = true, updatable = true)
+    public Long getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Long updateTime) {
+        this.updateTime = updateTime;
+    }
+}

+ 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 resultCode = -1;
+    private String message;
+    private String extra;
+    private T resultObj;
+
+    public int getResultCode() {
+        return resultCode;
+    }
+
+    public void setResultCode(int resultCode) {
+        this.resultCode = resultCode;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public T getResultObj() {
+        return resultObj;
+    }
+
+    public void setResultObj(T resultObj) {
+        this.resultObj = resultObj;
+    }
+
+    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;
+}

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

@@ -0,0 +1,167 @@
+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;
+
+    // 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;
+    }
+}

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

@@ -0,0 +1,57 @@
+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 WuUpgrade {
+    private Integer id;
+    private Integer status;
+    private Integer versionCode;
+    private String url;
+
+    // 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;
+    }
+
+    @Basic
+    @Column(name = "status", nullable = true, insertable = true, updatable = true)
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    @Basic
+    @Column(name = "versionCode", nullable = true, insertable = true, updatable = true)
+    public Integer getVersionCode() {
+        return versionCode;
+    }
+
+    public void setVersionCode(Integer versionCode) {
+        this.versionCode = versionCode;
+    }
+
+    @Basic
+    @Column(name = "url", nullable = true, insertable = true, updatable = true)
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+}

+ 165 - 0
src/main/java/com/miekir/shibei/controller/api/NoteController.java

@@ -0,0 +1,165 @@
+package com.miekir.shibei.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.NoteBean;
+import com.miekir.shibei.bean.ResponseResult;
+import com.miekir.shibei.bean.ResultCode;
+import com.miekir.shibei.repository.NoteRepository;
+import com.miekir.shibei.repository.UserRepository;
+import com.miekir.shibei.tool.TextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.util.List;
+
+@Controller
+public class NoteController {
+
+    // 自动装配
+    @Autowired
+    private NoteRepository noteRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    /**
+     * 新增记事,接收的是纯JSON数据  严格来说,也要传递id和token过来校验的
+     */
+    @RequestMapping(value = "/api/addNote", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String addNote(String email, String token, String note_bean) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("保存失败");
+
+        NoteBean bean;
+        try {
+            bean = JSON.parseObject(note_bean, NoteBean.class);
+            bean.setUpdateTime(System.currentTimeMillis());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        NoteBean dbNOteBean;
+        try {
+            dbNOteBean = noteRepository.save(bean);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setResultObj(JSON.toJSONString(dbNOteBean));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("保存成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 删除密码记事
+     */
+    @RequestMapping(value = "/api/delNote", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String delNote(String email, String token, int noteId) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("操作失败");
+
+        NoteBean dbNoteBean;
+        try {
+            dbNoteBean = noteRepository.findNoteBeanById(noteId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 密码不属于该用户
+        if (dbNoteBean == null || !TextUtils.equals(email, dbNoteBean.getUserId())) {
+            return JSON.toJSONString(responseResult);
+        }
+
+
+        try {
+            noteRepository.delete(noteId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("删除成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 查询密码记事
+     */
+    @RequestMapping(value = "/api/getNote", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getNote(String email, String token) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("获取失败");
+
+        List<NoteBean> noteBeanList;
+        try {
+            noteBeanList = noteRepository.findNotesByEmail(email);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setResultObj(JSON.toJSONString(noteBeanList));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 更新密码记事
+     */
+    @RequestMapping(value = "/api/updateNote", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String updateNote(String email, String token, String note_bean) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("更新失败");
+
+        NoteBean clientBean;
+        try {
+            clientBean = JSON.parseObject(note_bean, NoteBean.class);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 发送方的用户和该记事的所有者不是同一个人,没有权限
+        NoteBean oldBean = noteRepository.findNoteBeanById(clientBean.getId());
+        if (!TextUtils.equals(email, oldBean.getUserId())) {
+            return JSON.toJSONString(responseResult);
+        }
+
+
+        try {
+            noteRepository.updateNoteBean(clientBean.getContent(), clientBean.getId(), System.currentTimeMillis());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("更新成功");
+        return JSON.toJSONString(responseResult);
+    }
+}

+ 174 - 0
src/main/java/com/miekir/shibei/controller/api/PasswordController.java

@@ -0,0 +1,174 @@
+package com.miekir.shibei.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.PasswordBean;
+import com.miekir.shibei.bean.ResponseResult;
+import com.miekir.shibei.bean.ResultCode;
+import com.miekir.shibei.repository.PasswordRepository;
+import com.miekir.shibei.repository.UserRepository;
+import com.miekir.shibei.tool.TextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.util.List;
+
+@Controller
+public class PasswordController {
+
+    // 自动装配
+    @Autowired
+    private PasswordRepository passwordRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    /**
+     * 新增密码记事,接收的是纯JSON数据  严格来说,也要传递id和token过来校验的
+     */
+    @RequestMapping(value = "/api/addPassword", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String addPassword(String email, String token, String password_bean) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("保存失败");
+
+        PasswordBean bean;
+        try {
+            //bean = JSON.parseObject(password_bean, PasswordBean.class);
+            bean = JSON.parseObject(password_bean, PasswordBean.class);
+            bean.setUpdateTime(System.currentTimeMillis());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        PasswordBean dbPasswordBean;
+        try {
+            dbPasswordBean = passwordRepository.save(bean);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setResultObj(JSON.toJSONString(dbPasswordBean));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("保存成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 删除密码记事
+     */
+    @RequestMapping(value = "/api/delPassword", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String delPassword(String email, String token, int passwordBeanId) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("操作失败");
+
+        PasswordBean dbPasswordBean;
+        try {
+            dbPasswordBean = passwordRepository.findPasswordBeanById(passwordBeanId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 密码不属于该用户
+        if (dbPasswordBean == null || !TextUtils.equals(email, dbPasswordBean.getUserId())) {
+            return JSON.toJSONString(responseResult);
+        }
+
+
+        try {
+            passwordRepository.delete(passwordBeanId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("删除成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 查询密码记事
+     */
+    @RequestMapping(value = "/api/getPassword", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getPassword(String email, String token) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("获取失败");
+
+        List<PasswordBean> passwordBeanList;
+        try {
+            passwordBeanList = passwordRepository.findPasswordNotesByEmail(email);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setResultObj(JSON.toJSONString(passwordBeanList));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 更新密码记事
+     */
+    @RequestMapping(value = "/api/updatePassword", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String updatePassword(String email, String token, String mixedPasswordBean) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setMessage("更新失败");
+
+        PasswordBean clientBean;
+        try {
+            //bean = JSON.parseObject(password_bean, PasswordBean.class);
+            clientBean = JSON.parseObject(mixedPasswordBean, PasswordBean.class);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 发送方的用户和该记事的所有者不是同一个人,没有权限
+        PasswordBean oldBean = passwordRepository.findPasswordBeanById(clientBean.getId());
+        if (!TextUtils.equals(email, oldBean.getUserId())) {
+            return JSON.toJSONString(responseResult);
+        }
+
+
+        try {
+            passwordRepository.updatePasswordBean(clientBean.getPlatform(), clientBean.getUrl(), clientBean.getAccount(),
+                    clientBean.getPassword(), clientBean.getDescription(), clientBean.getId(), System.currentTimeMillis());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        /*try {
+            responseResult.setResultObj(SecureManager.getInstance().encrypt(JSON.toJSONString(dbPasswordBean)));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }*/
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("更新成功");
+        return JSON.toJSONString(responseResult);
+    }
+}

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

@@ -0,0 +1,114 @@
+package com.miekir.shibei.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.miekir.shibei.bean.Feedback;
+import com.miekir.shibei.bean.ResponseResult;
+import com.miekir.shibei.bean.ResultCode;
+import com.miekir.shibei.bean.WuUpgrade;
+import com.miekir.shibei.repository.FeedbackRepository;
+import com.miekir.shibei.repository.UpgradeRepository;
+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.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 {
+    private static final String EMAIL_FEEDBACK = "[email protected]";
+
+    @Autowired
+    FeedbackRepository feedbackRepository;
+
+    @Autowired
+    UpgradeRepository upgradeRepository;
+
+    /**
+     * 意见反馈
+     */
+    @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.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("反馈失败");
+
+        Feedback feedbackBean = new Feedback();
+        feedbackBean.setEmail(email);
+        feedbackBean.setFeedback(feedback);
+        feedbackBean.setTime(System.currentTimeMillis());
+
+        // 开始重设密码,插入数据库
+        try {
+            feedbackRepository.save(feedbackBean);
+            responseResult.setResultCode(ResultCode.SUCCESS);
+            responseResult.setMessage("反馈成功");
+        } catch (Exception e) {
+            responseResult.setMessage("反馈失败");
+            e.printStackTrace();
+        }
+
+        try {
+            // 同时发送邮件
+            new EmailTool().sendEmail("吾记反馈:" + "【From: " + email + "】" + feedback, EMAIL_FEEDBACK);
+        } 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/getUpgradeInfo", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getUpgradeInfo(String email, String token) {
+        ResponseResult<WuUpgrade> responseResult = new ResponseResult<WuUpgrade>();
+        responseResult.setMessage("获取失败");
+
+        WuUpgrade upgradeInfo;
+        try {
+            upgradeInfo = upgradeRepository.findUpgradeInfoById(0);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        try {
+            responseResult.setResultObj(upgradeInfo);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return JSON.toJSONString(responseResult);
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        return JSON.toJSONString(responseResult);
+    }
+}

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

@@ -0,0 +1,360 @@
+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.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.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.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getAuthCode(String email) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        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.setResultCode(ResultCode.SUCCESS);
+            responseResult.setMessage("获取验证码成功");
+            responseResult.setExtra(SecureManager.KEY_FOR_CLIENT + "=" + SecureManager.IV_FOR_CLIENT);
+        } else {
+            responseResult.setResultCode(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(String email, String password, String code, String nickName) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("注册失败");
+
+        // 从数据库查询,如果没有这个email并且不在黑名单里,才可以继续注册
+        User dbUser = userRepository.findUserByEmail(email);
+        if (dbUser != null) {
+            responseResult.setResultCode(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);
+        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.setResultCode(ResultCode.SUCCESS);
+            responseResult.setMessage("注册成功");
+            responseResult.setResultObj(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.setResultCode(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.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("登录成功");
+        responseResult.setResultObj(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.setResultCode(ResultCode.FAILED_NEED_RE_LOGIN);
+        }
+
+        responseResult.setMessage("token登录成功");
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 重置密码
+     */
+    @RequestMapping(value = "/api/password", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String resetPassword(String email, String code, String password) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("密码重置失败");
+
+        // 从数据库查询,如果有这个email并且不在黑名单里,才可以继续
+        User dbUser = userRepository.findUserByEmail(email);
+        if (dbUser == null) {
+            responseResult.setResultCode(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.setResultCode(ResultCode.SUCCESS);
+            responseResult.setMessage("密码重置成功");
+            responseResult.setResultObj(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.setResultCode(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.setResultCode(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.setResultCode(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.setResultCode(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;
+    }
+}

+ 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> {
+
+}

+ 40 - 0
src/main/java/com/miekir/shibei/repository/NoteRepository.java

@@ -0,0 +1,40 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.NoteBean;
+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 NoteRepository extends JpaRepository<NoteBean, Integer> {
+    // 说明该方法是事务性操作
+    @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);
+
+    // 根据密码Id查询密码记事
+    // 说明该方法是事务性操作
+    @Transactional
+    // @Param注解用于提取参数
+    @Query(value="select note from NoteBean note where note.id=:id")
+    public NoteBean findNoteBeanById(@Param("id") Integer id);
+
+    // 修改密码记事
+    @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);
+}

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

@@ -0,0 +1,42 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.PasswordBean;
+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 PasswordRepository extends JpaRepository<PasswordBean, Integer> {
+    // 说明该方法是事务性操作
+    @Transactional
+    // 根据邮件查询用户所有密码记事
+    // @Param注解用于提取参数
+    @Query(value="select password from PasswordBean password where password.userId=:email order by password.updateTime desc")
+    public List<PasswordBean> findPasswordNotesByEmail(@Param("email") String email);
+
+    // 根据密码Id查询密码记事
+    // 说明该方法是事务性操作
+    @Transactional
+    // @Param注解用于提取参数
+    @Query(value="select password from PasswordBean password where password.id=:id")
+    public PasswordBean findPasswordBeanById(@Param("id") Integer id);
+
+    // 修改密码记事
+    @Modifying
+    // 说明该方法是事务性操作
+    @Transactional
+    // @Param注解用于提取参数
+    @Query("update PasswordBean pass set pass.platform=:platform, pass.url=:url, pass.account=:account, pass.password=:password, pass.description=:description, pass.updateTime=:updateTime where pass.id=:passId")
+    public int updatePasswordBean(@Param("platform") String platform, @Param("url") String url, @Param("account") String account,
+                           @Param("password") String password, @Param("description") String description, @Param("passId") Integer passId,
+                           @Param("updateTime") Long updateTime);
+}

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

@@ -0,0 +1,22 @@
+package com.miekir.shibei.repository;
+
+import com.miekir.shibei.bean.WuUpgrade;
+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 UpgradeRepository extends JpaRepository<WuUpgrade, Integer> {
+    // 根据密码Id查询密码记事
+    // 说明该方法是事务性操作
+    @Transactional
+    // @Param注解用于提取参数
+    @Query(value="select upgradeInfo from WuUpgrade upgradeInfo where upgradeInfo.id=:id")
+    public WuUpgrade findUpgradeInfoById(@Param("id") Integer id);
+}

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

@@ -0,0 +1,46 @@
+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;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface UserRepository extends JpaRepository<User, String> {
+    /*// 说明该方法是修改操作
+    @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);
+
+    // 说明该方法是修改操作
+    @Modifying
+    // 说明该方法是事务性操作
+    @Transactional
+    // 定义查询
+    // @Param注解用于提取参数
+    @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();
+    }
+}

+ 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;
+    }
+}

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

@@ -0,0 +1,37 @@
+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());
+        } catch (Exception e) {
+            token = "";
+            e.printStackTrace();
+        }
+        return token;
+    }
+}

+ 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);
+    }
+}
+

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

@@ -0,0 +1,151 @@
+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协议
+*/
+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;

文件差异内容过多而无法显示
+ 94 - 0
src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml


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

@@ -0,0 +1,37 @@
+<?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请求中文出现乱码情况 -->
+    <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>

文件差异内容过多而无法显示
+ 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>

文件差异内容过多而无法显示
+ 7 - 0
src/main/webapp/js/bootstrap.min.js


文件差异内容过多而无法显示
+ 6 - 0
src/main/webapp/js/jquery.min.js


+ 5 - 0
注意.txt

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