前言


这两年springboot比较火,而我平时的工作中不怎么使用spring boot,所以工作之余就自己写写项目练练手,也跟大家一起学习。

打算从最开始的搭架子,登录注册,到后台管理的增删改查,业务逻辑,引用权限框架,如果能一直坚持下去就再增加缓存,中间件,消息队列,数据库方面分库分表,负载均衡这些比较主流的东西都玩一遍。

页面基本上都是在网上找的免费模板,也会借鉴一下其他的博客,如果引用较多会挂上原文链接。

spring boot


这里引用一篇阿里云的文章,有兴趣的朋友可以去看一看,是spring boot的介绍和使用。

https://yq.aliyun.com/articles/495578

正文


创建项目,用的JDK版本是1.8,

项目结构

js css这些资源要放在static包下,我放别的地方引用不进去,后文再说。

页面位置

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org</groupId>
<artifactId>mall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mall</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency> <!-- spring boot mybatis依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency> <!-- mysql连接驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
<!-- <version>${mysql-connector}</version>-->
</dependency> <!-- spring boot freemarker依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency> <!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency> <!-- swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.5.0</version>
</dependency> <!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> <!-- 热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency> <!-- maven方式是使用mybatis-generator-->
<!-- mybatis自动生成工具-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency> </dependencies> <build>
<plugins> <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<!-- spring-boot:run 中文乱码解决 -->
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
</configuration>
</plugin> <!-- mybatis generator 自动生成代码插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>
src/main/resources/generator/generatorConfig.xml
</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin> </plugins>
</build> </project>

application.properties

换上自己的配置

## 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/independenttest?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
## 数据库账号密码
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
##spring.datasource.driver-class-name=com.mysql.jdbc.Driver ## 实体类
mybatis.typeAliasesPackage=com.wjy.entity
## mapper.xml
mybatis.mapperLocations=classpath:mapper/*.xml ## Freemarker 配置
## 文件配置路径
spring.freemarker.template-loader-path=classpath:/web/
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
## 获取contextPath
spring.freemarker.request-context-attribute=request
spring.freemarker.suffix=.ftl

 mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.wjy.mapper.TUserMapper" >
<resultMap id="BaseResultMap" type="com.wjy.entity.TUser" >
<id column="id" property="id" jdbcType="BIGINT" />
<result column="username" property="username" jdbcType="VARCHAR" />
<result column="userpassword" property="userpassword" jdbcType="VARCHAR" />
<result column="usertel" property="usertel" jdbcType="VARCHAR" />
<result column="login_error_num" property="loginErrorNum" jdbcType="BIT" />
<result column="lock_time" property="lockTime" jdbcType="INTEGER" />
<result column="status" property="status" jdbcType="BIT" />
<result column="real_name" property="realName" jdbcType="VARCHAR" />
<result column="id_card" property="idCard" jdbcType="VARCHAR" />
<result column="userpassword_salt" property="userpasswordSalt" jdbcType="VARCHAR" />
<result column="remark" property="remark" jdbcType="VARCHAR" />
</resultMap>
<sql id="Base_Column_List" >
id, username, userpassword, usertel, login_error_num, lock_time, status, real_name,
id_card, userpassword_salt, remark
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" >
select
<include refid="Base_Column_List" />
from t_user
where id = #{id,jdbcType=BIGINT}
</select>
<select id="selectByName" resultMap="BaseResultMap" parameterType="java.lang.String" >
select
<include refid="Base_Column_List" />
from t_user
where username = #{username,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long" >
delete from t_user
where id = #{id,jdbcType=BIGINT}
</delete>
<insert id="insert" parameterType="com.wjy.entity.TUser" >
insert into t_user (id, username, userpassword,
usertel, login_error_num, lock_time,
status, real_name, id_card,
userpassword_salt, remark)
values (#{id,jdbcType=BIGINT}, #{username,jdbcType=VARCHAR}, #{userpassword,jdbcType=VARCHAR},
#{usertel,jdbcType=VARCHAR}, #{loginErrorNum,jdbcType=BIT}, #{lockTime,jdbcType=INTEGER},
#{status,jdbcType=BIT}, #{realName,jdbcType=VARCHAR}, #{idCard,jdbcType=VARCHAR},
#{userpasswordSalt,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="com.wjy.entity.TUser" >
insert into t_user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="username != null" >
username,
</if>
<if test="userpassword != null" >
userpassword,
</if>
<if test="usertel != null" >
usertel,
</if>
<if test="loginErrorNum != null" >
login_error_num,
</if>
<if test="lockTime != null" >
lock_time,
</if>
<if test="status != null" >
status,
</if>
<if test="realName != null" >
real_name,
</if>
<if test="idCard != null" >
id_card,
</if>
<if test="userpasswordSalt != null" >
userpassword_salt,
</if>
<if test="remark != null" >
remark,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=BIGINT},
</if>
<if test="username != null" >
#{username,jdbcType=VARCHAR},
</if>
<if test="userpassword != null" >
#{userpassword,jdbcType=VARCHAR},
</if>
<if test="usertel != null" >
#{usertel,jdbcType=VARCHAR},
</if>
<if test="loginErrorNum != null" >
#{loginErrorNum,jdbcType=BIT},
</if>
<if test="lockTime != null" >
#{lockTime,jdbcType=INTEGER},
</if>
<if test="status != null" >
#{status,jdbcType=BIT},
</if>
<if test="realName != null" >
#{realName,jdbcType=VARCHAR},
</if>
<if test="idCard != null" >
#{idCard,jdbcType=VARCHAR},
</if>
<if test="userpasswordSalt != null" >
#{userpasswordSalt,jdbcType=VARCHAR},
</if>
<if test="remark != null" >
#{remark,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.wjy.entity.TUser" >
update t_user
<set >
<if test="username != null" >
username = #{username,jdbcType=VARCHAR},
</if>
<if test="userpassword != null" >
userpassword = #{userpassword,jdbcType=VARCHAR},
</if>
<if test="usertel != null" >
usertel = #{usertel,jdbcType=VARCHAR},
</if>
<if test="loginErrorNum != null" >
login_error_num = #{loginErrorNum,jdbcType=BIT},
</if>
<if test="lockTime != null" >
lock_time = #{lockTime,jdbcType=INTEGER},
</if>
<if test="status != null" >
status = #{status,jdbcType=BIT},
</if>
<if test="realName != null" >
real_name = #{realName,jdbcType=VARCHAR},
</if>
<if test="idCard != null" >
id_card = #{idCard,jdbcType=VARCHAR},
</if>
<if test="userpasswordSalt != null" >
userpassword_salt = #{userpasswordSalt,jdbcType=VARCHAR},
</if>
<if test="remark != null" >
remark = #{remark,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKey" parameterType="com.wjy.entity.TUser" >
update t_user
set username = #{username,jdbcType=VARCHAR},
userpassword = #{userpassword,jdbcType=VARCHAR},
usertel = #{usertel,jdbcType=VARCHAR},
login_error_num = #{loginErrorNum,jdbcType=BIT},
lock_time = #{lockTime,jdbcType=INTEGER},
status = #{status,jdbcType=BIT},
real_name = #{realName,jdbcType=VARCHAR},
id_card = #{idCard,jdbcType=VARCHAR},
userpassword_salt = #{userpasswordSalt,jdbcType=VARCHAR},
remark = #{remark,jdbcType=VARCHAR}
where id = #{id,jdbcType=BIGINT}
</update>
</mapper>

mapper接口

package com.wjy.mapper;

import com.wjy.entity.TUser;

import java.util.List;

public interface TUserMapper {
int deleteByPrimaryKey(Long id); int insert(TUser record); int insertSelective(TUser record); TUser selectByPrimaryKey(Long id); int updateByPrimaryKeySelective(TUser record); int updateByPrimaryKey(TUser record); List<TUser> selectByName(String userName);
}

service接口

package com.wjy.service;

import com.wjy.entity.TUser;

import java.util.List;

/**
*用户service
*/
public interface TuserService { //根据用户名查user
List<TUser> findTuserByUsername(String userName); //根据用户名查user
int insertTuser(TUser tUser); }

service实现类

package com.wjy.service.impl;

import com.wjy.entity.TUser;
import com.wjy.mapper.TUserMapper;
import com.wjy.service.TuserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import java.util.List; @Service
public class TuserServiceImpl implements TuserService { @Autowired(required = false)
private TUserMapper tUserMapper; @Override
public List<TUser> findTuserByUsername(String userName) {
return tUserMapper.selectByName(userName);
} @Override
public int insertTuser(TUser tUser) {
return tUserMapper.insert(tUser);
}
}

实体类

package com.wjy.entity;

public class TUser {
private Long id; private String username; private String userpassword; private String usertel; private Boolean loginErrorNum; private Integer lockTime; private Boolean status; private String realName; private String idCard; private String userpasswordSalt; private String remark; public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username == null ? null : username.trim();
} public String getUserpassword() {
return userpassword;
} public void setUserpassword(String userpassword) {
this.userpassword = userpassword == null ? null : userpassword.trim();
} public String getUsertel() {
return usertel;
} public void setUsertel(String usertel) {
this.usertel = usertel == null ? null : usertel.trim();
} public Boolean getLoginErrorNum() {
return loginErrorNum;
} public void setLoginErrorNum(Boolean loginErrorNum) {
this.loginErrorNum = loginErrorNum;
} public Integer getLockTime() {
return lockTime;
} public void setLockTime(Integer lockTime) {
this.lockTime = lockTime;
} public Boolean getStatus() {
return status;
} public void setStatus(Boolean status) {
this.status = status;
} public String getRealName() {
return realName;
} public void setRealName(String realName) {
this.realName = realName == null ? null : realName.trim();
} public String getIdCard() {
return idCard;
} public void setIdCard(String idCard) {
this.idCard = idCard == null ? null : idCard.trim();
} public String getUserpasswordSalt() {
return userpasswordSalt;
} public void setUserpasswordSalt(String userpasswordSalt) {
this.userpasswordSalt = userpasswordSalt == null ? null : userpasswordSalt.trim();
} public String getRemark() {
return remark;
} public void setRemark(String remark) {
this.remark = remark == null ? null : remark.trim();
}
}

MD5utils

package com.wjy.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; public class MD5Utils { public static String encrypt(String password) {
String passwordMd5 = null;
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bytes = md5.digest(password.getBytes("utf-8"));
passwordMd5 = toHex(bytes);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return passwordMd5;
} private static String toHex(byte[] bytes) { final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
StringBuilder ret = new StringBuilder(bytes.length * 2);
for (int i=0; i<bytes.length; i++) {
ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
}
return ret.toString();
} }
ResultUtils(这个ResultUtils是之前从别人那拿过来的,原链接实在找不到了)
package com.wjy.utils;

import com.alibaba.fastjson.JSON;

/*
* 结果类
* */
public class ResultUtils {
//返回结果true:成功,false:失败
private boolean success = true;
//返回信息
private String msg;
//返回结果集
private Object result; public void setSuccess(boolean success) {
this.success = success;
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
} public Object getResult() {
return result;
} public void setResult(Object result) {
this.result = result;
} public ResultUtils() {
} public ResultUtils(boolean success, String msg) {
this.success = success;
this.msg = msg;
} public ResultUtils(boolean success, String msg, Object result) {
this.success = success;
this.msg = msg;
this.result = result;
} public boolean isSuccess() {
return success;
}
/*
* 返回成功结果
* */
public Object successResult(){
ResultUtils resultUtils = new ResultUtils();
resultUtils.setSuccess(true);
resultUtils.setMsg("success");
resultUtils.setResult(null);
return JSON.toJSON(resultUtils);
}
/*
* 返回成功结果
* */
public Object successResult(Object obj){
//判断参数obj是否是String类型
if (obj instanceof String){
return successResult(null, (String) obj);
}else{
return successResult(obj, "error");
}
} /*
* 返回成功结果
* */
public Object successResult(Object obj, String msg){
ResultUtils resultUtils = new ResultUtils();
resultUtils.setSuccess(true);
resultUtils.setMsg(msg);
resultUtils.setResult(obj);
return JSON.toJSON(resultUtils);
}
/*
* 返回错误结果
* */
public Object errorResult(String msg){
ResultUtils resultUtils = new ResultUtils();
resultUtils.setSuccess(false);
resultUtils.setMsg(msg);
resultUtils.setResult(null);
return JSON.toJSON(resultUtils);
}
/*
* 返回错误结果
* */
public Object errorResult(Object obj){
if (obj instanceof String){
return renderJsonError(null, (String) obj);
}else{
return renderJsonError(obj, "error");
}
}
/*
* 返回错误结果
* */
public Object renderJsonError(Object obj, String msg){
ResultUtils resultUtils = new ResultUtils();
resultUtils.setSuccess(false);
resultUtils.setMsg(msg);
resultUtils.setResult(obj);
return JSON.toJSON(resultUtils);
}
}
UserController
package com.wjy.controller;

import com.wjy.entity.TUser;
import com.wjy.entity.WmUserUsers;
import com.wjy.service.TuserService;
import com.wjy.service.WmUserUsersService;
import com.wjy.utils.MD5Utils;
import com.wjy.utils.ResultUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.util.StringUtils; import javax.servlet.ServletException;
import java.io.IOException;
import java.util.List; @RestController
@RequestMapping("/user")
public class UserController { @Autowired
private WmUserUsersService wmUserUsersService; @Autowired
private TuserService tuserService; /**
* @param
* @return
* @throws IOException
* @throws ServletException
*/
@RequestMapping(value = "userSignUp", method = {RequestMethod.GET, RequestMethod.POST})
public Object userSignUp(TUser tUser) throws IOException, ServletException {
ResultUtils res = new ResultUtils();
if (StringUtils.isEmpty(tUser.getUsername()) || StringUtils.isEmpty(tUser.getUserpassword()))
return res.errorResult("请填写用户名或密码"); List<TUser> tuserList = tuserService.findTuserByUsername(tUser.getUsername());
if (tuserList.size() > 0)
return res.errorResult("该用户名已经注册过"); tUser.setUserpassword(MD5Utils.encrypt(tUser.getUserpassword()));
int i = tuserService.insertTuser(tUser);
return res.successResult(null, "注册成功!");
} @RequestMapping(value = "userSignIn", method = {RequestMethod.GET, RequestMethod.POST})
public Object userSignIn(TUser tUser) throws IOException, ServletException {
ResultUtils res = new ResultUtils();
if (StringUtils.isEmpty(tUser.getUsername()) || StringUtils.isEmpty(tUser.getUserpassword()))
return res.errorResult("请填写用户名或密码"); List<TUser> tuserList = tuserService.findTuserByUsername(tUser.getUsername());
if (tuserList.size() <= 0)
return res.errorResult("未找到账号"); if (tuserList.size() > 0 && !tuserList.get(0).getUserpassword().equals(MD5Utils.encrypt(tUser.getUserpassword())))
return res.errorResult("密码错误"); return res.successResult(null, "登录成功!");
} }
IndexController 首页和页面跳转   
package com.wjy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @RestController
@RequestMapping("/")
public class IndexController { /**
* 首页
* @param response
* @param request
* @return
* @throws IOException
* @throws ServletException
*/
@RequestMapping(value ="index",method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView index(HttpServletResponse response, HttpServletRequest request) throws IOException, ServletException {
return new ModelAndView("index");
} /**
* html 页面之间的跳转 th:href="@{/toPage(url=sign-up2.html)}"
* @param request
* @return
*/
@RequestMapping(value = "/toPage",method = RequestMethod.GET)
public ModelAndView ModelAndView(HttpServletRequest request){
String url = request.getParameter("url");
return new ModelAndView(url);
} }
generatorConfiguration.xml  
mybatis的自动生成工具 放在generator包下
里面的一些配置需要自己修改 然后执行 mvn mybatis-generator:generate命令
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 数据库驱动:选择你的本地硬盘上面的数据库驱动包
<classPathEntry location="F:\Projects\IdeaProjects\kfcloud\mysql-connector-java-5.1.25.jar"/>
-->
<classPathEntry location="D:\jar\mysql-connector-java-8.0.11.jar"/> <context id="userGenerator" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库链接URL,用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/independenttest?serverTimezone=UTC" userId="root" password="root"></jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成模型的包名和位置-->
<javaModelGenerator targetPackage="com.wjy.entity" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成映射文件的包名和位置-->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 生成DAO的包名和位置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.wjy.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
<table tableName="wm_user_users" domainObjectName="WmUserUsers" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
</context>
</generatorConfiguration>
MinimalProjectApplication 启动类
package com.wjy;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
//mapper接口类扫描包配置
@MapperScan("com.wjy.mapper")
public class MinimalProjectApplication { public static void main(String[] args) {
SpringApplication.run(MinimalProjectApplication.class, args);
} }
index.html
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Minimal and Clean Sign up / Login and Forgot Form by FreeHTML5.co</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Free HTML5 Template by FreeHTML5.co" />
<meta name="keywords" content="free html5, free template, free bootstrap, html5, css3, mobile first, responsive" /> <!-- Facebook and Twitter integration -->
<meta property="og:title" content=""/>
<meta property="og:image" content=""/>
<meta property="og:url" content=""/>
<meta property="og:site_name" content=""/>
<meta property="og:description" content=""/>
<meta name="twitter:title" content="" />
<meta name="twitter:image" content="" />
<meta name="twitter:url" content="" />
<meta name="twitter:card" content="" /> <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<link rel="shortcut icon" href="favicon.ico"> <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700,300' rel='stylesheet' type='text/css'> <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/animate.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/style.css}"> </head>
<body class="style-2"> <div class="container">
<div class="row">
<div class="col-md-4"> <!-- Start Sign In Form -->
<form id="form" action="#" class="fh5co-form animate-box" data-animate-effect="fadeInLeft" >
<h2>Sign In</h2>
<div class="form-group">
<label for="username" class="sr-only">Username</label>
<input type="text" class="form-control" required="true" id="username" name="username" placeholder="Username" autocomplete="off" value="123456">
</div>
<div class="form-group">
<label for="userpassword" class="sr-only">Password</label>
<input type="password" class="form-control" required="true" id="userpassword" placeholder="userpassword" autocomplete="off" value="123456">
</div>
<div class="form-group">
<label for="remember"><input type="checkbox" id="remember"> Remember Me</label>
</div>
<div class="form-group">
<p>Not registered? <a th:href="@{/toPage(url=sign-up2.html)}" >Sign Up</a> | <a th:href="@{/toPage(url=forgot2.html)}" >Forgot Password?</a></p>
</div>
<div class="form-group">
<input type="" onclick="signIn()" value="Sign In" class="btn btn-primary">
</div>
</form>
<!-- END Sign In Form --> </div>
</div> <!--公有js-->
<div th:replace="headJs::common_js(~{::script})">
</div>
</div>
<script th:src="@{/js/index.js}"></script>
</body>
</html>

index.js

$(function () {
//console.info("index.js")
}); function signIn() {
if ($("#form").valid()) {
var username = $("#username").val();
var userpassword = $("#userpassword").val();
$.ajax({
url: '/user/userSignIn',
type: 'GET',/*POST*/
contentType: 'application/json',
dataType: 'json',
data: {username: username, userpassword: userpassword},
success: function (result) {
console.info(result.success)
confirm(result.msg);
//window.location.href = '/toPage?url=index_home.html';
}
}); } else {
return false;
} }

sign-up2.html

<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<!--[if lt IE 7]>
<html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>
<html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>
<html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Minimal and Clean Sign up / Login and Forgot Form by FreeHTML5.co</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Free HTML5 Template by FreeHTML5.co"/>
<meta name="keywords" content="free html5, free template, free bootstrap, html5, css3, mobile first, responsive"/> <!-- Facebook and Twitter integration -->
<meta property="og:title" content=""/>
<meta property="og:image" content=""/>
<meta property="og:url" content=""/>
<meta property="og:site_name" content=""/>
<meta property="og:description" content=""/>
<meta name="twitter:title" content=""/>
<meta name="twitter:image" content=""/>
<meta name="twitter:url" content=""/>
<meta name="twitter:card" content=""/> <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<link rel="shortcut icon" href="favicon.ico"> <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700,300' rel='stylesheet' type='text/css'> <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/animate.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/style.css}"> <!-- Modernizr JS -->
<script src="js/modernizr-2.6.2.min.js"></script>
<!-- FOR IE9 below -->
<!--[if lt IE 9]>
<script src="js/respond.min.js"></script>
<![endif]--> </head>
<body class="style-2"> <div class="container">
<div class="row">
<div class="col-md-4"> <!-- Start Sign In Form -->
<form action="#" class="fh5co-form animate-box" data-animate-effect="fadeInLeft" id="form">
<h2>Sign Up</h2>
<div class="form-group">
<div class="alert alert-success" role="alert">Your info has been saved.</div>
</div>
<div class="form-group">
<label for="username" class="sr-only">Name</label>
<input type="text" class="form-control" id="username" name="username" required="true" placeholder="Name" autocomplete="off">
</div>
<!-- <div class="form-group">
<label for="email" class="sr-only">Email</label>
<input type="email" class="form-control" id="email" required="true" placeholder="Email" autocomplete="off">
</div>-->
<div class="form-group">
<label for="userpassword" class="sr-only">Password</label>
<input type="password" class="form-control" id="userpassword" name="userpassword" minlength="6" maxlength="20" required="true" placeholder="Password" autocomplete="off">
</div>
<div class="form-group">
<label for="repassword" class="sr-only">Re-type Password</label>
<input type="password" class="form-control" id="repassword" name="repassword" minlength="6" maxlength="20" required="true" placeholder="Re-type Password"
autocomplete="off">
</div>
<div class="form-group">
<label for="remember"><input type="checkbox" id="remember"> Remember Me</label>
</div>
<div class="form-group">
<p>Already registered? <a th:href="@{/toPage(url=index.html)}">Sign In</a></p>
</div>
<div class="form-group">
<input type="" value="Sign Up" onclick="signUp()" class="btn btn-primary">
</div>
</form>
<!-- END Sign In Form --> </div>
</div> <!--公有js-->
<div th:replace="headJs::common_js(~{::script})">
</div> </div> </body>
<script th:src="@{/js/sign-up2.js}"></script>
</html>

sign-up2.js

function signUp() {
if ($("#form").valid()) {
var username = $("#username").val();
var userpassword = $("#userpassword").val();
var repassword = $("#repassword").val();
if ($.trim(userpassword) != $.trim(repassword)) {
confirm("两次密码不一致");
return;
} $.ajax({
url: '/user/userSignUp',
type: 'GET',/*POST*/
contentType: 'application/json',
dataType: 'json',
data: {username: username, userpassword: userpassword},
success: function (result) {
console.info(result)
confirm(result.msg);
}
});
} else {
return false;
}
}

至于css这些资源就不往上贴了,直接贴源码地址。

链接:https://pan.baidu.com/s/1Tm0EcoC9f1NWDRQuD3EoPw
提取码:d4mg

访问路径  localhost:8080/index

说一下遇到的一些问题

由于第一次使用springboot项目,暂时只会用 thymeleaf 这个东西来使用页面,页面必须要放在templates下,静态资源必须放在static下。

html里要加代码    <html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">  ,

引css: <link rel="stylesheet" type="text/css" th:href="@{/css/style.css}"> ,

引js: <script th:src="@{/js/index.js}"></script>,

而且跳页的时候两个页面之间好像不能互相跳,只能用下面这种方式先请求后台在返回 ModelAndView,因为在controller中用了  @RestController  注解,如果直接return “页面路径” 的话会输出字符串,用重定向好像也没成功,只能用 ModelAndView 这种方式。

如果有了解别的方法的可以留言,还有就是必须要使用 thymeleaf 这种方式吗,我的页面和静态资源正常来说想放在任何包下都可以吧。

  a标签      <a th:href="@{/toPage(url=sign-up2.html)}" >

  后台方法  (方法名应该改一下,当时没注意)
    /**
* html 页面之间的跳转 th:href="@{/toPage(url=sign-up2.html)}"
* @param request
* @return
*/
@RequestMapping(value = "/toPage",method = RequestMethod.GET)
public ModelAndView ModelAndView(HttpServletRequest request){
String url = request.getParameter("url");
return new ModelAndView(url);
}

不知道是不是只有这一种方法,有人还知道别的方法的话可以留个言。

在项目中创建了一个公共的html,为了抽取一些公用js,代码如下:

headJs.js
<html lang="zh-CN">
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<div th:fragment="common_js(scripts)"> <script th:src="@{/js/jquery.min.js}"></script> <!--jquery验证插件 -->
<script th:src="@{http://static.runoob.com/assets/jquery-validation-1.14.0/dist/jquery.validate.min.js}"></script> <script th:src="@{/js/bootstrap.min.js}"></script> <script th:src="@{/js/jquery.placeholder.min.js}"></script> <script th:src="@{/js/jquery.waypoints.min.js}"></script> <script th:src="@{/js/main.js}"></script> <!-- Modernizr JS -->
<script th:src="@{/js/modernizr-2.6.2.min.js}"></script>
<script th:src="@{/js/respond.min.js}"></script> <!--/* Per-page placeholder for additional js */-->
<!-- <th:block th:replace="${scripts}" />--> </div>
</html>

引入方式

    <!--公有js-->
<div th:replace="headJs::common_js(~{::script})">
</div>

还有要注意springboot的启动类  MinimalProjectApplication 必须要放在项目根目录,

因为Spring 在扫描注解的时候是扫描这个文件所在包以下的所有Class,

如果其他类放在了高于这个类或其他目录下就会扫描不到。

未完待续

总体来说就是这些,用什么问题和建议随时交流下次会对service和mapper接口做一些抽取,封装baseService和baseDao,再使用一下通用mapper简化一下开发。