前言:
在springboot的开发框架中,本来就推荐使用thymeleaf的前端框架,所以结合起来进行请后端的开发也是很方面的。下面就是我学习两者的一个实际用例笔记的额一个记录,方便回看关键的知识点
开发环境
- Windows 10 10.0 amd64
- eclipse Oxygen.3a Release (4.7.3a)
- Gradle 4.9
- JDK1.8.0_151
启动项目的快速搭建
- 在前面的文章有写到如何利用gradle快速搭建一个springboot启动项目,这里就不再重复
- https://www.jianshu.com/p/de72c26ec3b5
在eclipse开发环境中导入gradle项目
- 在前面的文章中也有写到如何导入,在这里也不再详述
- https://www.jianshu.com/p/3bdf834dcba6
用户管理实例的后台代码编写
-
首先是整个项目的目录结构,如下
- 然后就是实体类User.java 的编写,代码如下
package com.waylau.spring.boot.blog.domain;
/**
* @author: crj
* @date: 2018年8月21日 上午10:42:13
*/
public class User {
private Long id;//实体类的唯一标志
private String name;//名称
private String email;//邮箱
public User(){
//无参的默认的构造函数
}
public User(Long id,String name,String email) {//有参的构造函数
this.id = id;
this.name = name;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
- 然后就是借口UserRepository.java 的编写,代码如下:
package com.waylau.spring.boot.blog.repository;
import java.util.List;
import com.waylau.spring.boot.blog.domain.User;
/**
* user资源库
* @author: crj
* @date: 2018年8月21日 上午10:48:16
*/
public interface UserRepository {
/**
* 创建或者修改用户
* @author: crj
* @param user
* @return
* @date:2018年8月21日 上午10:49:02
*/
User saveOrUpdateUser(User user);
/**
* 删除用户
* @author: crj
* @param id
* @date:2018年8月21日 上午10:50:06
*/
void deleteUser(Long id);
/**
* 根据用户id查询用户
* @author: crj
* @param id
* @return
* @date:2018年8月21日 上午10:52:17
*/
User getUserById(Long id);
/**
* 获取用户列表
* @author: crj
* @return
* @date:2018年8月21日 上午10:52:01
*/
List listUsers();
}
- 然后就是编写UserRepositoryImpl.java实现上面的接口类,代码如下
package com.waylau.spring.boot.blog.repository.Impl;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Repository;
import com.waylau.spring.boot.blog.domain.User;
import com.waylau.spring.boot.blog.repository.UserRepository;
/**
* UserRepository的实现类
* @author: crj
* @date: 2018年8月21日 上午11:01:26
*/
@Repository
public class UserRepositoryImpl implements UserRepository{
//计数,每增加一个用户就递增一个,来生成每个用户的唯一id
private static AtomicLong counter= new AtomicLong();
//模拟存储库,把数据存储在内存当中,需要用到ConcurrentMap来存储用户信息的容器
private final ConcurrentMap userMap = new ConcurrentHashMap<>();
@Override
public User saveOrUpdateUser(User user) {
Long id = user.getId();
if(id == null) {//新建的
id = counter.incrementAndGet();
user.setId(id);
}
this.userMap.put(id, user);
return user;
}
@Override
public void deleteUser(Long id) {
this.userMap.remove(id);
}
@Override
public User getUserById(Long id) {
return this.userMap.get(id);
}
/**
* 说明:这里需要用到ArrayList去包装一下并以List方式返回
*/
@Override
public List listUsers() {
return new ArrayList(this.userMap.values());
}
}
- 然后就是编写与前端进行交互的UserController.java类,代码如下:
package com.waylau.spring.boot.blog.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.waylau.spring.boot.blog.domain.User;
import com.waylau.spring.boot.blog.repository.UserRepository;
/**
* User控制器
* @author: crj
* @date: 2018年8月20日 下午4:19:24
*/
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository userRepository;
/**
* 查询用户
* @author: crj
* @param model
* @return
* @date:2018年8月21日 上午11:27:11
*/
@GetMapping
public ModelAndView list(Model model) {
model.addAttribute("userList",userRepository.listUsers());
model.addAttribute("title", "用户管理");
return new ModelAndView("users/list","userModel",model);
}
/**
* 根据用户id查看用户
* @author: crj
* @param id
* @param model
* @return
* @date:2018年8月21日 上午11:30:43
*/
@GetMapping("{id}")
public ModelAndView view(@PathVariable("id") Long id,Model model) {
User user = userRepository.getUserById(id);
model.addAttribute("user",user);
model.addAttribute("title", "查看用户");
return new ModelAndView("users/view","userModel",model);
}
/**
* 获取创建表单页面
* @author: crj
* @param model
* @return
* @date:2018年8月21日 上午11:34:57
*/
@GetMapping("/form")
public ModelAndView createForm(Model model) {
model.addAttribute("user",new User());
model.addAttribute("title", "创建用户");
return new ModelAndView("users/form","userModel",model);
}
/**
* 保存或者更新用户,并返回用户列表
* @author: crj
* @param user
* @return
* @date:2018年8月21日 上午11:43:07
*/
@PostMapping
public ModelAndView saveOrUpdateUser(User user) {
user = userRepository.saveOrUpdateUser(user);
return new ModelAndView("redirect:/users");//重定向到list页面
}
/**
* s删除用户,并返回用户列表
* @author: crj
* @param id
* @return
* @date:2018年8月22日 上午9:27:49
*/
@GetMapping("/delete/{id}")
public ModelAndView deleteUser(@PathVariable("id") Long id) {
userRepository.deleteUser(id);
return new ModelAndView("redirect:/users");//重定向到list页面
}
/**
* 修改用户跳转页面
* @author: crj
* @param model
* @return
* @date:2018年8月22日 上午9:27:31
*/
@GetMapping("/modify/{id}")
public ModelAndView modifyUser(@PathVariable("id") Long id,Model model) {
model.addAttribute("user",userRepository.getUserById(id));
model.addAttribute("title", "修改用户");
return new ModelAndView("users/modify","userModel",model);
}
}
用户管理实例的前端页面代码编写
- 这里写了两个thymeleaf的页面引用模板片段,分别是header.html和footer.html分别如下:
- header
Thymeleaf in action
Thymeleaf in action
首页
- footer.html
Thymeleaf in action
- 另外分别是增删改查的页面
- list.html
Thymeleaf in action
ID
Email
Name
操作
没有用户信息!
删除
修改
- form.html
Thymeleaf in action
- view.html
Thymeleaf in action
ID:
Name:
Email:
- modify.html
Thymeleaf in action
项目运行之后,测试页面效果展示
-
展示用户列表
-
用户信息展示
-
用户信息修改
修改后自动跳转到用户列表页面
-
用户删除,删除后自动跳转回用户列表页面
后记
以上没有用到存储数据库,仅仅是在内存中进行了简单的数据操作模拟,后续会有与存储数据库进行交互
以上的代码,仅仅供给自己学习回顾记录所用
-
在这个实例编写的过程中,会遇到各种小问题,bug,我在这个过程中遇到的一个坑就是忘了导入Thymeleaf依赖,所以当测试编写的路径的时候,没有跳转到指定的前端页面,一直报下面的这个错误:
2018-08-22 12:05:09.500 WARN 13856 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to bind request element: org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "list"
原因是:如下图所记录的,
-
当我把thymeleaf的依赖加上,在重新右键项目名称,
选择Gradle的Refresh Gradle Project更新时候,就能正常跳转到具体的页面了
因为工程是用gradle创建的,所以不熟悉的朋友需要自行学习一下gradle构建项目相关知识。网上也有很多相关的gradle的开源项目,当拿过来学习的时候,也是需要用到gradle的,这个相当于maven的作用
项目的相关依赖是通过gradle的build.gradle 文件注入的,详细的过程以往的文章也有写到的。
在eclipse中,如果更改了gradle相关的配置,如增加相关依赖,需要选择Gradle的Refresh Gradle Project重新更新一下,再启动项目