这篇博文将前两篇博文的知识内容给串一串,展示如何将之前零碎的东西给整合成一个小的、完整的东西,并且,介绍一个前端模板引擎 ------ Thymeleaf
示例:
sql 文件:
CREATE TABLE `tab_user` (
`id` varchar(50) NOT NULL,
`user_name` varchar(255) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`photo` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
实体类:
public class TabUser {
private String id;
private String userName;
private String password;
private String photo;
// getter/setter
}
【开发环境】:
【工程结构图】:
1、引入依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2、添加 application.yml
配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/zzc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
password: root
username: root
driver-class-name: com.mysql.jdbc.Driver
thymeleaf: # thymeleaf 配置
cache: false # 关闭 thymeleaf 缓存
prefix: classpath:/templates/ # 配置模板(非必要) 默认是 templates
suffix: .html
mybatis:
type-aliases-package: com.zzc.entity # 实体类别名
mapper-locations: classpath:mybatis/mapper/*.xml # mapper 配置文件(必要)
configuration:
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志输出位置
map-underscore-to-camel-case: true # 驼峰命名
#logging:
# level:
# com.zzc.mapper: debug # 设置日志级别
file:
uploadPath: E:/upload # 头像上传路径
这里面主要添加了 thymeleaf
的配置
3、测试 Thymeleaf 模板是否引入成功:
在路径 resources/templates
路径下添加一个 html 文件(如:index.html),然后,添加一个控制器进行访问:
@Controller
@RequestMapping("/test")
public class TestController {
@GetMapping("/index")
public String index() {
return "index";
}
}
浏览器访问:http://localhost:8080/test/index
如果页面出现了内容,则表示访问成功。
UserController
:
@Controller
public class UserController {
@Autowired
private UserService userService;
// 跳转到 user/user.html 页面
@GetMapping("/user")
public String user() {
return "user/user";
}
// 添加用户信息,并以json格式返回用户信息给前台
@ResponseBody
@PostMapping("/add")
public UserVo addUser(MultipartFile file, UserVo userVo) {
return userService.addUser(file, userVo);
}
}
UserService:
public interface UserService {
UserVo addUser(MultipartFile multipartFile, UserVo userVo);
}
UserServiceImpl:
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public UserVo addUser(MultipartFile multipartFile, UserVo userVo) {
if (null == multipartFile) {
return userVo;
}
// 1.上传图片
String fileName = null;
try {
fileName = FileUtil.uploadFile(multipartFile, userVo);
} catch (Exception e) {
e.printStackTrace();
}
// 2.添加到数据库
userVo.setPhoto(fileName);
TabUser tabUser = UserUtil.transformTabUser(userVo);
int i = userMapper.addUser(tabUser);
return userVo;
}
}
添加用户方法做了两个逻辑处理:上传图片到本地;存用户信息到数据库
FileUtil#uploadFile():
上传图片到本地
public class FileUtil {
private static FileConfig fileConfig = ApplicationContextHolder.getContext().getBean(FileConfig.class);
public static String uploadFile(MultipartFile file, UserVo userVo) throws Exception {
// 1.获取上传的文件名称
String sOldFileName = file.getOriginalFilename();
// 2.获取上传文件路径
String uploadPath = fileConfig.getUploadPath() + File.separator + userVo.getUserName();
// 3.生成父路径
File uploadFile = mkdirs(uploadPath);
String suffixPath = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + sOldFileName;
String fileFullPath = uploadPath + File.separator + suffixPath;
file.transferTo(new File(fileFullPath));
// 4.拼接存在数据库的文件名
return userVo.getUserName() + File.separator + suffixPath;
}
// 生成相应的目录
public static File mkdirs(String path) {
File file = new File(path);
if(!file.exists() || !file.isDirectory()) {
file.mkdirs();
}
return file;
}
}
1、上传图片到本地
uploadFile()
方法:将前台上传的图片上传到指定的路径下,并按照新的规则生成新的图片名(用户名/当前日期_上传的文件名) 存到数据库中。其中,指定的路径通过 FileConfig
类中的 uploadPath
属性获取。它配置在 application.yml
:
file:
uploadPath: E:/upload # 头像上传路径
FileConfig
:
@Component
@ConfigurationProperties(prefix = "file")
public class FileConfig {
// 上传路径
private String uploadPath;
// getter/setter
}
ApplicationContextHolder
:
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
public static Object getBean(String name) {
return context != null ? context.getBean(name) : null;
}
public static <T> T getBean(Class<T> clz) {
return context != null ? context.getBean(clz) : null;
}
public static <T> T getBean(String name, Class<T> clz) {
return context != null ? context.getBean(name, clz) : null;
}
public static void addApplicationListenerBean(String listenerBeanName) {
if (context != null) {
ApplicationEventMulticaster applicationEventMulticaster = (ApplicationEventMulticaster)context.getBean(ApplicationEventMulticaster.class);
applicationEventMulticaster.addApplicationListenerBean(listenerBeanName);
}
}
}
2、存用户信息到数据库
UserUtil:
public class UserUtil {
public static List<UserVo> transformUserVos(List<TabUser> tabUsers) {
List<UserVo> userVos = tabUsers.stream().map(tabUser -> {
UserVo userVo = new UserVo();
userVo.setsId(tabUser.getId());
userVo.setUserName(tabUser.getUserName());
userVo.setPassword(tabUser.getPassword());
return userVo;
}).collect(Collectors.toList());
return userVos;
}
public static TabUser transformTabUser(UserVo userVo) {
TabUser tabUser = new TabUser();
String sId = UUID.randomUUID().toString().trim().replaceAll("-", "");
if (StringUtils.isEmpty(userVo.getsId())) {
tabUser.setId(sId);
userVo.setsId(sId);
} else {
tabUser.setId(userVo.getsId());
}
tabUser.setUserName(userVo.getUserName());
tabUser.setPassword(userVo.getPassword());
tabUser.setPhoto(userVo.getPhoto());
return tabUser;
}
}
UserVo:
public class UserVo {
private String sId;
private String userName;
private String password;
private String photo;
// getter/setter
}
UserMapper 接口:
public interface UserMapper {
int addUser(TabUser tabUser);
}
UserMapper.xml 文件:
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zzc.mapper.UserMapper">
<insert id="addUser" parameterType="TabUser">
INSERT INTO TAB_USER (id, user_name, password, photo) values (#{id}, #{userName}, #{password}, #{photo})
</insert>
</mapper>
user.html
:用户页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/css/user.css" />
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
</head>
<body>
<h1>注册用户信息</h1>
<form id="myForm">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="userName" placeholder="用户名"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password" placeholder="密码"></td>
</tr>
<tr>
<td>头像</td>
<td><input type="file" accept="*/*" name="file" id="FileImg" onchange="uploadImg(this)" /></td>
</tr>
<tr>
<td>上传的头像</td>
<td><img src="" alt="默认头像地址(可以自己填)" id="avarimgs" style="border-radius: 50%" width="200px" height="200px"></td>
</tr>
<tr>
<td colspan="2">
<input type="button" value="注册" id="registerBtn" onclick="reg()">
</td>
</tr>
</table>
</form>
<hr>
<h1>用户注册的信息</h1>
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="userName" id="myUsername" placeholder="用户名" readonly></td>
</tr>
<tr>
<td>密码</td>
<td><input type="text" name="password" id="myPassword" placeholder="密码" readonly></td>
</tr>
<tr>
<td>头像</td>
<td>
<img src="" id="myImg" style="border-radius: 50%" width="200px" height="200px" />
</td>
</tr>
</table>
<script>
// 回显图片
function uploadImg(obj) {
var file = obj.files[0];
var reader = new FileReader();
reader.onload = function (e) {
// e 就是 ProgressEvent 对象,里面的target.result就是base64编码
var img = document.getElementById("avarimgs");
img.src = e.target.result; //或者 img.src = this.result; e.target == this
}
reader.readAsDataURL(file)
}
// 注册
function reg() {
let form = new FormData($("#myForm")[0])
$.ajax({
//接口地址
url: '/add',
type: 'POST',
data: form,
async: false,
cache: false,
contentType: false,
processData: false,
success:function (data) {
console.log(data)
var userName = data.userName;
var password = data.password;
// 图片回显
var photo = 'mystatic' + '/' + data.photo
$('#myUsername').val(userName)
$('#myPassword').val(password)
$('#myImg').attr('src', photo)
}
});
}
</script>
</body>
</html>
【注意】:js 中的 reg()
函数代码:var photo = 'mystatic' + '/' + data.photo
:
在后台中,我们将一个图片上传到一个本地路径下(FileUtil#uploadFile()
),正常情况下,SpringBoot 工程中是无法访问到静态资源的。所以,我们必须添加资源映射 ``:
@Configuration
public class MyStaticConfig implements WebMvcConfigurer {
private static String UPLOAD_FILE_PATH = "file:E:/upload/";
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 访问路径以 “/mystatic” 开头时,会去 “mystatic” 路径下找静态资源
registry
.addResourceHandler("/mystatic/**")
.addResourceLocations(UPLOAD_FILE_PATH);
}
}
上述代码的意思:在本地磁盘的路径 E:/upload/
下的文件,都可以以 /mystatic/
进行访问。
所以,var photo = 'mystatic' + '/' + data.photo
代码中,是通过 mystatic
进行拼接的(前台和后台保持一致即可!!)
因篇幅问题不能全部显示,请点此查看更多更全内容