詹子聪 5 gadi atpakaļ
revīzija
01ac23fa9f
63 mainītis faili ar 13279 papildinājumiem un 0 dzēšanām
  1. 7 0
      .gitignore
  2. 2 0
      META-INF/MANIFEST.MF
  3. 14 0
      README.md
  4. 194 0
      libs/UnlimitedJCEPolicy/README.txt
  5. BIN
      libs/UnlimitedJCEPolicy/US_export_policy.jar
  6. BIN
      libs/UnlimitedJCEPolicy/local_policy.jar
  7. BIN
      libs/mail-1.5.0-b01.jar
  8. 132 0
      pom.xml
  9. 5 0
      src/main/java/com/itant/laf/ToDo.java
  10. 55 0
      src/main/java/com/itant/laf/bean/Favorite.java
  11. 22 0
      src/main/java/com/itant/laf/bean/FavoriteResult.java
  12. 66 0
      src/main/java/com/itant/laf/bean/Feedback.java
  13. 207 0
      src/main/java/com/itant/laf/bean/LostFound.java
  14. 37 0
      src/main/java/com/itant/laf/bean/Message.java
  15. 40 0
      src/main/java/com/itant/laf/bean/ResponseResult.java
  16. 17 0
      src/main/java/com/itant/laf/bean/ResultCode.java
  17. 194 0
      src/main/java/com/itant/laf/bean/User.java
  18. 308 0
      src/main/java/com/itant/laf/controller/api/LostFoundController.java
  19. 95 0
      src/main/java/com/itant/laf/controller/api/SystemController.java
  20. 360 0
      src/main/java/com/itant/laf/controller/api/UserController.java
  21. 18 0
      src/main/java/com/itant/laf/controller/web/LAFMainController.java
  22. 43 0
      src/main/java/com/itant/laf/interceptor/AuthInterceptor.java
  23. 77 0
      src/main/java/com/itant/laf/model/BlogEntity.java
  24. 91 0
      src/main/java/com/itant/laf/model/UserEntity.java
  25. 30 0
      src/main/java/com/itant/laf/repository/FavoriteRepository.java
  26. 14 0
      src/main/java/com/itant/laf/repository/FeedbackRepository.java
  27. 138 0
      src/main/java/com/itant/laf/repository/LostFoundRepository.java
  28. 55 0
      src/main/java/com/itant/laf/repository/MessageRepository.java
  29. 56 0
      src/main/java/com/itant/laf/repository/UserRepository.java
  30. 33 0
      src/main/java/com/itant/laf/tool/CodeGenerator.java
  31. 24 0
      src/main/java/com/itant/laf/tool/TextUtils.java
  32. 37 0
      src/main/java/com/itant/laf/tool/TokenGenerator.java
  33. 17 0
      src/main/java/com/itant/laf/tool/email/EmailAuthenticator.java
  34. 71 0
      src/main/java/com/itant/laf/tool/email/EmailTool.java
  35. 109 0
      src/main/java/com/itant/laf/tool/secure/SecureManager.java
  36. 37 0
      src/main/resources/META-INF/persistence.xml
  37. 0 0
      src/main/resources/application.properties
  38. 39 0
      src/main/resources/spring_mvc_user.sql
  39. 93 0
      src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
  40. 37 0
      src/main/webapp/WEB-INF/web.xml
  41. 587 0
      src/main/webapp/css/bootstrap-theme.css
  42. 1 0
      src/main/webapp/css/bootstrap-theme.css.map
  43. 5 0
      src/main/webapp/css/bootstrap-theme.min.css
  44. 6837 0
      src/main/webapp/css/bootstrap.css
  45. 1 0
      src/main/webapp/css/bootstrap.css.map
  46. 5 0
      src/main/webapp/css/bootstrap.min.css
  47. BIN
      src/main/webapp/fonts/glyphicons-halflings-regular.eot
  48. 288 0
      src/main/webapp/fonts/glyphicons-halflings-regular.svg
  49. BIN
      src/main/webapp/fonts/glyphicons-halflings-regular.ttf
  50. BIN
      src/main/webapp/fonts/glyphicons-halflings-regular.woff
  51. BIN
      src/main/webapp/fonts/glyphicons-halflings-regular.woff2
  52. 59 0
      src/main/webapp/html/addUser.jsp
  53. 39 0
      src/main/webapp/html/index.jsp
  54. 81 0
      src/main/webapp/html/msg/message.jsp
  55. 66 0
      src/main/webapp/html/updateUser.jsp
  56. 60 0
      src/main/webapp/html/userDetail.jsp
  57. 78 0
      src/main/webapp/html/userManage.jsp
  58. 2363 0
      src/main/webapp/js/bootstrap.js
  59. 7 0
      src/main/webapp/js/bootstrap.min.js
  60. 4 0
      src/main/webapp/js/jquery-3.1.0.min.js
  61. 6 0
      src/main/webapp/js/jquery.min.js
  62. 13 0
      src/main/webapp/js/npm.js
  63. 5 0
      注意.txt

+ 7 - 0
.gitignore

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

+ 2 - 0
META-INF/MANIFEST.MF

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

+ 14 - 0
README.md

@@ -0,0 +1,14 @@
+### SpringMVC的学习例子,使用Intellij进行的,spring,hibernate,mysql
+
+- 本项目只是一个简单的例子,包含了一个只有两张表的数据库;
+- 一直controller,里面仅有增删改查等操作而已;
+- 学习过程中完全参照博客:http://my.oschina.net/gaussik/blog/385697 相关系列的文章,总共四篇。感谢作者Gaussic(一个为AI而奋斗却不得不兼顾项目的研究生) 的贡献帮助;
+- 具体的请clone项目,使用idea直接打开查看即可;
+- user表放在resources下面
+
+# Demo截图
+
+![](https://raw.githubusercontent.com/Cenyol/SpringMVC/master/images/list.jpg)
+![](https://raw.githubusercontent.com/Cenyol/SpringMVC/master/images/add.jpg)
+![](https://raw.githubusercontent.com/Cenyol/SpringMVC/master/images/update.jpg)
+![](https://raw.githubusercontent.com/Cenyol/SpringMVC/master/images/view.jpg)

+ 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!

BIN
libs/UnlimitedJCEPolicy/US_export_policy.jar


BIN
libs/UnlimitedJCEPolicy/local_policy.jar


BIN
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.itant</groupId>
+  <artifactId>laf</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>laf</finalName>
+  </build>
+</project>

+ 5 - 0
src/main/java/com/itant/laf/ToDo.java

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

+ 55 - 0
src/main/java/com/itant/laf/bean/Favorite.java

@@ -0,0 +1,55 @@
+package com.itant.laf.bean;
+
+import javax.persistence.*;
+
+/**
+ * Created by Jason on 2018/8/26.
+ */
+@Entity
+@Table(name = "t_favorite", schema = "laf", catalog = "")
+public class Favorite {
+    private Integer id;
+    private String userId;
+    private Integer postId;
+    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;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    @Column(name = "userId", nullable = false, insertable = true, updatable = true, length = 50)
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    @Basic
+    @Column(name = "time", nullable = true, insertable = true, updatable = true)
+    public Long getTime() {
+        return time;
+    }
+
+    public void setTime(Long time) {
+        this.time = time;
+    }
+
+    @Column(name = "postId", nullable = false, insertable = true, updatable = true)
+    public Integer getPostId() {
+        return postId;
+    }
+
+    public void setPostId(Integer postId) {
+        this.postId = postId;
+    }
+}

+ 22 - 0
src/main/java/com/itant/laf/bean/FavoriteResult.java

@@ -0,0 +1,22 @@
+package com.itant.laf.bean;
+
+public class FavoriteResult {
+    private int browseNum;
+    private boolean isFavorite;
+
+    public int getBrowseNum() {
+        return browseNum;
+    }
+
+    public void setBrowseNum(int browseNum) {
+        this.browseNum = browseNum;
+    }
+
+    public boolean isFavorite() {
+        return isFavorite;
+    }
+
+    public void setFavorite(boolean favorite) {
+        isFavorite = favorite;
+    }
+}

+ 66 - 0
src/main/java/com/itant/laf/bean/Feedback.java

@@ -0,0 +1,66 @@
+package com.itant.laf.bean;
+
+import javax.persistence.*;
+
+/**
+ * Created by Jason on 2018/8/26.
+ */
+@Entity
+@Table(name = "t_feedback", schema = "laf", catalog = "")
+public class Feedback {
+    private Integer id;
+    private String userId;
+    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;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    @Column(name = "userId", nullable = false, insertable = true, updatable = true, length = 50)
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    @Column(name = "email", 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;
+    }
+}

+ 207 - 0
src/main/java/com/itant/laf/bean/LostFound.java

@@ -0,0 +1,207 @@
+package com.itant.laf.bean;
+
+import javax.persistence.*;
+
+/**
+ * Created by Jason on 2018/10/9.
+ */
+@Entity
+@Table(name = "t_lost_found", schema = "laf", catalog = "")
+public class LostFound {
+    public static final String KEY_POST_TYPE = "post_type";
+    public static final String KEY_LOST_TYPE = "lost_type";
+    public static final int POST_TYPE_LOST = 0;
+    public static final int LOST_TYPE_ALL = 0;
+    public static final int LOST_TYPE_MONEY = 1;
+    public static final int LOST_TYPE_MAN = 2;
+    public static final int LOST_TYPE_GOODS = 3;
+    public static final int LOST_TYPE_PETS = 4;
+    // 我的发布
+    public static final int LOST_TYPE_PUBLISH = -1;
+    // 我的收藏
+    public static final int LOST_TYPE_FAVORITE = -2;
+    public static final int POST_TYPE_FOUND = 1;
+    private Integer lostFoundId;
+    private String authorId;
+
+    // 发帖人是否VIP,发帖人头像URL,当前帖子是否被当前用户所收藏,都是从数据库查到列表后,遍历过程中查询到最新结果,动态set的
+    private Boolean isAuthorVip;
+    private String authorHeadUrl;
+    private Boolean isFavorite;
+
+    // 描述
+    private String content;
+    // 图片
+    private String photoUrl;
+    private Long publishTimeMillis;
+    // 事发城市
+    private String cityName;
+    // 事发城市id
+    private Integer cityId;
+    private Integer commentNum;
+    // 浏览次数
+    private Integer browseNum = 0;
+    // 联系方式
+    private String phoneNumber;
+    // 0失物 1招领
+    private Integer postType;
+    // 失物才有,0寻人 1找物 2爱宠
+    private Integer lostType;
+    // 悬赏金额
+    private Integer money;
+
+    private String authorName;
+
+    @Id
+    @GeneratedValue(strategy= GenerationType.AUTO)
+    @Column(name = "id", nullable = false, insertable = true, updatable = true)
+    public Integer getLostFoundId() {
+        return lostFoundId;
+    }
+
+    public void setLostFoundId(Integer lostFoundId) {
+        this.lostFoundId = lostFoundId;
+    }
+
+    @Column(name = "authorId", nullable = false, insertable = true, updatable = true)
+    public String getAuthorId() {
+        return authorId;
+    }
+
+    public void setAuthorId(String authorId) {
+        this.authorId = authorId;
+    }
+
+    @Column(name = "authorVip", nullable = true, insertable = true, updatable = true)
+    public Boolean getAuthorVip() {
+        return isAuthorVip;
+    }
+
+    public void setAuthorVip(Boolean authorVip) {
+        isAuthorVip = authorVip;
+    }
+
+    @Column(name = "authorHeadUrl", nullable = true, insertable = true, updatable = true)
+    public String getAuthorHeadUrl() {
+        return authorHeadUrl;
+    }
+
+    public void setAuthorHeadUrl(String authorHeadUrl) {
+        this.authorHeadUrl = authorHeadUrl;
+    }
+
+    @Column(name = "favorite", nullable = true, insertable = true, updatable = true)
+    public Boolean getFavorite() {
+        return isFavorite;
+    }
+
+    public void setFavorite(Boolean favorite) {
+        isFavorite = favorite;
+    }
+
+    @Column(name = "content", nullable = true, insertable = true, updatable = true)
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    @Column(name = "photoUrl", nullable = true, insertable = true, updatable = true)
+    public String getPhotoUrl() {
+        return photoUrl;
+    }
+
+    public void setPhotoUrl(String photoUrl) {
+        this.photoUrl = photoUrl;
+    }
+
+    @Column(name = "publishTimeMillis", nullable = true, insertable = true, updatable = true)
+    public Long getPublishTimeMillis() {
+        return publishTimeMillis;
+    }
+
+    public void setPublishTimeMillis(Long publishTimeMillis) {
+        this.publishTimeMillis = publishTimeMillis;
+    }
+
+    @Column(name = "cityName", nullable = true, insertable = true, updatable = true)
+    public String getCityName() {
+        return cityName;
+    }
+
+    public void setCityName(String cityName) {
+        this.cityName = cityName;
+    }
+    @Column(name = "cityId", nullable = true, insertable = true, updatable = true)
+    public Integer getCityId() {
+        return cityId;
+    }
+
+    public void setCityId(Integer cityId) {
+        this.cityId = cityId;
+    }
+
+    @Column(name = "commentNum", nullable = true, insertable = true, updatable = true)
+    public Integer getCommentNum() {
+        return commentNum;
+    }
+
+    public void setCommentNum(Integer commentNum) {
+        this.commentNum = commentNum;
+    }
+
+    @Column(name = "browseNum", nullable = true, insertable = true, updatable = true)
+    public Integer getBrowseNum() {
+        return browseNum;
+    }
+
+    public void setBrowseNum(Integer browseNum) {
+        this.browseNum = browseNum;
+    }
+
+    @Column(name = "phoneNumber", nullable = true, insertable = true, updatable = true)
+    public String getPhoneNumber() {
+        return phoneNumber;
+    }
+
+    public void setPhoneNumber(String phoneNumber) {
+        this.phoneNumber = phoneNumber;
+    }
+
+    @Column(name = "postType", nullable = true, insertable = true, updatable = true)
+    public Integer getPostType() {
+        return postType;
+    }
+
+    public void setPostType(Integer postType) {
+        this.postType = postType;
+    }
+
+    @Column(name = "lostType", nullable = true, insertable = true, updatable = true)
+    public Integer getLostType() {
+        return lostType;
+    }
+
+    public void setLostType(Integer lostType) {
+        this.lostType = lostType;
+    }
+
+    @Column(name = "money", nullable = true, insertable = true, updatable = true)
+    public Integer getMoney() {
+        return money;
+    }
+
+    public void setMoney(Integer money) {
+        this.money = money;
+    }
+
+    public String getAuthorName() {
+        return authorName;
+    }
+
+    public void setAuthorName(String authorName) {
+        this.authorName = authorName;
+    }
+}

+ 37 - 0
src/main/java/com/itant/laf/bean/Message.java

@@ -0,0 +1,37 @@
+package com.itant.laf.bean;
+
+import javax.persistence.*;
+
+/**
+ * Created by Jason on 2018/8/26.
+ */
+@Entity
+@Table(name = "t_message", schema = "laf", catalog = "")
+public class Message {
+    private Integer id;
+    private String messageContent;
+
+
+    // 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 = "messageContent", nullable = true, insertable = true, updatable = true)
+    public String getMessageContent() {
+        return messageContent;
+    }
+
+    public void setMessageContent(String messageContent) {
+        this.messageContent = messageContent;
+    }
+}

+ 40 - 0
src/main/java/com/itant/laf/bean/ResponseResult.java

@@ -0,0 +1,40 @@
+package com.itant.laf.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/itant/laf/bean/ResultCode.java

@@ -0,0 +1,17 @@
+package com.itant.laf.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;
+}

+ 194 - 0
src/main/java/com/itant/laf/bean/User.java

@@ -0,0 +1,194 @@
+package com.itant.laf.bean;
+
+import javax.persistence.*;
+
+/**
+ * Created by Jason on 2018/8/26.
+ */
+@Entity
+@Table(name = "t_user", schema = "laf", catalog = "")
+public class User {
+    public static final int USER_TYPE_INVALID = -1;
+    public static final int USER_TYPE_NORMAL = 0;
+    public static final int USER_TYPE_VIP = 1;
+    //private Integer id;
+    private String userId;
+    private String email;
+    private String nickName;
+    private String password;
+    private String headIcon;
+    private Integer sex;
+    private String token;
+    private Long registerTimeMillis;
+    private Long lastLoginTimeMillis;
+    // 0普通会员,-1是非法用户,1是VIP
+    private Integer userType=0;
+    private String deviceId;
+    private String lastIp;
+    private Integer themeMode;
+    private String phone;
+    private String saying;
+
+    // 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;
+    }*/
+
+    @Id
+    @Column(name = "userId", unique = true, nullable = false, insertable = true, updatable = true, length = 50)
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    @Basic
+    @Column(name = "phone", nullable = true, insertable = true, updatable = true, length = 50)
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    @Basic
+    @Column(name = "email", unique = true, nullable = true, 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 = true, 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 = "deviceId", nullable = true, insertable = true, updatable = true, length = 100)
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    @Basic
+    @Column(name = "lastIp", nullable = true, insertable = true, updatable = true, length = 100)
+    public String getLastIp() {
+        return lastIp;
+    }
+
+    public void setLastIp(String lastIp) {
+        this.lastIp = lastIp;
+    }
+
+    @Basic
+    @Column(name = "themeMode", nullable = true, insertable = true, updatable = true)
+    public Integer getThemeMode() {
+        return themeMode;
+    }
+
+    public void setThemeMode(Integer themeMode) {
+        this.themeMode = themeMode;
+    }
+
+    @Basic
+    @Column(name = "saying", nullable = true, insertable = true, updatable = true, length = 100)
+    public String getSaying() {
+        return saying;
+    }
+
+    public void setSaying(String saying) {
+        this.saying = saying;
+    }
+
+    @Basic
+    @Column(name = "userType", nullable = true, insertable = true, updatable = true)
+    public Integer getUserType() {
+        return userType;
+    }
+
+    public void setUserType(Integer userType) {
+        this.userType = userType;
+    }
+}

+ 308 - 0
src/main/java/com/itant/laf/controller/api/LostFoundController.java

@@ -0,0 +1,308 @@
+package com.itant.laf.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.itant.laf.bean.*;
+import com.itant.laf.repository.FavoriteRepository;
+import com.itant.laf.repository.LostFoundRepository;
+import com.itant.laf.repository.UserRepository;
+import com.itant.laf.tool.TextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.PageRequest;
+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.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.List;
+
+@Controller
+public class LostFoundController {
+    // 自动装配
+    @Autowired
+    private UserRepository userRepository;
+    @Autowired
+    private LostFoundRepository lostFoundRepository;
+    @Autowired
+    HttpServletRequest request;
+    @Autowired
+    FavoriteRepository favoriteRepository;
+    private static final int MAX_BROWSE_NUM = Integer.MAX_VALUE-100;
+
+    @RequestMapping(value = "/api/publishPost", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String publishPost(String userId, String token, int cityId, String cityName, String phoneNumber,
+                                 int money, int postType, int lostType, String content, MultipartFile file) {
+        ResponseResult<LostFound> responseResult = new ResponseResult<LostFound>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("发布失败");
+
+        String postPhotoDir = request.getSession().getServletContext().getRealPath("/resources/image/post") + File.separator;
+        File bgDirFile = new File(postPhotoDir);
+        if (!bgDirFile.exists()) {
+            bgDirFile.mkdirs();
+        }
+
+        LostFound lostFound = new LostFound();
+        if (file != null) {
+            String fileName = file.getOriginalFilename();
+            //String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
+            try {
+                BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(postPhotoDir + userId + fileName)));
+                //System.out.println(file.getName());
+                out.write(file.getBytes());
+                out.flush();
+                out.close();
+
+                lostFound.setPhotoUrl("/resources/image/post/" + userId + fileName);
+            } catch (Exception e) {
+                responseResult.setMessage("发布失败");
+                e.printStackTrace();
+            }
+        }
+
+        lostFound.setAuthorId(userId);
+        User author = userRepository.findUserByUserId(userId);
+        if (author != null) {
+            lostFound.setAuthorVip(author.getUserType() == User.USER_TYPE_VIP);
+            lostFound.setAuthorHeadUrl(author.getHeadIcon());
+            lostFound.setAuthorName(author.getNickName());
+        }
+        lostFound.setContent(content);
+        lostFound.setPublishTimeMillis(System.currentTimeMillis());
+        lostFound.setCityId(cityId);
+        lostFound.setCityName(cityName);
+        lostFound.setPhoneNumber(phoneNumber);
+        lostFound.setPostType(postType);
+        lostFound.setLostType(lostType);
+        lostFound.setMoney(money);
+
+        lostFoundRepository.save(lostFound);
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("发布成功");
+        responseResult.setResultObj(lostFound);
+        return JSON.toJSONString(responseResult);
+    }
+
+
+
+    // 获取启事,加new PageRequest(page, 10)就是分页
+    @RequestMapping(value = "/api/getPost", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getPost(String userId, String token, int cityId, int postType, int lostType, String keywords, int page) {
+        ResponseResult<List<LostFound>> responseResult = new ResponseResult<List<LostFound>>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("获取失败");
+
+        List<LostFound> lostFoundList = null;
+        if (lostType == LostFound.LOST_TYPE_PUBLISH) {
+            // 我的发布
+            lostFoundList = lostFoundRepository.findPublishedPostByUserId(userId, new PageRequest(page, 10));
+        } else if (lostType == LostFound.LOST_TYPE_FAVORITE) {
+            // 我的收藏
+            List<Integer> favoriteUserIdList = favoriteRepository.findFavoritePostIdListByUserId(userId);
+            if (favoriteUserIdList != null && favoriteUserIdList.size() > 0) {
+                lostFoundList = lostFoundRepository.findFavoritePostByIdList(favoriteUserIdList, new PageRequest(page, 10));
+            }
+        } else {
+            // 属于失物招领两大Tab的
+            if (lostType == LostFound.LOST_TYPE_MONEY) {
+                // 悬赏类
+                if (TextUtils.isEmpty(keywords)) {
+                    if (cityId == 0) {
+                        // 所有悬赏,无关键字
+                        lostFoundList = lostFoundRepository.findMoneyPost(LostFound.POST_TYPE_LOST, new PageRequest(page, 10));
+                    } else {
+                        // 某个城市的悬赏,无关键字
+                        lostFoundList = lostFoundRepository.findMoneyPost(LostFound.POST_TYPE_LOST, cityId, new PageRequest(page, 10));
+                    }
+                } else {
+                    if (cityId == 0) {
+                        // 所有悬赏,有关键字
+                        lostFoundList = lostFoundRepository.findMoneyPost(LostFound.POST_TYPE_LOST, keywords, new PageRequest(page, 10));
+                    } else {
+                        // 某个城市的悬赏,有关键字
+                        lostFoundList = lostFoundRepository.findMoneyPost(LostFound.POST_TYPE_LOST, cityId, keywords, new PageRequest(page, 10));
+                    }
+                }
+
+            } else {
+                int queryTpe = getQueryType(cityId, postType, lostType, keywords);
+                switch (queryTpe) {
+                    case 1:
+                        lostFoundList = lostFoundRepository.findPostByPostType(postType, new PageRequest(page, 10));
+                        break;
+                    case 2:
+                        lostFoundList = lostFoundRepository.findPostByPostTypeKeywords(postType, keywords, new PageRequest(page, 10));
+                        break;
+                    case 3:
+                        lostFoundList = lostFoundRepository.findPostByLostType(postType, lostType, new PageRequest(page, 10));
+                        break;
+                    case 4:
+                        lostFoundList = lostFoundRepository.findPostByLostTypeKeywords(postType, lostType, keywords, new PageRequest(page, 10));
+                        break;
+                    case 5:
+                        lostFoundList = lostFoundRepository.findPostByPostTypeCityId(postType, cityId, new PageRequest(page, 10));
+                        break;
+                    case 6:
+                        lostFoundList = lostFoundRepository.findPostByPostTypeCityIdKeywords(postType, cityId, keywords, new PageRequest(page, 10));
+                        break;
+                    case 7:
+                        lostFoundList = lostFoundRepository.findPostByPostTypeLostTypeCityId(postType, lostType, cityId, new PageRequest(page, 10));
+                        break;
+                    case 8:
+                        lostFoundList = lostFoundRepository.findPostByPostTypeLostTypeCityIdKeywords(postType, lostType, cityId, keywords, new PageRequest(page, 10));
+                        break;
+                }
+            }
+        }
+
+        if (lostFoundList != null) {
+            for (LostFound lostFound : lostFoundList) {
+                User author = userRepository.findUserByUserId(lostFound.getAuthorId());
+                // 帖子发布者是否为VIP
+                lostFound.setAuthorName(author.getNickName());
+                lostFound.setAuthorVip(author.getUserType() == User.USER_TYPE_VIP);
+                lostFound.setAuthorHeadUrl(author.getHeadIcon());
+            }
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("获取成功");
+        responseResult.setResultObj(lostFoundList);
+        return JSON.toJSONString(responseResult);
+    }
+
+    // 查询的是什么数据
+    private int getQueryType(int cityId, int postType, int lostType, String keywords) {
+        if (cityId == 0) {
+            if (lostType == 0) {
+                if (TextUtils.isEmpty(keywords)) {
+                    return 1;
+                } else {
+                    return 2;
+                }
+            } else {
+                if (TextUtils.isEmpty(keywords)) {
+                    return 3;
+                } else {
+                    return 4;
+                }
+            }
+        } else {
+            if (lostType == 0) {
+                if (TextUtils.isEmpty(keywords)) {
+                    return 5;
+                } else {
+                    return 6;
+                }
+            } else {
+                if (TextUtils.isEmpty(keywords)) {
+                    return 7;
+                } else {
+                    return 8;
+                }
+            }
+        }
+    }
+
+    // 查看本帖子是否被当前用户收藏,顺便浏览次数+1
+    @RequestMapping(value = "/api/isFavorite", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String getIsFavorite(String userId, String token, int postId) {
+        ResponseResult<FavoriteResult> responseResult = new ResponseResult<FavoriteResult>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("查询失败");
+
+        FavoriteResult result = new FavoriteResult();
+        Favorite favorite = favoriteRepository.findFavorite(userId, postId);
+        if (favorite != null) {
+            result.setFavorite(true);
+        } else {
+            result.setFavorite(false);
+        }
+
+        LostFound lostFound = lostFoundRepository.findPostByPostId(postId);
+        if (lostFound != null) {
+            Integer lastNum = lostFound.getBrowseNum();
+            if (lastNum == null) {
+                lastNum = 0;
+            }
+            int browseNum = lastNum+1;
+            if (browseNum > MAX_BROWSE_NUM) {
+                browseNum = MAX_BROWSE_NUM;
+            }
+            result.setBrowseNum(browseNum);
+            lostFound.setBrowseNum(browseNum);
+        } else {
+            responseResult.setMessage("启事已被删除");
+            responseResult.setResultObj(result);
+            return JSON.toJSONString(responseResult);
+        }
+        lostFoundRepository.save(lostFound);
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("查询成功");
+        responseResult.setResultObj(result);
+        return JSON.toJSONString(responseResult);
+    }
+
+    // 收藏或取消收藏
+    @RequestMapping(value = "/api/goFavorite", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String goFavorite(String userId, String token, int postId) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("操作失败");
+
+
+        Favorite favorite = favoriteRepository.findFavorite(userId, postId);
+        if (favorite != null) {
+            // 取消收藏
+            favoriteRepository.delete(favorite);
+            responseResult.setMessage("取消收藏成功");
+        } else {
+            // 收藏
+            Favorite addFavorite = new Favorite();
+            addFavorite.setUserId(userId);
+            addFavorite.setPostId(postId);
+            addFavorite.setTime(System.currentTimeMillis());
+            favoriteRepository.save(addFavorite);
+            responseResult.setMessage("收藏成功");
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        return JSON.toJSONString(responseResult);
+    }
+
+
+    @RequestMapping(value = "/api/delPost", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String goFavorite(String userId, String token, int postId, String authorId) {
+        ResponseResult<String> responseResult = new ResponseResult<String>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("操作失败");
+
+        boolean hasPermission = false;
+        if (TextUtils.equals(userId, authorId)) {
+            hasPermission = true;
+        } else {
+            if (TextUtils.equals(userId, "[email protected]")) {
+                hasPermission = true;
+            }
+        }
+
+        if (hasPermission) {
+            LostFound lostFound = lostFoundRepository.findPostByPostId(postId);
+            if (lostFound != null) {
+                lostFoundRepository.delete(lostFound);
+                responseResult.setResultCode(ResultCode.SUCCESS);
+            }
+        }
+
+        return JSON.toJSONString(responseResult);
+    }
+}

+ 95 - 0
src/main/java/com/itant/laf/controller/api/SystemController.java

@@ -0,0 +1,95 @@
+package com.itant.laf.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.itant.laf.bean.Feedback;
+import com.itant.laf.bean.Message;
+import com.itant.laf.bean.ResponseResult;
+import com.itant.laf.bean.ResultCode;
+import com.itant.laf.repository.FeedbackRepository;
+import com.itant.laf.repository.MessageRepository;
+import com.itant.laf.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
+    MessageRepository messageRepository;
+
+    /**
+     * 意见反馈
+     */
+    @RequestMapping(value = "/api/feedback", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String dealFeedback(String userId, String email, 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\\laf\\upgrade\\laf.apk
+        // 获取的时候,就是访问这个URL:http://www.xxx.com/api/upgrade
+        // 需要正式发布才起作用
+        String webPath = request.getSession().getServletContext().getRealPath("upgrade") + File.separator + "laf.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/systemMessage", method = RequestMethod.GET)
+    public String index(HttpServletRequest request) {
+        Message message = messageRepository.findMessage();
+        if (message != null) {
+            request.setAttribute("message", message.getMessageContent());
+            request.setAttribute("bean", message);
+        }
+        return "msg/message";
+    }
+}

+ 360 - 0
src/main/java/com/itant/laf/controller/api/UserController.java

@@ -0,0 +1,360 @@
+package com.itant.laf.controller.api;
+
+import com.alibaba.fastjson.JSON;
+import com.itant.laf.bean.Feedback;
+import com.itant.laf.bean.ResponseResult;
+import com.itant.laf.bean.ResultCode;
+import com.itant.laf.bean.User;
+import com.itant.laf.repository.UserRepository;
+import com.itant.laf.tool.CodeGenerator;
+import com.itant.laf.tool.TextUtils;
+import com.itant.laf.tool.TokenGenerator;
+import com.itant.laf.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.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);
+                }
+            }
+        }
+    }
+
+    /**
+     * 注册
+     */
+    @RequestMapping(value = "/api/register", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String register(String nickName, String email, String password) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("注册失败");
+
+        // 从数据库查询,如果没有这个email并且不在黑名单里,才可以继续注册
+        User dbUser = userRepository.findUserByUserId(email);
+        if (dbUser != null) {
+            responseResult.setResultCode(ResultCode.FAILED_USER_ALREADY_EXIST);
+            responseResult.setMessage("该邮箱已被使用");
+            return JSON.toJSONString(responseResult);
+        }
+
+        // 开始注册,插入数据库
+        User user = new User();
+        user.setUserId(email);
+        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);
+    }
+
+    /**
+     * 邮箱登录
+     */
+    @RequestMapping(value = "/api/login", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String login(String userId, String password) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("登录失败");
+
+        // 从数据库查询,如果有这个用户,说明以前用QQ登录过
+        User dbUser = userRepository.findUserByUserId(userId);
+        if (dbUser == null) {
+            // 用户不存在
+            responseResult.setMessage("用户不存在");
+            return JSON.toJSONString(responseResult);
+        } else {
+            if (!TextUtils.equals(password, dbUser.getPassword())) {
+                // 密码错误
+                responseResult.setMessage("密码错误");
+                return JSON.toJSONString(responseResult);
+            }
+
+            //dbUser.setNickName(nickName);
+            String token = TokenGenerator.getInstance().getToken(userId);
+            dbUser.setToken(token);
+            userRepository.save(dbUser);
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("登录成功");
+        responseResult.setResultObj(dbUser);
+
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * QQ登录
+     */
+    @RequestMapping(value = "/api/qqLogin", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String qqLogin(String userId, String token, String nickName, String headIcon) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("登录失败");
+
+        // 从数据库查询,如果有这个用户,说明以前用QQ登录过
+        User dbUser = userRepository.findUserByUserId(userId);
+        if (dbUser == null) {
+            // 开始注册,插入数据库
+            dbUser = new User();
+            dbUser.setUserId(userId);
+            dbUser.setToken(token);
+            dbUser.setNickName(nickName);
+            dbUser.setHeadIcon(headIcon);
+            dbUser.setRegisterTimeMillis(System.currentTimeMillis());
+            userRepository.save(dbUser);
+        } else {
+            dbUser.setToken(token);
+            //dbUser.setNickName(nickName);
+            dbUser.setHeadIcon(headIcon);
+            userRepository.save(dbUser);
+        }
+
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("登录成功");
+        responseResult.setResultObj(dbUser);
+
+        return JSON.toJSONString(responseResult);
+    }
+
+    /**
+     * 重置密码之前要先获取验证码
+     */
+    @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();
+
+        // 从数据库查询看该用户是否存在
+        User dbUser = userRepository.findUserByUserId(email);
+        if (dbUser == null) {
+            // 用户不存在
+            responseResult.setMessage("用户不存在");
+            return JSON.toJSONString(responseResult);
+        }
+
+        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("获取验证码成功");
+        } else {
+            responseResult.setResultCode(ResultCode.FAILED_COMMON);
+            responseResult.setMessage("获取验证码失败");
+        }
+        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.findUserByUserId(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);
+    }
+
+    /**
+     * 成为VIP
+     */
+    @RequestMapping(value = "/api/becomeVip", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String becomeVip(String userId, String token) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("成为VIP失败");
+
+        User dbUser = userRepository.findUserByUserId(userId);
+        dbUser.setUserType(User.USER_TYPE_VIP);
+
+        try {
+            userRepository.save(dbUser);
+            responseResult.setResultCode(ResultCode.SUCCESS);
+            responseResult.setResultObj(dbUser);
+            responseResult.setMessage("成为VIP成功");
+        } catch (Exception e) {
+            responseResult.setMessage("成为VIP失败");
+            e.printStackTrace();
+        }
+        return JSON.toJSONString(responseResult);
+    }
+
+
+    // 假设发布的war包为laf.war,那么我们配置了<mvc:resources mapping="/resources/**" location="/resources/" />,说明
+    // D:\software\apache-tomcat-7.0.90\webapps\laf\resources下的文件夹和文件都可以直接通过URL直接访问,注意要打成war包后才起作用
+    // 最终得到的图片链接为http://localhost:8080/laf/resources/head/用户的userId+suffix
+    // eg:http://localhost:8080/laf/resources/head/6C714C894FFB6207C9691CD0E826399A.jpg
+    // 正式发布时,要更改为正式域名
+    @RequestMapping(value = "/api/updateUserData", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
+    @ResponseBody
+    public String updateUserData(String userId, String token, String nickname, String saying, MultipartFile file, String suffix) {
+        ResponseResult<User> responseResult = new ResponseResult<User>();
+        responseResult.setResultCode(ResultCode.FAILED_COMMON);
+        responseResult.setMessage("更新资料失败");
+
+        String headDir = request.getSession().getServletContext().getRealPath("/resources/image/head") + File.separator;
+        File bgDirFile = new File(headDir);
+        if (!bgDirFile.exists()) {
+            bgDirFile.mkdirs();
+        }
+
+        User dbUser = userRepository.findUserByUserId(userId);
+        if (file != null) {
+            //String fileName = file.getOriginalFilename();
+            //String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
+            try {
+                BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(headDir + userId + suffix)));
+                //System.out.println(file.getName());
+                out.write(file.getBytes());
+                out.flush();
+                out.close();
+
+                dbUser.setHeadIcon("/resources/image/head/" + userId + suffix);
+            } catch (Exception e) {
+                responseResult.setMessage("更新资料失败");
+                e.printStackTrace();
+            }
+        }
+
+        dbUser.setNickName(nickname);
+        dbUser.setSaying(saying);
+        userRepository.save(dbUser);
+        responseResult.setResultCode(ResultCode.SUCCESS);
+        responseResult.setMessage("更新资料成功");
+        responseResult.setResultObj(dbUser);
+        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";
+        File file = new File(bgPath);
+        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;
+    }
+}

+ 18 - 0
src/main/java/com/itant/laf/controller/web/LAFMainController.java

@@ -0,0 +1,18 @@
+package com.itant.laf.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 LAFMainController {
+
+    // 首页(会和文件上传的mapping冲突)
+    @RequestMapping(value = "/", method = RequestMethod.GET)
+    public String index() {
+        return "index";
+    }
+}

+ 43 - 0
src/main/java/com/itant/laf/interceptor/AuthInterceptor.java

@@ -0,0 +1,43 @@
+package com.itant.laf.interceptor;
+
+import com.alibaba.fastjson.JSON;
+import com.itant.laf.bean.ResponseResult;
+import com.itant.laf.bean.ResultCode;
+import com.itant.laf.bean.User;
+import com.itant.laf.repository.UserRepository;
+import com.itant.laf.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 userId = request.getParameter("userId");
+        String token = request.getParameter("token");
+        User user = userRepository.findUserByUserId(userId);
+        if (user == null || user.getUserType() == User.USER_TYPE_INVALID || !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/itant/laf/model/BlogEntity.java

@@ -0,0 +1,77 @@
+package com.itant.laf.model;
+
+import javax.persistence.*;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+@Entity
+@Table(name = "blog", schema = "laf", 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/itant/laf/model/UserEntity.java

@@ -0,0 +1,91 @@
+package com.itant.laf.model;
+
+import javax.persistence.*;
+import java.util.Collection;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+@Entity
+@Table(name = "spring_mvc_user", schema = "laf", 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;
+    }
+}

+ 30 - 0
src/main/java/com/itant/laf/repository/FavoriteRepository.java

@@ -0,0 +1,30 @@
+package com.itant.laf.repository;
+
+import com.itant.laf.bean.Favorite;
+import com.itant.laf.bean.Feedback;
+import com.itant.laf.bean.LostFound;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface FavoriteRepository extends JpaRepository<Favorite, Integer> {
+    // 根据用户id和帖子id查找收藏记录
+    @Transactional
+    @Query(value="select favorite from Favorite favorite where favorite.userId=:userId and favorite.postId=:postId")
+    public Favorite findFavorite(@Param("userId") String userId, @Param("postId") int postId);
+
+    // 根据用户id找出该用户收藏的所有帖子id
+    @Transactional
+    @Query(value="select favorite.postId from Favorite favorite where favorite.userId=:userId")
+    public List<Integer> findFavoritePostIdListByUserId(@Param("userId") String userId);
+}

+ 14 - 0
src/main/java/com/itant/laf/repository/FeedbackRepository.java

@@ -0,0 +1,14 @@
+package com.itant.laf.repository;
+
+import com.itant.laf.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> {
+
+}

+ 138 - 0
src/main/java/com/itant/laf/repository/LostFoundRepository.java

@@ -0,0 +1,138 @@
+package com.itant.laf.repository;
+
+import com.itant.laf.bean.LostFound;
+import com.itant.laf.bean.User;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface LostFoundRepository extends JpaRepository<LostFound, String> {
+    /*@Query(nativeQuery=true,value = "") value里写正常sql语句
+    如果返回的是数据库对应的实体对象,那么sql的返回结果集字段别名中应该与该实体类中对应的数据库字段名一致,可以有多余字段,但不能少字段*/
+
+    /*// 说明该方法是修改操作
+    @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
+    // 根据用户id查找帖子
+    // @Param注解用于提取参数
+    @Query(value="select post from LostFound post where post.lostFoundId=:lostFoundId")
+    public LostFound findPostByPostId(@Param("lostFoundId") int lostFoundId);
+
+    // 根据用户id找出该用户发布的所有帖子
+    @Transactional
+    @Query(value="select post from LostFound post where post.authorId=:userId order by post.publishTimeMillis desc")
+    public List<LostFound> findPublishedPostByUserId(@Param("userId") String userId, Pageable pageable);
+
+    // 根据帖子id找出帖子(我的收藏)
+    @Query("select post from LostFound post where post.lostFoundId in :ids order by post.publishTimeMillis desc")
+    public List<LostFound> findFavoritePostByIdList(@Param(value = "ids") List<Integer> ids, Pageable pageable);
+
+    // ①所有城市-所有Tab-没关键字------------降序、分页
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType order by post.publishTimeMillis desc")
+    public List<LostFound> findPostByPostType(@Param("postType") int postType, Pageable pageable);
+
+    // ②所有城市-所有Tab-有关键字------------
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.content like CONCAT('%',:keywords,'%') order by post.publishTimeMillis desc")
+    public List<LostFound> findPostByPostTypeKeywords(@Param("postType") int postType, @Param("keywords") String keywords, Pageable pageable);
+
+
+    // ③所有城市-某个Tab-无关键字
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.lostType=:lostType order by post.publishTimeMillis desc")
+    public List<LostFound> findPostByLostType(@Param("postType") int postType, @Param("lostType") int lostType, Pageable pageable);
+
+    // ④所有城市-某个Tab-有关键字
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.lostType=:lostType and post.content like CONCAT('%',:keywords,'%') order by post.publishTimeMillis desc")
+    public List<LostFound> findPostByLostTypeKeywords(@Param("postType") int postType, @Param("lostType") int lostType, @Param("keywords") String keywords, Pageable pageable);
+
+    // ⑤某个城市-所有Tab-无关键字-----------
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.cityId=:cityId order by post.publishTimeMillis desc")
+    public List<LostFound> findPostByPostTypeCityId(@Param("postType") int postType, @Param("cityId") int cityId, Pageable pageable);
+
+    // ⑥某个城市-所有Tab-有关键字-----------
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.cityId=:cityId and post.content like CONCAT('%',:keywords,'%') order by post.publishTimeMillis desc")
+    public List<LostFound> findPostByPostTypeCityIdKeywords(@Param("postType") int postType, @Param("cityId") int cityId, @Param("keywords") String keywords, Pageable pageable);
+
+
+    // ⑦某个城市-某个Tab-无关键字
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.cityId=:cityId and post.lostType=:lostType order by post.publishTimeMillis desc")
+    public List<LostFound> findPostByPostTypeLostTypeCityId(@Param("postType") int postType, @Param("lostType") int lostType, @Param("cityId") int cityId, Pageable pageable);
+
+    // ⑧某个城市-某个Tab-有关键字
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.cityId=:cityId and post.lostType=:lostType and post.content like CONCAT('%',:keywords,'%') order by post.publishTimeMillis desc")
+    public List<LostFound> findPostByPostTypeLostTypeCityIdKeywords(@Param("postType") int postType, @Param("lostType") int lostType, @Param("cityId") int cityId, @Param("keywords") String keywords, Pageable pageable);
+
+
+    // 注意:@Param标签为必需,否则会查询出错
+    // 查找所有悬赏
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.money > 0 order by post.publishTimeMillis desc")
+    public List<LostFound> findMoneyPost(@Param("postType") int postType, Pageable pageable);
+
+    // 查某个城市的悬赏,没有关键字
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.money > 0 and post.cityId=:cityId order by post.publishTimeMillis desc")
+    public List<LostFound> findMoneyPost(@Param("postType") int postType, @Param("cityId") int cityId, Pageable pageable);
+
+    // 查某所有悬赏,有关键字
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.money > 0 and post.content like CONCAT('%',:keywords,'%') order by post.publishTimeMillis desc")
+    public List<LostFound> findMoneyPost(@Param("postType") int postType, @Param("keywords") String keywords, Pageable pageable);
+
+    // 查找某个城市的悬赏,有关键字
+    @Transactional
+    @Query(value="select post from LostFound post where post.postType=:postType and post.money > 0 and post.cityId=:cityId and post.content like CONCAT('%',:keywords,'%') order by post.publishTimeMillis desc")
+    public List<LostFound> findMoneyPost(@Param("postType") int postType, @Param("cityId") int cityId, @Param("keywords") String keywords, Pageable pageable);
+
+
+
+
+    /*// 说明该方法是修改操作
+    @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);*/
+
+    /*@Modifying
+    @Transactional
+    @Query("update User us set us.token=:token where us.userId=:userId")
+    public void updateUserToken(@Param("userId") String userId, @Param("token") String token);*/
+
+    //根据不同id,一次查询多条数据
+    /*@Query("update ShopCoupon sc set sc.deleted = true where sc.id in :ids")
+    public void deleteByIds(@Param(value = "ids") List<String> ids);*/
+
+
+}

+ 55 - 0
src/main/java/com/itant/laf/repository/MessageRepository.java

@@ -0,0 +1,55 @@
+package com.itant.laf.repository;
+
+import com.itant.laf.bean.Message;
+import com.itant.laf.bean.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Created by sjj on 2015/10/24 0024.
+ */
+// 添加注解
+@Repository
+public interface MessageRepository extends JpaRepository<Message, 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
+    // 根据用户id查找用户
+    // @Param注解用于提取参数
+    @Query(value="select message from Message message")
+    public Message findMessage();
+
+    /*// 说明该方法是修改操作
+    @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);*/
+
+    /*@Modifying
+    @Transactional
+    @Query("update User us set us.token=:token where us.userId=:userId")
+    public void updateUserToken(@Param("userId") String userId, @Param("token") String token);*/
+
+    //根据不同id,一次查询多条数据
+    /*@Query("update ShopCoupon sc set sc.deleted = true where sc.id in :ids")
+    public void deleteByIds(@Param(value = "ids") List<String> ids);*/
+
+
+}

+ 56 - 0
src/main/java/com/itant/laf/repository/UserRepository.java

@@ -0,0 +1,56 @@
+package com.itant.laf.repository;
+
+import com.itant.laf.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
+    // 根据用户id查找用户
+    // @Param注解用于提取参数
+    @Query(value="select user from User user where user.userId=:userId")
+    public User findUserByUserId(@Param("userId") String userId);
+
+    /*// 说明该方法是修改操作
+    @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);*/
+
+    /*@Modifying
+    @Transactional
+    @Query("update User us set us.token=:token where us.userId=:userId")
+    public void updateUserToken(@Param("userId") String userId, @Param("token") String token);*/
+
+    //根据不同id,一次查询多条数据
+    /*@Query("update ShopCoupon sc set sc.deleted = true where sc.id in :ids")
+    public void deleteByIds(@Param(value = "ids") List<String> ids);*/
+
+
+}

+ 33 - 0
src/main/java/com/itant/laf/tool/CodeGenerator.java

@@ -0,0 +1,33 @@
+package com.itant.laf.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/itant/laf/tool/TextUtils.java

@@ -0,0 +1,24 @@
+package com.itant.laf.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/itant/laf/tool/TokenGenerator.java

@@ -0,0 +1,37 @@
+package com.itant.laf.tool;
+
+import com.itant.laf.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/itant/laf/tool/email/EmailAuthenticator.java

@@ -0,0 +1,17 @@
+package com.itant.laf.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);
+    }
+}
+

+ 71 - 0
src/main/java/com/itant/laf/tool/email/EmailTool.java

@@ -0,0 +1,71 @@
+package com.itant.laf.tool.email;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.util.Properties;
+
+import javax.mail.Authenticator;
+import javax.mail.BodyPart;
+import javax.mail.Message;
+import javax.mail.Multipart;
+import javax.mail.Transport;
+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;
+
+    /**
+     * 发邮件
+     * @throws Exception
+     */
+    public int sendEmail(String subject, String content, String toEmailAddress) {
+        // 副标题
+        //String subject = "验证码";
+        Properties properties = new Properties();
+        properties.put("mail.smtp.host", "smtp.163.com");
+        properties.put("mail.smtp.port", "25");
+        properties.put("mail.smtp.auth", "true");
+        Authenticator authenticator = new EmailAuthenticator("[email protected]", "away6899458");
+        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;
+    }
+}

+ 109 - 0
src/main/java/com/itant/laf/tool/secure/SecureManager.java

@@ -0,0 +1,109 @@
+package com.itant.laf.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是wuji,如下:-->
+            <property name="hibernate.connection.url"
+                      value="jdbc:mysql://localhost:3306/laf"/>
+            <!-- 数据库连接的驱动 -->
+            <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;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 93 - 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>

+ 587 - 0
src/main/webapp/css/bootstrap-theme.css

@@ -0,0 +1,587 @@
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+}
+.btn-default:active,
+.btn-primary:active,
+.btn-success:active,
+.btn-info:active,
+.btn-warning:active,
+.btn-danger:active,
+.btn-default.active,
+.btn-primary.active,
+.btn-success.active,
+.btn-info.active,
+.btn-warning.active,
+.btn-danger.active {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-default.disabled,
+.btn-primary.disabled,
+.btn-success.disabled,
+.btn-info.disabled,
+.btn-warning.disabled,
+.btn-danger.disabled,
+.btn-default[disabled],
+.btn-primary[disabled],
+.btn-success[disabled],
+.btn-info[disabled],
+.btn-warning[disabled],
+.btn-danger[disabled],
+fieldset[disabled] .btn-default,
+fieldset[disabled] .btn-primary,
+fieldset[disabled] .btn-success,
+fieldset[disabled] .btn-info,
+fieldset[disabled] .btn-warning,
+fieldset[disabled] .btn-danger {
+  -webkit-box-shadow: none;
+          box-shadow: none;
+}
+.btn-default .badge,
+.btn-primary .badge,
+.btn-success .badge,
+.btn-info .badge,
+.btn-warning .badge,
+.btn-danger .badge {
+  text-shadow: none;
+}
+.btn:active,
+.btn.active {
+  background-image: none;
+}
+.btn-default {
+  text-shadow: 0 1px 0 #fff;
+  background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image:      -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
+  background-image:         linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #dbdbdb;
+  border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus {
+  background-color: #e0e0e0;
+  background-position: 0 -15px;
+}
+.btn-default:active,
+.btn-default.active {
+  background-color: #e0e0e0;
+  border-color: #dbdbdb;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+  background-color: #e0e0e0;
+  background-image: none;
+}
+.btn-primary {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #245580;
+}
+.btn-primary:hover,
+.btn-primary:focus {
+  background-color: #265a88;
+  background-position: 0 -15px;
+}
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #265a88;
+  border-color: #245580;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+  background-color: #265a88;
+  background-image: none;
+}
+.btn-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image:      -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
+  background-image:         linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #3e8f3e;
+}
+.btn-success:hover,
+.btn-success:focus {
+  background-color: #419641;
+  background-position: 0 -15px;
+}
+.btn-success:active,
+.btn-success.active {
+  background-color: #419641;
+  border-color: #3e8f3e;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+  background-color: #419641;
+  background-image: none;
+}
+.btn-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image:      -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
+  background-image:         linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #28a4c9;
+}
+.btn-info:hover,
+.btn-info:focus {
+  background-color: #2aabd2;
+  background-position: 0 -15px;
+}
+.btn-info:active,
+.btn-info.active {
+  background-color: #2aabd2;
+  border-color: #28a4c9;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+  background-color: #2aabd2;
+  background-image: none;
+}
+.btn-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
+  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #e38d13;
+}
+.btn-warning:hover,
+.btn-warning:focus {
+  background-color: #eb9316;
+  background-position: 0 -15px;
+}
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #eb9316;
+  border-color: #e38d13;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #eb9316;
+  background-image: none;
+}
+.btn-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image:      -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
+  background-image:         linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-color: #b92c28;
+}
+.btn-danger:hover,
+.btn-danger:focus {
+  background-color: #c12e2a;
+  background-position: 0 -15px;
+}
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #c12e2a;
+  border-color: #b92c28;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #c12e2a;
+  background-image: none;
+}
+.thumbnail,
+.img-thumbnail {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  background-color: #e8e8e8;
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  background-color: #2e6da4;
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+  background-repeat: repeat-x;
+}
+.navbar-default {
+  background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image:      -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
+  background-image:         linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+  background-image:      -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
+  background-image:         linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+}
+.navbar-brand,
+.navbar-nav > li > a {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
+}
+.navbar-inverse {
+  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image:      -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
+  background-image:         linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+  background-image:      -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
+  background-image:         linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+          box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+}
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-nav > li > a {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
+}
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  border-radius: 0;
+}
+@media (max-width: 767px) {
+  .navbar .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #fff;
+    background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+    background-image:      -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+    background-image:         linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+    background-repeat: repeat-x;
+  }
+}
+.alert {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+}
+.alert-success {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image:      -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
+  background-image:         linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #b2dba1;
+}
+.alert-info {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image:      -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
+  background-image:         linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #9acfea;
+}
+.alert-warning {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
+  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #f5e79e;
+}
+.alert-danger {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image:      -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
+  background-image:         linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dca7a7;
+}
+.progress {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image:      -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
+  background-image:         linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #286090 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #286090 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image:      -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
+  background-image:         linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image:      -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
+  background-image:         linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image:      -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
+  background-image:         linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image:      -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
+  background-image:         linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
+  background-repeat: repeat-x;
+}
+.progress-bar-striped {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:      -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image:         linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.list-group {
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  text-shadow: 0 -1px 0 #286090;
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #2b669a;
+}
+.list-group-item.active .badge,
+.list-group-item.active:hover .badge,
+.list-group-item.active:focus .badge {
+  text-shadow: none;
+}
+.panel {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+}
+.panel-default > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image:      -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image:         linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-primary > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image:      -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+  background-image:         linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-success > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image:      -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
+  background-image:         linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-info > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image:      -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
+  background-image:         linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-warning > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image:      -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
+  background-image:         linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
+  background-repeat: repeat-x;
+}
+.panel-danger > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image:      -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
+  background-image:         linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
+  background-repeat: repeat-x;
+}
+.well {
+  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image:      -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
+  background-image:         linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dcdcdc;
+  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+          box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+}
+/*# sourceMappingURL=bootstrap-theme.css.map */

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 0
src/main/webapp/css/bootstrap-theme.css.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 5 - 0
src/main/webapp/css/bootstrap-theme.min.css


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 6837 - 0
src/main/webapp/css/bootstrap.css


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 0
src/main/webapp/css/bootstrap.css.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 5 - 0
src/main/webapp/css/bootstrap.min.css


BIN
src/main/webapp/fonts/glyphicons-halflings-regular.eot


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 288 - 0
src/main/webapp/fonts/glyphicons-halflings-regular.svg


BIN
src/main/webapp/fonts/glyphicons-halflings-regular.ttf


BIN
src/main/webapp/fonts/glyphicons-halflings-regular.woff


BIN
src/main/webapp/fonts/glyphicons-halflings-regular.woff2


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

+ 81 - 0
src/main/webapp/html/msg/message.jsp

@@ -0,0 +1,81 @@
+<%--
+  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标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
+    <meta name="description" content="失物招领">
+    <meta name="author" content="itant">
+    <meta name="keywords" content="失物招领">
+    <title>失物树</title>
+
+    <!-- Bootstrap 调试的时候-->
+    <%--<link href="/css/bootstrap.css" rel="stylesheet">
+    <script src="/js/jquery-3.1.0.min.js"></script>
+    <script src="/js/bootstrap.js"></script>--%>
+
+    <!-- 要添加上下文路径,否则正式发布会访问失败-->
+    <link href="${pageContext.request.contextPath}/css/bootstrap.css" rel="stylesheet">
+    <script src="${pageContext.request.contextPath}/js/jquery-3.1.0.min.js"></script>
+    <script src="${pageContext.request.contextPath}/js/bootstrap.js"></script>
+</head>
+<body class="container">
+
+<!-- 导航栏 -->
+<%--<nav class="navbar navbar-default navbar-fixed-top">
+  <div class="container">
+    <div class="navbar-header">
+      <a class="navbar-brand" href="#">千雪崖</a>
+    </div>
+    <ul class="nav navbar-nav">
+      <li class="active"><a href="#">商店</a></li>
+      <li><a href="software.html">软件</a></li>
+      <li><a href="website.html">网址</a></li>
+
+    </ul>
+  </div>
+</nav>--%>
+
+<div class="panel panel-success navbar-fixed-top">
+    <div class="panel-heading">
+        失物树
+    </div>
+    <div class="panel-body">
+        欢迎光临本失物招领平台<br/>
+        ${message}
+        <%--<a href="http://www.baidu.com" target="_blank">
+            <button type="button" class="btn btn-success">直接购买</button>
+        </a>--%>
+    </div>
+
+    <%--<table class="table">
+        <tr>
+            <th>#</th>
+            <th>用户</th>
+            <th>角色</th>
+        </tr>
+
+        <tr>
+            <th scope="row">1</th>
+            <td>itmonkey</td>
+            <td>管理员</td>
+        </tr>
+    </table>--%>
+</div>
+
+<nav class="navbar navbar-default  navbar-fixed-bottom" role="navigation">
+    <div class="container text-center" id="qian-foot">
+        <p class="navbar-text col-md-12 col-sm-12 col-xs-12">&copy; 反馈邮箱[email protected]</p>
+    </div>
+</nav>
+</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>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 2363 - 0
src/main/webapp/js/bootstrap.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 7 - 0
src/main/webapp/js/bootstrap.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 4 - 0
src/main/webapp/js/jquery-3.1.0.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 6 - 0
src/main/webapp/js/jquery.min.js


+ 13 - 0
src/main/webapp/js/npm.js

@@ -0,0 +1,13 @@
+// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
+require('../../js/transition.js')
+require('../../js/alert.js')
+require('../../js/button.js')
+require('../../js/carousel.js')
+require('../../js/collapse.js')
+require('../../js/dropdown.js')
+require('../../js/modal.js')
+require('../../js/tooltip.js')
+require('../../js/popover.js')
+require('../../js/scrollspy.js')
+require('../../js/tab.js')
+require('../../js/affix.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,那么还要在我们这个项目做相应的改动。