点我点我:项目github地址。
1、数据库建表。
新建mysql数据库、取名为springcloudssh,设置编码utf8,执行如下SQL语句创建表。
DROP TABLE IF EXISTS `ssh_user`;
CREATE TABLE `ssh_user` (
`u_id` varchar(64) NOT NULL,
`username` varchar(100) NOT NULL,
`password` varchar(100) NOT NULL,
`nickname` varchar(255) DEFAULT NULL,
`mobile` varchar(20) DEFAULT NULL,
`gender` varchar(10) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`create_time` datetime NOT NULL,
`u_status` tinyint(2) NOT NULL DEFAULT '1' COMMENT '是否启用(1是0否)',
`address` varchar(255) DEFAULT NULL,
`description` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`u_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
2、搭建项目并进行配置及分层。
新建maven module,命名为micro-service-jpa,父项目指向micro,打包方式选择jar,新建方式选择“maven-archetype-webapp”。
pom.xml引入SpringBoot基础包、spring-cloud-starter-eureka、javax.servlet-api,pom.xml依赖导入spring-boot-starter-data-jpa(移除内置hibernate-commons-annotations并重新引用hibernate-commons-annotations 4.0.5.Final)、引入spring-boot-starter-thymeleaf spring-boot-starter-thymeleaf模板引擎、引入mysql-connector-java、jdo-api,如下图所示:
在src/main/java目录下新建com.xiudoua.study.micro包及其子包、并新建JpaApplication.java作为启动类,新建后结构如下:
在src/main/resources目录下新建application.properties文件,文件结构如下:
#标注服务名称
spring.application.name=add
#标注服务端口号
server.port=8086
#MySql数据库链接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springcloudssh?characterEncoding=utf-8
spring.datasource.username=你MySql数据库账号
spring.datasource.password=你MySql数据库密码
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#指定jpa配置
spring.jpa.database=mysql
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.show_sql=true
#thymeleaf模板引擎配置
spring.thymeleaf.mode=HTML5
spring.mvc.view.prefix=classpath:/templates/
spring.mvc.view.suffix=.html
#显示注册客户端主机和端口号
spring.cloud.client.ipAddres=http://localhost/
eureka.instance.instance-id=${spring.cloud.client.ipAddress}:${spring.application.name}:${spring.application.instance_id:${server.port}}
eureka.instance.preferIpAddress=true
#JustFresh 2018-04-02 配置服务链路追踪服务器地址
spring.zipkin.base-url=http://localhost:8081
3、后台增删改查dao、service、controller实现。
com.xiudoua.study.micro.entity包下新建SshUser.java类,对应数据库ssh_user表,代码如下(get、set省略):
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "ssh_user")
@SuppressWarnings("serial")
public class SshUser implements Serializable{
@Column(name = "id")
private String id;
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
@Column(name = "nickname")
private String nickname;
@Column(name = "mobile")
private String mobile;
@Column(name = "gender")
private String gender;
@Column(name = "email")
private String email;
@Column(name = "create_time")
private Date createTime;
@Column(name = "u_status")
private int uStatus;
@Column(name = "address")
private String address;
@Column(name = "description")
private String description;
}
在com.xiudoua.study.micro.dao目录下新建IUserDao接口,继承JpaRepository(JpaRepository已内置了一系列对数据的增删改查分页等操作,故此dao层方法的使用只需在此基础上添加即可),代码如下:
在com.xiudoua.study.micro.bean目录下新建UserBean.java类,对应SshUser的formbean(此处为测试,直接去除@Entity、@Column等Hibernate注解即可)。
在com.xiudoua.study.micro.exception目录下新建FormException继承Exception(目的为实现表单校验自定义异常,此处仅为个人粗略的设想做法而已,可忽略),代码如下:
public class FormException extends Exception{
private static final long serialVersionUID = 1L;
/**
* 错误编码
*/
private String errorCode;
/**
* 消息是否为属性文件中的Key
*/
private boolean propertiesKey = true;
/**
* 构造一个基本异常.
* Creates a new instance of FormException.<br/>
* Description: TODO<br/>
* @param msg
*/
public FormException(String msg){
super(msg);
}
public FormException(String errorCode,String msg){
this(errorCode,msg,true);
}
public FormException(String errorCode,String msg,Throwable cause){
this(errorCode, msg, cause, true);
}
public FormException(String errorCode,String msg,boolean propertiesKey){
super(msg);
this.setErrorCode(errorCode);
this.setPropertiesKey(propertiesKey);
}
public FormException(String errorCode,String msg,Throwable cause,boolean propertiesKey){
super(msg,cause);
this.setErrorCode(errorCode);
this.setPropertiesKey(propertiesKey);
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public boolean isPropertiesKey() {
return propertiesKey;
}
public void setPropertiesKey(boolean propertiesKey) {
this.propertiesKey = propertiesKey;
}
}
在com.xiudoua.study.micro.service目录下新建IBaseService<T>通用接口,方法如下:
public interface IBaseService<T> {
public int add(T param) throws FormException;
public int remove(T param) throws FormException;
public T update(T param) throws FormException;
public T getOne(T param) throws FormException;
public List<T> getList(T param) throws FormException;
}
在com.xiudoua.study.micro.service新建IUserService<UserBean>继承IBaseService<T>,在om.xiudoua.study.micro.service.impl目录下新建UserServiceImpl对IUserService实现,代码如下图:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.xiudoua.study.micro.bean.UserBean;
import com.xiudoua.study.micro.dao.IUserDao;
import com.xiudoua.study.micro.entity.SshUser;
import com.xiudoua.study.micro.exception.FormException;
import com.xiudoua.study.micro.service.IUserService;
import com.xiudoua.study.micro.utils.UUIDTool;
@Service("userService")
@Transactional
public class UserServiceImpl implements IUserService {
@Autowired
private IUserDao userDao;
@Override
public int add(UserBean param) throws FormException {
if(param.getUsername() == null || "".equals(param.getUsername().trim())){
throw new FormException("101","请输入用户名");
}
if(param.getPassword() == null || "".equals(param.getPassword())){
throw new FormException("101","请输入密码");
}
param.setId(UUIDTool.getUUID());
param.setuStatus(1);
param.setCreateTime(new Date());
SshUser user = new SshUser();
BeanUtils.copyProperties(param, user);
SshUser res = this.userDao.save(user);
if(res != null){
return 1;
}
return 0;
}
@Override
public int remove(UserBean param) throws FormException {
if(param.getId() == null || "".equals(param.getId().trim())){
throw new FormException("101","请选择需要删除的数据");
}
//逻辑删除
SshUser user = this.userDao.findOne(param.getId());
if(user != null){
user.setuStatus(0);
SshUser res = this.userDao.saveAndFlush(user);
if(res != null){
//逻辑删除成功
return 1;
}
}
return 0;
}
@Override
public UserBean update(UserBean param) throws FormException {
if(param.getId() == null || "".equals(param.getId().trim())){
throw new FormException("101","请选择需要修改的数据");
}
SshUser user = this.userDao.findOne(param.getId());
BeanUtils.copyProperties(param, user);
if(user != null){
SshUser res = this.userDao.saveAndFlush(user);
if(res != null){
BeanUtils.copyProperties(res, param);
return param;
}
}
return null;
}
@Override
public UserBean getOne(UserBean param) throws FormException {
if(param.getId() == null || "".equals(param.getId().trim())){
throw new FormException("101","请选择需要查询的数据");
}
SshUser user = this.userDao.findOne(param.getId());
if(user != null){
UserBean result = new UserBean();
BeanUtils.copyProperties(user, result);
return result;
}
return null;
}
@Override
public List<UserBean> getList(UserBean param) throws FormException {
List<SshUser> list = this.userDao.getListByHql(1);//查询状态值为1的用户数据
if(list != null && list.size() > 0){
List<UserBean> userList = new ArrayList<UserBean>();
for(SshUser user : list){
UserBean bean = new UserBean();
BeanUtils.copyProperties(user, bean);
userList.add(bean);
}
return userList;
}
return null;
}
}
在com.xiudoua.study.micro.controller目录下新建UserController.java类,处理用户信息的增删改查控制器、代码如下(此处控制器注解不能使用@RestController,若使用@RestController,则Thymeleaf模板视图不解析):
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.xiudoua.study.micro.bean.UserBean;
import com.xiudoua.study.micro.exception.FormException;
import com.xiudoua.study.micro.service.IUserService;
import com.xiudoua.study.micro.utils.Json;
import com.xiudoua.study.micro.utils.MD5Util;
@Controller
@RequestMapping("/user")
public class UserController {
private Logger logger = Logger.getLogger(UserController.class);
@Autowired
private IUserService userService;
/**
* 跳转到列表页面
* listGet:TODO Description <br/>
*/
@RequestMapping(value = "/list",method = RequestMethod.GET)
public String listGet(UserBean param,HttpServletRequest request,Model model){
try {
List<UserBean> adsList = this.userService.getList(param);
model.addAttribute("userList", adsList);
} catch (FormException e) {
model.addAttribute("errorMsg", e.getMessage());
logger.error(e.getMessage());
}
return "user/list";
}
/**
* 跳转到添加页面
* listGet:TODO Description <br/>
*/
@RequestMapping(value = "/add",method = RequestMethod.GET)
public String addGet(Model model){
return "user/add";
}
/**
* 添加用户
* listGet:TODO Description <br/>
*/
@ResponseBody
@RequestMapping(value = "/add",method = RequestMethod.POST)
public Json addPost(UserBean param,Model model,HttpServletRequest request){
Json json = new Json();
try {
int count = this.userService.add(param);
if(count > 0){
json.setMsg("添加成功");
json.setSuccess(true);
}else{
json.setMsg("添加失败");
json.setSuccess(false);
}
} catch (FormException e) {
logger.error(e.getMessage());
json.setErrorCode(e.getErrorCode());
json.setMsg(e.getMessage());
}
return json;
}
/**
* 删除用户
* listGet:TODO Description <br/>
*/
@ResponseBody
@RequestMapping(value = "/remove",method = RequestMethod.POST)
public Json removePost(UserBean param,Model model,HttpServletRequest request){
Json json = new Json();
try {
int count = this.userService.remove(param);
if(count > 0){
json.setMsg("删除成功");
json.setSuccess(true);
}else{
json.setMsg("删除失败");
json.setSuccess(false);
}
} catch (FormException e) {
logger.error(e.getMessage());
json.setErrorCode(e.getErrorCode());
json.setMsg(e.getMessage());
}
return json;
}
/**
* 跳转到修改页面
* listGet:TODO Description <br/>
*/
@RequestMapping(value = "/update",method = RequestMethod.GET)
public String updateGet(UserBean param,Model model){
try {
UserBean res = this.userService.getOne(param);
if(res != null && !"".equals(res.getPassword())){
res.setPassword(MD5Util.convertMD5(MD5Util.convertMD5(res.getPassword())));
}
model.addAttribute("userInfo", res);
} catch (FormException e) {
logger.error(e.getMessage());
}
return "user/update";
}
/**
* 添加用户
* listGet:TODO Description <br/>
*/
@ResponseBody
@RequestMapping(value = "/update",method = RequestMethod.POST)
public Json updatePost(UserBean param,Model model,HttpServletRequest request){
Json json = new Json();
try {
UserBean res = this.userService.update(param);
if(res != null){
json.setMsg("修改成功");
json.setSuccess(true);
}else{
json.setMsg("修改失败");
json.setSuccess(false);
}
} catch (FormException e) {
logger.error(e.getMessage());
json.setErrorCode(e.getErrorCode());
json.setMsg(e.getMessage());
}
return json;
}
/**
* 显示详细
*/
@RequestMapping(value = "/detail",method = RequestMethod.GET)
public String detailGet(UserBean param,Model model){
try {
UserBean res = this.userService.getOne(param);
model.addAttribute("userInfo", res);
} catch (FormException e) {
logger.error(e.getMessage());
}
return "user/detail";
}
}
4、前端页面实现。
在src/main/resrouces目录下新建public目录(此处引入js、css、images等文件),引入jquery.js、bootstrap.css、layer.js、fontawesome字体样式等,如下图:
在src/main/resources目录下新增templates文件夹(此文件夹对应Thymeleaf模板的视图),再此文件夹下新建user文件夹标示user处理,user文件夹下新建add.html、detail.html、list.html、update.html,分别用作用户新增页、用户详情查看页、用户列表页、用户信息修改页,代码分别如下:
(1)、add.html。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="zh-cn">
<head>
<meta charset="UTF-8" />
<title>SpringBoot SSH测试</title>
<link rel="stylesheet" href="/css/bootstrap.css" />
</head>
<body>
<div class="container">
<h1>新增用户</h1>
<div class="row">
<form id="addForm">
<div class="form-group">
<label>用户名</label>
<input type="text" class="form-control" id="username" placeholder="请输入用户名" />
</div>
<div class="form-group">
<label>密码</label>
<input type="password" class="form-control" id="password" placeholder="请输入密码" />
</div>
<div class="form-group">
<label>昵称</label>
<input type="text" class="form-control" id="nickname" placeholder="请输入昵称" />
</div>
<input type="button" class="btn btn-default" value="保存" onclick="add()"/>
</form>
</div>
</div>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/layer.js"></script>
<script type="text/javascript" src="/js/app.js"></script>
<script type="text/javascript">
var add = function(){
var username = $("#username").val();
var password = $("#password").val();
var nickname = $("#nickname").val();
if(username == null || username == ""){
layer.alert("请输入用户名");
return;
}
if(password == null || password == ""){
layer.alert("请输入密码");
return;
}
if(nickname == null || nickname == ""){
layer.alert("请输入昵称");
return;
}
$.ajax({
type: "post",
url: siteUrl + "user/add",
data: {
username: username,
password: password,
nickname: nickname
},dataType: "json",
success: function(res){
if(res.success){
window.location.href = siteUrl + "user/list";
}else{
layer.alert(res.msg);
}
}
});
};
</script>
</body>
</html>
detail.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="zh-cn">
<head>
<meta charset="UTF-8" />
<title>SpringBoot SSH测试</title>
<link rel="stylesheet" href="/css/bootstrap.css" />
</head>
<body>
<div class="container">
<h1>用户详细信息</h1>
<p>用户名: <span th:text="*{userInfo.username}">...</span>.</p>
<p>密码: <span th:text="*{userInfo.password}">...</span>.</p>
<p>昵称: <span th:text="*{userInfo.nickname}">...</span>.</p>
<a href="javascript: history.go(-1)" class="btn btn-danger">返回</a>
</div>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/layer.js"></script>
<script type="text/javascript" src="/js/app.js"></script>
<script type="text/javascript">
</script>
</body>
</html>
update.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="zh-cn">
<head>
<meta charset="UTF-8" />
<title>SpringBoot SSH测试</title>
<link rel="stylesheet" href="/css/bootstrap.css" />
</head>
<body>
<div class="container">
<h1>修改用户信息</h1>
<div class="row">
<form id="addForm">
<input type="hidden" name="userId" id="userId" th:value="${userInfo.uId}" />
<div class="form-group">
<label>用户名</label>
<input type="text" class="form-control" id="username" placeholder="请输入用户名" th:value="${userInfo.username}" />
</div>
<div class="form-group">
<label>密码</label>
<input type="password" class="form-control" id="password" placeholder="请输入密码" th:value="${userInfo.password}" />
</div>
<div class="form-group">
<label>昵称</label>
<input type="text" class="form-control" id="nickname" placeholder="请输入昵称" th:value="${userInfo.nickname}" />
</div>
<input type="button" class="btn btn-default" value="保存" onclick="update()"/>
</form>
</div>
</div>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/layer.js"></script>
<script type="text/javascript" src="/js/app.js"></script>
<script type="text/javascript">
var update = function(){
var userId = $("#userId").val();
var username = $("#username").val();
var password = $("#password").val();
var nickname = $("#nickname").val();
if(userId == null || userId == ""){
layer.alert("请选择需要修改的数据");
return;
}
if(username == null || username == ""){
layer.alert("请输入用户名");
return;
}
if(password == null || password == ""){
layer.alert("请输入密码");
return;
}
if(nickname == null || nickname == ""){
layer.alert("请输入昵称");
return;
}
$.ajax({
type: "post",
url: siteUrl + "user/update",
data: {
uId: userId,
username: username,
password: password,
nickname: nickname
},dataType: "json",
success: function(res){
if(res.success){
window.location.href = siteUrl + "user/list";
}else{
layer.alert(res.msg);
}
}
});
};
</script>
</body>
</html>
list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="zh-cn">
<head>
<meta charset="UTF-8" />
<title>SpringBoot SSH测试</title>
<link rel="stylesheet" href="/css/bootstrap.css" />
<style type="text/css">
.jf-table{margin-top: 15px;}
</style>
</head>
<body>
<div class="container">
<h1>用户列表展示</h1>
<div class="pull-right">
<a class="btn btn-success" href="/user/add">添加</a>
</div>
<div class="clearfix"></div>
<table class="table table-bordered table-striped table-hover jf-table">
<tr>
<th>姓名</th>
<th>密码</th>
<th>昵称</th>
<th>操作</th>
</tr>
<tr data-th-each="user : ${userList}">
<td data-th-text="${user.username}">...</td>
<td data-th-text="${user.password}">...</td>
<td data-th-text="${user.nickname}">...</td>
<td>
<a href="detail" th:href="@{/user/detail(uId=${user.uId})}">详细</a> |
<a href="update" th:href="@{/user/update(uId=${user.uId})}">修改</a> |
<a href="javascript: void(0)" th:onclick="'javascript:remove(\''+${user.uId}+'\')'">删除</a>
</td>
</tr>
</table>
</div>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/layer.js"></script>
<script type="text/javascript" src="/js/app.js"></script>
<script type="text/javascript">
var remove = function(id){
if(id == null || id == ""){
layer.alert("请选择需要删除的数据",{icon:2});
return;
}
var index = layer.confirm('确定要删除数据?', {
btn: ['是','否']
}, function(){
$.ajax({
type: "post",
url: siteUrl + "user/remove",
data: {
uId: id
},dataType: "json",
success: function(res){
if(res.success){
window.location.href = siteUrl + "user/list";
}else{
layer.alert(res.msg);
}
}
});
}, function(){
layer.close(index);
});
};
</script>
</body>
</html>
启动JpaApplication.java,访问http://localhost:8086/user/list,即可进行用户增删改查操作,如下图所示: