赞
踩
三层架构指的是持久层、业务层和Web层
SSM就是Spring Framework Spring MVC Mybatis
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接和Java POJO (Plain Old Java Objects,普通老式Java 对象)为数据库中的记录。
可以在https://mvnrepository.com搜索相关驱动
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
在pom.xml中:先在中定义版本号<mybatis.version>2.1.1</mybatis.version>,再在中粘贴上述代码,注意中版本改为${mybatis.version}。
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
注意:可能会报错Plugin ‘org.springframework.boot:spring-boot-maven-plugin:’ not found使得无法进行后续操作,可按照https://blog.csdn.net/weixin_46291251/article/details/125289383中的方法二解决。
首先连接数据库:这里选择oa数据库中的oa_emp数据表。
在entity包中新建一个User实体,并在其中添加如下代码:
这样,一个User实体便开发好了。
注意:
类型名称 | 显示长度 | 数据库类型 | Java类型 | 备注/描述 |
---|---|---|---|---|
varchar | L+N | varchar | java.lang.String | 长度根据填入的长度变化 |
CHAR | N | char | java.lang.String | 固定长度,未填满的会以空格补齐 |
TEXT | 65535 | varchar | java.lang.String | |
INTEGER | 4 | integer unsigned | java.lang.Long | |
DECIMAL | 11 | decimal | java.lang.BigDecimal | 适用于标记价格等,自定义小数位 |
DATE | 10 | date | java.sql.Date | |
TIME | 8 | time | java.sql.Time | 只包括时分秒 |
DATETIME | 19 | datetime | java.sql.Timestamp | 包括年月日时分秒 |
TIMESTAMP | 19 | timestamp | java.sql.Timestamp | 适合记录最后的编辑时间 |
YEAR | 4 | year | java.sql.Date | |
BLOB | L+N | blob | java.lang.byte[] | |
TINYINT | 3 | tinyint unsigned | java.lang.Interger | 适合标志位 |
SMALLINT | 5 | smallint unsigned | java.lang.Interger | |
MEDIUMINT | 8 | mediumint unsigned | java.lang.Interger | |
BIT | 1 | bit | java.lang.Boolean | |
BIGINT | 20 | bigint unsigned | java.math.BigInteger | |
FLOAT | 4+8 | float | java.lang.Float | +8是因为有小数位 |
DOUBLE | 22 | double | java.lang.Double | |
ID | 11 | pk(integer unsigned) | java.lang.Long | 主键,long大一点 |
这里可以使用Lombok插件简化了程序的编写:
Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。
将其添加至依赖:
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
程序中的几个@分别代表的意思如下:
修改application.properties配置如下:
注意:application.properties中的logging.level设置日志级别
注意定义时选择Interface选项。(interface也即接口,接口程序)
在该接口文件中定义功能的接口:
UserQuery类中代码如下:
// 功能:根据用户名查询用户信息并分页展示 package com.example.studymybatis.dao.query; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class UserQuery { private Integer pageNum = 1; //当前的页码 private Integer pageSize = 2; //每一页所显示的数量 private String name; //根据用户名查询 }
注意这里使用的两个注解:
具体内容如下:
<?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.example.studymybatis.dao.UserDao"> <select id="listUser" resultType="com.example.studymybatis.entity.User"> slect * from oa.oa_emp </select> <select id="listUserByName" parameterType="com.example.studymybatis.entity.query.UserQuery" resultType="com.example.studymybatis.entity.User"> select * from oa.oa_emp <where> <if test="name !=null and name !=' '"> and 'name' like concat('%',#{name},'%') </if> </where> </select> </mapper>
在service包中新建一个UserService接口,其内容与UserDao接口中的内容一致。
package com.example.studymybatis.service;
import com.example.studymybatis.entity.User;
import com.example.studymybatis.entity.query.UserQuery;
import com.github.pagehelper.PageInfo;
import java.util.List;
public interface UserService {
//查询所有用户
public List<User> listUser();
//根据用户名来查询用户,并分页展示
public PageInfo<User> listUserByName(UserQuery userQuery);
}
注意:由于listUserByName函数是根据用户名查询结果分页展示信息,因此需要将List更改为PageHelper分页插件所提供的PageInfo函数
PageHelper分页插件的引入可在pom.xml文件中引入以下依赖:
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
PageHelper分页插件具体的使用教程可见:https://zhuanlan.zhihu.com/p/344982068
再在service包中新建一个名为UserServiceImpl的UserService实现类,用于实现UserService接口。
各个步骤的详细说明如下:
implements是一个类实现一个接口用的关键字。实现一个接口,必须实现接口中的所有方法。
进行重写操作,其快捷键为Crtl+O。接口是抽象的,其中的方法不需要实现,但是对于调用这个接口的类都必须实现或者重写这个方法。
使用@Serive注解:@Service注解用于类上,标记当前类是一个service类,加上该注解会将当前类自动注入到spring容器中,不需要再在applicationContext.xml文件定义bean了。
注入UserDao层,这样就可以直接调用UserDao层里的方法:当我们在将一个类上标注@Service或者@Controller或@Component或@Repository注解之后,spring的组件扫描就会自动发现它,并且会将其初始化为spring应用上下文中的bean。 当需要使用这个bean的时候,例如加上@Autowired注解的时候,这个bean就会被创建。而且初始化是根据无参构造函数。
编写listUser()函数的返回值。
编写listUserByName(UserQuery userQuery)函数的返回值:注意这里首先需要使用PageHelper.startPage(userQuery.getPageNum(),userQuery.getPageSize())进行启动,其中的括号里为传入对象的所有参数。
在contorller包下新建一个UserContorller类,用于控制跳转。
这里有几个注意的点:
index.html文件用于定义程序运行后http://localhost/8080网页所展示的内容和形式,其应在resources/templates中创建,其中templates即专门用于存放html文件的文件夹。
注意:需提前在pom.xml文件中引入spring-boot-starter-thymeleaf依赖才能正常实现html文件页面的跳转。(Thymeleaf是一个模板引擎,主要用于编写动态页面。)
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>3.0.0</version>
</dependency>
index.html文件的结构如下:
此时直接运行会报错,报错界面如下:
*************************** APPLICATION FAILED TO START *************************** Description: Field userDao in com.example.studymybatis.service.UserServiceImpl required a bean of type 'com.example.studymybatis.dao.UserDao' that could not be found. The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true) Action: Consider defining a bean of type 'com.example.studymybatis.dao.UserDao' in your configuration. Process finished with exit code 0
网上搜索该错误解决方案,发现该问题都是由于没有添加@Mapper注解引起的,但是我在UserDao接口已经添加过@Mapper注解了。最后发现是spring-boot-starter-parent版本太高(原来是3.0.0版本)的缘故,在pom.xml文件中将其版本改为2.4.3即可成功编译运行。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
网页界面:
此时网页比较单调,若要更改页面形式和内容,可继续在index.html文件进行编写。
https://semantic-ui.com/introduction/build-tools.html
Semantic-UI是一个前端ui库
https://echarts.apache.org/zh/index.html
Apache ECharts是一个基于 JavaScript 的开源可视化图表库
这里使用Semantic-UI来尝试进行前端的UI简单开发。
首先选择一个基本表格,并复制其源代码粘贴至index.html文件的
中。<body> <div class="ui container"> <table class="ui table" style="margin-top: 40px !important;"> # 把顶部间距调至40px <thead> <tr> <th>Name</th> <th>Registration Date</th> <th>E-mail address</th> <th>Premium Plan</th> </tr> </thead> <tbody> <tr> <td>John Lilki</td> <td>September 14, 2013</td> <td>jhlilk22@yahoo.com</td> <td>No</td> </tr> <tr> <td>Jamie Harington</td> <td>January 11, 2014</td> <td>jamieharingonton@yahoo.com</td> <td>Yes</td> </tr> <tr> <td>Jill Lewis</td> <td>May 11, 2014</td> <td>jilsewris22@yahoo.com</td> <td>Yes</td> </tr> </tbody> </table> </div> </body>
程序运行结果如下,可以发现还不是很美观,可以继续引入样式和JavaScript文件。
将上面的两行代码分别粘贴至index.html文件中,同时引入jquery cdn(见https://www.bootcdn.cn/jquery/)如下所示:
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.css">
</head>
<body>
<div class="ui container">
...
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.js"></script>
</body>
运行程序,此时已经出现了一个较为美观的表格。
最后,将表格样式调整至我们需要的形式。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.css"> </head> <body> <div class="ui container"> <table class="ui table" style="margin-top: 40px !important;"> <thead> <tr> <th>id</th> <th>姓名</th> <th>性别</th> <th>工资</th> <th>入职日期</th> <th>部门id</th> <th>操作</th> </tr> </thead> <tbody> <tr> <td>John Lilki</td> <td>September 14, 2013</td> <td>jhlilk22@yahoo.com</td> <td>No</td> <td>No</td> <td>No</td> <td> <a href=" " class="ui button mini pink">编辑</a> <a href=" " class="ui button mini teal">删除</a> </td> </tr> </tbody> </table> </div> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script> <script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.js"></script> </body> </html>
在UserContorller类的index函数中传入Model接口
@GetMapping("/")
public String index(Model model, UserQuery userQuery){
PageInfo<User> userPageInfo = userService.listUserByName(userQuery);
model.addAttribute("page",userPageInfo);
return "index";
}
Model(org.springframework.ui.Model)是一个接口,包含addAttribute方法,其实现类是ExtendedModelMap。ExtendedModelMap继承了ModelMap类,ModelMap类实现了Map接口。Model通过以下方法向页面传递参数:
Model.addAttribute(String attributeName,Object attributeValue);
之后,在index.html文件中引入thymeleaf命名空间以使用thymeleaf模板:
<html lang="en" xmlns:th="http://www.thymeleaf.org">
再更改数据的获取代码:
<tbody>
<tr th:each="oa_emp : ${page.list}">
<td th:text="${oa_emp.id}">John Lilki</td>
<td th:text="${oa_emp.name}">September 14, 2013</td>
<td th:text="${oa_emp.gender}">jhlilk22@yahoo.com</td>
<td th:text="${oa_emp.salary}">No</td>
<td th:text="${oa_emp.hire_date}">No</td>
<td th:text="${oa_emp.dept_id}">No</td>
<td>
<a href=" " class="ui button mini pink">编辑</a>
<a href=" " class="ui button mini teal">删除</a>
</td>
</tr>
</tbody>
由于是分页显示数据,因此再加上页码栏用于实现页码跳转:
<div class="ui attached segment" > <table class="m-mobile-wide" width="425px"> <tbody> <tr align="center"> <td> <a th:href="@{/(pageNum=${page.pageNum}-1)}" class="ui button basic mini" th:unless="${page.isFirstPage}">上一页</a> </td> <td> 第 <h8 th:text="${page.pageNum}">2</h8> 页/共 <h8 th:text="${page.pages}">4</h8> 页 共 <h8 th:text="${page.total}">29</h8> 条 </td> <td> <form name="pageForm" th:action="@{/}" method="get"> <div class="ui mini input "> <input type="text" class="m-bg" name="pageNum" placeholder="页码" style="width: 50px!important; height: 27.76px!important;" required> <button type="submit" style="font-size: 11px!important;width: 30px!important; height: 0px!important; border: none;margin: 5px;padding: 0;" class="button mini"> 跳转 </button> </div> </form> </td> <td> </td> <td style="float: right"> <a th:href="@{/(pageNum=${page.pageNum}+1)}" class="ui button basic mini " style="float: right;" th:unless="${page.isLastPage}">下一页</a> </td> </tr> </tbody> </table> </div>
运行程序,结果如下:
在UserContorller类中新建一个listUserByName方法:
@PostMapping("/")
public String listUserByName(Model model,UserQuery userQuery){
PageInfo<User> userPageInfo = userService.listUserByName(userQuery);
model.addAttribute("page",userPageInfo);
return "index";
}
这里@PostMapping注解是用于处理post请求。
在index.html文件中增加一个form表单用于显示搜索框和获取UserQuery中所定义的name参数值。
<div>
<form th:action="@{/}" method="post">
<input type="text" name="name" placeholder="输入用户名进行查找">
<input type="submit" value="搜索">
</form>
</div>
运行程序,结果如下:
先在index页面中添加一个“新增”按钮,再在UserDao接口中定义一个新增用户功能的持久化方法。
…
在UserServiceImpl的UserService实现类中添加接口实现方法
…
有人看到话后面再写。
在UserDao接口中定义一个删除用户功能的持久化方法。
//根据用户id删除用户
public int deleteUserById(Integer id); //传入的参数是被删除的id,故是int类型
再在UserMapper.xml文件中编写删除用户的SQL语句。
<delete id="deleteUserById" parameterType="int">
delete from oa.oa_emp where id=#{id}
</delete>
在UserService接口文件中增加删除方法,并在名为UserServiceImpl的UserService实现类中Crtl+O进行实现。
//根据用户id删除用户
public boolean deleteUserById(Integer id); //希望得到的结果是是否被删除,故是boolean类型
@Override
public boolean deleteUserById(Integer id) {
int i = userDao.deleteUserById(id);
if (i > 0){
return true; //删除成功
}else {
return false;
}
}
在UserContorller文件下添加关于用户删除的代码:
@GetMapping("/delete/{id}") //网页路径
public String delete(@PathVariable("id") Integer id, RedirectAttributes attributes){
boolean b = userService.deleteUserById(id);
if (b){
attributes.addFlashAttribute("message","删除用户成功");
return "redirect:/"; //重定向到/页面
}else {
attributes.addFlashAttribute("message","删除用户失败");
return "redirect:/"; //重定向到/页面
}
}
再在首页文件中找到删除按钮对应的代码。修改为如下代码:
<a th:href="@{/delete/{id}(id=${oa_emp.id})}" class="ui button mini teal">删除</a>
运行程序,可以删除,但是并没有提示"删除用户成功"这个消息界面出现,此时应在首页文件中继续添加
<div class="ui success message" th:unless="${#strings.isEmpty(message)}">
<i class="close icon"></i>
<div class="header">提示:</div>
<p th:text="${message}"></p>
</div>
<script>
$(".message .close").on('click',function () {
$(this).closest(".message")
.transition("fade");
})
</script>
这样,再执行程序,并点击删除按钮即可以完成从数据库中删除数据的功能,且在页面下方会出现消息提示框。
首先在templates文件夹下新建一个用于编辑和新增用户的editUser.html文件并修改
<div class="ui container"> <form class="ui form" action="" method="post" style="margin-top: 80px !important;" th:object="${user}"> <div class="field"> <label>用户名</label> <input type="text" name="name" placeholder="请输入用户名" required th:value="*{name}"> </div> <div class="field"> <label>性别</label> <input type="text" name="gender" placeholder="请输入性别" required th:value="*{gender}"> </div> <div class="field"> <label>工资</label> <input type="text" name="salary" placeholder="请输入工资" th:value="*{salary}"> </div> <div class="field"> <label>入职日期</label> <input type="text" name="hire_date" placeholder="请输入入职日期" th:value="*{hire_date}"> </div> <div class="field"> <label>部门id</label> <input type="text" name="dept_id" placeholder="请输入部门id" th:value="*{dept_id}"> </div> <button class="ui button" type="submit">提交</button> </form> </div>
在UserDao接口文件中定义一个根据用户id查询用户的方法,并在UserMapper.xml文件中编写删除用户的SQL语句。
//根据用户id查询用户
public User queryUserById(Integer id);
<select id="queryUserById" parameterType="int" resultType="com.example.studymybatis.entity.User">
select * from oa.oa_emp where id=#{id}
</select>
在UserService接口文件中增加根据用户id查询用户的方法,并在名为UserServiceImpl的UserService实现类中Crtl+O进行实现。
//根据用户id查询用户
public User queryUserById(Integer id);
@Override
public User queryUserById(Integer id) {
return userDao.queryUserById(id);
}
然后在UserContorller文件下添加关于根据用户id查询用户的代码:
@GetMapping("/edit/{id}")
public String toEdit(@PathVariable Integer id, Model model){
model.addAttribute("user",userService.queryUserById(id));
return "editUser";
}
再在首页文件中找到编辑按钮对应的代码。修改为如下代码:
<a th:href="@{/edit/{id}(id=${oa_emp.id})}" class="ui button mini pink">编辑</a>
这样,即可通过点击编辑按钮进入修改用户界面,且显示了原本的值:
但此时修改后点击提交会报错,这是因为提交按钮还没有添加处理事件,且还没有写编辑过程的代码。
在UserDao接口文件中定义一个修改用户的方法,并在UserMapper.xml文件中编写更新用户的SQL语句。
//修改用户
public int updateUser(User user);
<update id="updateUser" parameterType="com.example.studymybatis.entity.User">
update oa.oa_emp
set name = #{name}, gender=#{gender},salary=#{salary},hire_date=#{hire_date},dept_id=#{dept_id}
where id=#{id};
</update>
在UserService接口文件中增加编辑用户的方法,并在名为UserServiceImpl的UserService实现类中Crtl+O进行实现。
//修改用户
public boolean updateUser(User user);
@Override
public boolean updateUser(User user) {
int i = userDao.updateUser(user);
if (i > 0){
return true;
}else {
return false;
}
}
在UserContorller文件下添加关于用户更新的代码:
@PostMapping("/edit")
public String edit(User user,RedirectAttributes attributes){
boolean b = userService.updateUser(user);
if (b){
attributes.addFlashAttribute("message","更新用户成功");
return "redirect:/"; //重定向到/页面
}else {
attributes.addFlashAttribute("message","更新用户失败");
return "redirect:/"; //重定向到/页面
}
}
再在editUser.html文件中添加如下代码:
<form class="ui form" th:action="@{/edit}" method="post" style="margin-top: 80px !important;" th:object="${user}">
<input type="hidden" th:value="*{id}" name="id">
运行程序,此时就可以修改用户信息了。
@Mapper // 使用这个注解表示这是一个mybatis的mapper类 @Component // 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注 @Repository // 用于dao层 用于标注数据访问组件,即dao层 @Servico // 用于标注业务层组件 @Controller // 用于标注控制层组件(如struts中的action) // 以上四个注解的作用都是将相应的类注入到spring容器中 @GetMapping //处理get请求 @PostMapping //处理post请求 @PutMapping //处理put请求 @DeleteMapping //处理delete请求 @PostMapping(value = “/user/login”) //等价于 @RequestMapping(value = “/user/login”,method = RequestMethod.POST)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。