学习Springboot一之Springboot+Mybatis(注解形式)+Mysql+Web简单Demo

xiaoxiao2021-02-28  24

学习SpringBoot,通过Springboot简单配置连接Mysql数据库,采用Mybatis注解方式实现数据库“增、删、改、查”,结合Spring web实现页面呈现后,。

IDE及相关环境:Windows10 :Eclipse+Maven,Linux(Centos7):Mysql 7.5

1.Demo项目结构:

2.Pom.xml文件引入相关依赖:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>springboot</groupId> <artifactId>springboot-mybatis-annotation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <!-- Spring Boot 启动父依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <properties> <mybatis-spring-boot>1.2.0</mybatis-spring-boot> <mysql-connector>5.1.39</mysql-connector> </properties> <dependencies> <!-- Spring Boot Web 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- Spring Boot Test 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Spring Boot Mybatis 依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis-spring-boot}</version> </dependency> <!-- MySQL 连接驱动依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- lombok依赖 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!-- 分页插件依赖 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.5</version> </dependency> <!-- Junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <!-- <dependency> --> <!-- <groupId>com.fasterxml.jackson.core</groupId> --> <!-- <artifactId>jackson-databind</artifactId> --> <!-- <version>2.9.0</version> --> <!-- </dependency> --> </dependencies> <build> <plugins> <plugin> <groupId>org.projectlombok</groupId> <artifactId>lombok-maven-plugin</artifactId> <version>1.12.6.0</version> </plugin> </plugins> </build> </project>

此处说明一下lombok,主要是为了省略实体定义中的重复set、get定义方法,具体可百度相关资料不少。

3. Applicaiton.properties文件

spring.datasource.url=jdbc:mysql://xxx.xxx.xxx.xxx/database?useUnicode=true&characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver // xxx.xxx.xxx.xxx/database 为mysql数据库所在地址及相应数据库(本文中mysql不在本机,在linux服务器中,因此需要IP地址) server.port=8088 //配置tomcat端口(默认为8080,已被其他app占用) spring.thymeleaf.cache=false //设置thymeleaf缓存机制(thymeleaf为快速开发web引擎模板,目前相关资料较少,后续考虑更换采用bootstrap编写前端) xxx.xxx.xxx.xxx/database?useUnicode=true&characterEncoding=utf8&useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver // xxx.xxx.xxx.xxx/database 为mysql数据库所在地址及相应数据库(本文中mysql不在本机,在linux服务器中,因此需要IP地址) server.port=8088 //配置tomcat端口(默认为8080,已被其他app占用) spring.thymeleaf.cache=false //设置thymeleaf缓存机制(thymeleaf为快速开发web引擎模板,目前相关资料较少,后续考虑更换采用bootstrap编写前端)

4.实体类User

package com.test.user.entity; import java.io.Serializable; import java.sql.Date; import com.fasterxml.jackson.annotation.JsonAutoDetect; import lombok.Getter; import lombok.Setter; /** * User实体类 * */ @Setter @Getter @JsonAutoDetect public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; /** * UserID编号 */ private String id; /** * UserName用户名称 */ private String name; /** * UserBirth用户生日 */ private Date birthday; /** * 描述 */ private String description; @Override public String toString(){ return "User{"+ "id="+id+ ",name="+name+ ",birthday="+birthday+ ",description="+description+"}"; }

编写User实体类,对应mysql数据库中的testuser表;引入了lombok因此省略set,get方法的定义。

 

相应的数据库testuser表结构如下:

CREATE TABLE `testuser` ( `UserID` varchar(50) NOT NULL, `UserName` varchar(50) DEFAULT NULL, `UserBirth` date DEFAULT NULL, `Descript` varchar(255) DEFAULT NULL, PRIMARY KEY (`UserID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

5.UserDao,编写数据库交互层接口

package com.test.user.dao; import java.util.List; import org.apache.ibatis.annotations.*; import com.test.user.entity.User; /** * User DAO 接口类 * */ @Mapper // 标志为 Mybatis 的 Mapper public interface UserDao { /** * 列出所有用户信息 * * @param name 用户名 */ @Select("SELECT * FROM testuser ORDER BY UserID") // 返回所有User信息 @Results({ @Result(property = "id", column = "UserID"), @Result(property = "name", column = "UserName"), @Result(property = "birthday", column = "UserBirth"), @Result(property = "description", column = "Descript")}) List<User> showAll(); /** * 根据UserName查询用户信息 * @param name * @return */ @Select("SELECT * FROM testuser WHERE UserName=#{name}") //根据UserName查询User信息 @Results({ @Result(property = "id", column = "UserID"), @Result(property = "name", column = "UserName"), @Result(property = "birthday", column = "UserBirth"), @Result(property = "description", column = "Descript")}) List<User> selectByName(String name); //根据UserID查询User信息 @Select("SELECT * FROM testuser WHERE UserID=#{id}") @Results({ @Result(property = "id", column = "UserID"), @Result(property = "name", column = "UserName"), @Result(property = "birthday", column = "UserBirth"), @Result(property = "description", column = "Descript")}) User selectByID(String id); /** * 插入新User * @param user * @return */ @SelectKey(keyProperty = "id",keyColumn="UserID",resultType = String.class, before =true, statement = "select replace(uuid(), '-', '-')" ) @Options(keyProperty = "id", useGeneratedKeys = true) @Insert("INSERT INTO testuser(UserID,UserName,UserBirth,Descript)" + "VALUES(#{id},#{name},#{birthday},#{description})") // @Results({ // @Result(property = "id", column = "UserID"), // @Result(property = "name", column = "UserName"), // @Result(property = "birthday", column = "UserBirth"), // @Result(property = "description", column = "Descript")}) public void addUser(User user); /** * 根据用户ID更新用户信息(ID唯一标识) * @param user */ @Update("UPDATE testuser SET UserName=#{name},UserBirth=#{birthday},Descript=#{description} WHERE UserID=#{id}") @Results({ @Result(property = "id", column = "UserID"), @Result(property = "name", column = "UserName"), @Result(property = "birthday", column = "UserBirth"), @Result(property = "description", column = "Descript")}) public void updateByUserID(User user); /** * 根据用户ID删除用户信息(ID唯一标识) * @param id * @return */ @Delete("DELETE FROM testuser WHERE UserID=#{id}") public void deleteByUserID(String id); }

这里采用Mybatis注解的方式引入数据库增删改查的操作,省去xml配置的书写(取决于个人喜好,不习惯采用xml配置的方式)

6.UserService类及UserServiceImpl类

 

package com.test.user.service; import java.util.List; import com.test.user.entity.User; /** * User业务逻辑接口类 * */ public interface UserService { /** * 列出所有用户信息 */ List<User> showAll(); /** * 根据用户名称查询用户信息 */ List<User> selectByName(String name); /** * 增加用户信息 * @return */ User selectByID(String id); // User selectByName(String name); public void addUser(User user); /** * 根据UserID更新用户信息 */ public void updateByUserID(User user); // /** // * 根据UserName更新用户信息 // */ // public void updateByUserName(User user); /** * 根据UserID删除用户信息 * @param id * @return */ public void deleteByUserID(String id); /** * 根据UserName删除用户信息 * @param name * @return */ // public void deleteByUserName(String name); // }

UserService类,定义了增删改查的方法(貌似可以省去,直接由UserServiceImpl实现UserDao类也可以实现完整功能)。

package com.test.user.service.impl; import java.util.List; import java.util.concurrent.TimeUnit; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import com.test.user.dao.UserDao; import com.test.user.entity.User; import com.test.user.service.UserService; /** * UserService逻辑实现类 * */ @Service("UserService") public class UserServiceImpl implements UserService { private static final Logger LOGGER= LoggerFactory.getLogger(UserServiceImpl.class); @Autowired private UserDao userDao; @Resource private RedisServiceImpl redisService; /** * 获取User逻辑:如缓存存在则从换从取值,否则从DB中获取,插入缓存 */ public List<User> showAll() { return userDao.showAll(); } public List<User> selectByName(String name){ return userDao.selectByName(name); } public User selectByID(String id) { User user=userDao.selectByID(id); return user; } public void addUser(User user){ userDao.addUser(user); } public void updateByUserID(User user) { userDao.updateByUserID(user); } public void deleteByUserID(String id) { userDao.deleteByUserID(id); } }

UserServiceImpl类,实现Service类中定义的方法,此处@Cache相关注解参考了别人的blog,暂时还未全部搞懂原理。

 

7.Controller类,RESTFul定义前后端数据交换

package com.test.user.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.*; import com.test.user.entity.User; import com.test.user.service.UserService; /** * */ @Controller @RequestMapping(value="/user") public class UserRestController { @Autowired private UserService userService; private static final String USER_LIST = "UserList"; private static final String USER_LIST2 = "UserList2"; private static final String USER_FORM = "UserForm"; private static final String REDIRECT_TO_USER_LIST = "redirect:/user"; /** * 获取用户列表 * 通过"/user"GET请求获取 * @param map * @return */ @RequestMapping(method=RequestMethod.GET) public String showAll(ModelMap map) { map.addAttribute("UserList",userService.showAll()); return USER_LIST; } /** * * @param name * @return */ @RequestMapping(value="/selectByName/{name}",method=RequestMethod.GET) public String selectByUserName(@PathVariable String name, ModelMap map){ if(userService.selectByName(name)==null) { return "传值未成功!"; } else { map.addAttribute("UserList2",userService.selectByName(name)); return USER_LIST2; } } @RequestMapping(value="/selectByID/{id}",method=RequestMethod.GET) public String selectByID(@PathVariable String id, ModelMap map){ if(userService.selectByID(id)==null) { return "传值未成功!"; } else { map.addAttribute("UserList2",userService.selectByID(id)); return USER_LIST2; } } /** * 获取创建UserForm表单 * @param map * @return */ @RequestMapping(value="/addUser",method=RequestMethod.GET) public String createUserForm(ModelMap map) { map.addAttribute("user", new User()); map.addAttribute("action", "addUser"); return USER_FORM; } @RequestMapping(value="/addUser",method=RequestMethod.POST) public String postUser(@ModelAttribute User user) { userService.addUser(user); return REDIRECT_TO_USER_LIST; } @RequestMapping(value="/updateByID/{id}",method=RequestMethod.GET) public String getByUserID(@PathVariable String id, ModelMap map) { if(userService.selectByID(id)==null) { return "传值未成功!"; } else { map.addAttribute("user",userService.selectByID(id)); map.addAttribute("action","updateByID"); return USER_FORM; } } @RequestMapping(value="/updateByID",method=RequestMethod.POST) public String putByUserID(@ModelAttribute User user) { userService.updateByUserID(user); return REDIRECT_TO_USER_LIST; } @RequestMapping(value="/deleteByID/{id}",method=RequestMethod.GET) public String deleteUserByID(@PathVariable String id) { userService.deleteByUserID(id); return REDIRECT_TO_USER_LIST; } }

10.程序入口及Springboot项目启动类

package com.test.user; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableAutoConfiguration public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

至此所有后端相关的类已全部定义,运行程序可通过POSTMan等API工具实现增删改查操作。(前端相关的不是很懂,尝试结合别人写的Demo做了简单页面)

A.前端相关——结构

在resource文件下建立如下文件夹及相关文件(其中UserForm1.html及UserInfoByName.html无用,为实现一些小想法做的测试);

1.static/css/default.css

/* contentDiv */ .contentDiv {padding:50px 100px;}

css模板引入?不是很懂。。。

2.image引入

此处引入的是作为标签页的logo-----> 就是这个东西lol。本文中页面没有添加图片及背景之类的,因此就引入了一张图片作为标签页图像。

3.静态页面编写

UserList.html用于列出查询的所有用户(showAll),UserForm.html页面为添加(add)、更新(updata)用户的跳转页面,UserList2.html页面用于列出根据条件查询所得用户信息的列表页面,代码基本与UserList相同——取消了几个按钮的设置。

1.UserList.html

<!DOCTYPE html> <html lang="zh-CN"> <head> <script type="text/javascript" th:src="@{https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js}"></script> <link th:href="@{https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css}" rel="stylesheet"/> <link th:href="@{/css/default.css}" rel="stylesheet"/> <link rel="icon" th:href="@{/images/205311905.jpg}" type="image/x-icon"/> <meta charset="UTF-8"/> <title>用户列表</title> </head> <body> <div class="contentDiv"> <h5><strong><font size="5"> 用户信息管理系统</font><br/></strong></h5> <form th:action="@{/user/{action}(action=${action})}" method="post" > <input name="username" class="form-control" id="user_name" type="text" value="" placeholder="请输入用户名..." /> <td><a class="btn btn-danger" th:href="@{/user/selectByName/{username}(username=${username})}">查询</a></td> </form> <div id="2" style="margin:10px"> <div align="center"> <a class="btn btn-primary" href="/user/addUser" role="button" style="margin-right:10px;">新增用户</a> </div> </div> <table class="table table-hover table-condensed"> <legend> <strong>用户列表</strong> </legend> <thead> <tr> <th>用户编号</th> <th>用户名称</th> <th>用户生日</th> <th>用户简介</th> <th>附件</th> </tr> </thead> <tbody> <tr th:each="user : ${UserList}"> <td style="width:300px;" th:text="${user.id}"></td> <th style="width:100px;" th:text="${user.name}"></th> <td style="width:120px;" th:text="${#dates.format(user.birthday,'yyyy-MM-dd')}"></td> <td style="width:350px;" th:text="${user.description}"></td> <td style="width:150px;">附件</td> <td><a class="btn btn-danger" th:href="@{/user/deleteByID/{id}(id=${user.id})}">删除</a></td> <td><a class="btn btn-danger" th:href="@{/user/updateByID/{id}(id=${user.id})}">更新</a></td> </tr> </tbody> </table> </div> </body> <body> </body> </html> <form th:action="@{/user/{action}(action=${action})}" method="post" > <input name="username" class="form-control" id="user_name" type="text" value="" placeholder="请输入用户名..." /> <td><a class="btn btn-danger" th:href="@{/user/selectByName/{username}(username=${username})}">查询</a></td> </form> <div id="2" style="margin:10px"> <div align="center"> <a class="btn btn-primary" href="/user/addUser" role="button" style="margin-right:10px;">新增用户</a> </div> </div> <table class="table table-hover table-condensed"> <legend> <strong>用户列表</strong> </legend> <thead> <tr> <th>用户编号</th> <th>用户名称</th> <th>用户生日</th> <th>用户简介</th> <th>附件</th> </tr> </thead> <tbody> <tr th:each="user : ${UserList}"> <td style="width:300px;" th:text="${user.id}"></td> <th style="width:100px;" th:text="${user.name}"></th> <td style="width:120px;" th:text="${#dates.format(user.birthday,'yyyy-MM-dd')}"></td> <td style="width:350px;" th:text="${user.description}"></td> <td style="width:150px;">附件</td> <td><a class="btn btn-danger" th:href="@{/user/deleteByID/{id}(id=${user.id})}">删除</a></td> <td><a class="btn btn-danger" th:href="@{/user/updateByID/{id}(id=${user.id})}">更新</a></td> </tr> </tbody> </table> </div> </body> <body> </body> </html>

2.UserList2.html

<!DOCTYPE html> <html lang="zh-CN"> <head> <script type="text/javascript" th:src="@{https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js}"></script> <link th:href="@{https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css}" rel="stylesheet"/> <link th:href="@{/css/default.css}" rel="stylesheet"/> <link rel="icon" th:href="@{/images/205311905.jpg}" type="image/x-icon"/> <meta charset="UTF-8"/> <title>用户列表</title> </head> <body> <div class="contentDiv"> <h5> 用户信息管理系统</h5> <table class="table table-hover table-condensed"> <legend> <strong>用户列表</strong> </legend> <thead> <tr> <th>用户编号</th> <th>用户名称</th> <th>用户生日</th> <th>用户简介</th> <th>附件</th> </tr> </thead> <tbody> <tr th:each="user : ${UserList2}"> <td style="width:300px;" th:text="${user.id}"></td> <th style="width:100px;" th:text="${user.name}"></th> <td style="width:120px;" th:text="${#dates.format(user.birthday,'yyyy-MM-dd')}"></td> <td style="width:350px;" th:text="${user.description}"></td> <td style="width:150px;">附件</td> <td><a class="btn btn-danger" th:href="@{/user/deleteByID/{id}(id=${user.id})}">删除</a></td> <td><a class="btn btn-danger" th:href="@{/user/updateByID/{id}(id=${user.id})}">更新</a></td> </tr> </tbody> </table> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <input class="btn" type="button" value="返回" onclick="history.back()" style="margin-right:60px;"/> </div> </div> </body> </html>

3.UserForm.html

<!DOCTYPE html> <html lang="zh-CN"> <head> <script type="text/javascript" th:src="@{https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js}"></script> <link th:href="@{https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css}" rel="stylesheet"/> <link th:href="@{/css/default.css}" rel="stylesheet"/> <link rel="icon" th:href="@{/images/205311905.jpg}" type="image/x-icon"/> <meta charset="UTF-8"/> <title>用户管理</title> </head> <body> <div class="contentDiv"> <h5>TEST 用户管理系统 </h5> <legend> <strong>用户管理</strong> </legend> <form th:action="@{/user/{action}(action=${action})}" method="post" class="form-horizontal"> <input type="hidden" id="user_id" name="id" th:value="${user.id}"/> <div class="form-group"> <label for="user_name" class="col-sm-2 control-label">姓名:</label> <div class="col-xs-4"> <input type="text" class="form-control" id="user_name" name="name" th:value="${user.name}" th:field="*{user.name}"/> </div> </div> <div class="form-group"> <label for="user_birth" class="col-sm-2 control-label">生日:</label> <div class="col-xs-4"> <input type="text" class="form-control" id="user_birth" name="birthday" th:value="${user.birthday}" th:field="*{user.birthday}"/> </div> </div> <div class="form-group"> <label for="user_introduction" class="col-sm-2 control-label">简介:</label> <div class="col-xs-4"> <textarea class="form-control" id="user_introduction" rows="3" name="description" th:value="${user.description}" th:field="*{user.description}"></textarea> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <input class="btn btn-primary" type="submit" value="提交" onclick="user/updateByID"/> <input class="btn" type="button" value="返回" onclick="history.back()"/> </div> </div> </form> </div> </body> </html>

UserList页面中标红的部分,原本想采用设置文本框接收输入的username值,查询相关用户信息,但实在不懂thymeleaf语法,不知怎么写,文本框传值不成功。。。其他增删改功能均正常。话不多说,效果如下图:

UserList页面,也是主页面,显示所有用户信息

点击新增用户按钮,弹出UserForm.html页面:

输入一条信息:

提交后自动返回主页:已添加新用户信息,更新、删除类似。

这里说一下按条件查询,点击查询框跳转到http://localhost:8088/user/selectByName/  这个地址,最后一个/后没有变量{username}传进来,所以页面出错:

就是上面说过的UserList中红色的那两行不知道怎么写(待指正),因此出错。但直接在url输入查询条件结果是正常的(跳转UserList2页面):

按ID查找

至此,实现了springboot+mybatis+mysql实现了简单的user增删改查的web应用。

代码已传至github(最终代码,已经整合了第二篇文章中的redis缓存):https://github.com/Anonym91/springboot-web-test

后续研究整合Redis作为缓存,HDFS作为非关系数据存储。

转载请注明原文地址: https://www.6miu.com/read-2650349.html

最新回复(0)