之前在第四次笔记中完成了;对于关联查询的情况
Mybatis框架学习笔记(4)
当然,之前的数据基本都在控制台显示,那么我想让它显示到前端的页面,怎么去完成呢;
文章目录
1.首先解决一个问题;之前忘记创建web项目;怎么把普通的文件夹标记为能被识别的web文件夹
首先得去找存放web文件的文件夹了;
啊这,之前创建这个项目的时候,没有选择是web项目,忘记了…
那么,就得手动添加创建了;
在这里添加创建
但是,目前它没在
src
目录下的main
目录
手动,搬过去,怎么说;
它的标记好像没了,变成了一个普通文件夹;
当然,为了让它和标准创建的web项目相同,我把文件夹
web
的名字改为webapp
;也用不到jsp文件,那就删掉;
那么,首先得让它恢复标记;
在文件处点击项目结构;
这两处的路径需要手动改一下;双击文件,进行修改;
结束
这时,发现项目就已经被标记好了;
当然,要部署web项目,先去配置服务器
然后,先去pom.xml文件导入需要的依赖jar坐标
<dependencies>
<!--需要的mybatis依赖jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!--数据库驱动连接的jar包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!--log4j日志包-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<!--这里的test标识,即表示它不会被打包-->
<scope>test</scope>
</dependency>
<!--导入json需要的依赖-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
在xiaozhi
包下创建servlet
包;
在前几次的整理测试时,注意到,调用公共类的这部分代码;以及调用持久层的方法;还是比较多的,
若是直接放在servlet层中去直接写的话;也是可行的;;但是在项目的整体架构上来看,这个耦合度就比较高;那么为了能尽量降低耦合度
;就得在持久层(dao数据交互访问层)
和servlet(控制层)
之间加一层(服务层service层
);就是说,让持久层和控制层尽量不要直接接触,
比如说你要去租房子;一般来说;你不会直接去和房东进行沟通的;而是去找中介,然后中介在你和房东之间进行沟通;那么,添加的这个服务层就相当于一个中介;
在xiaozhi
包下创建service
包;
2.员工查询展示,以及在搜索框输入Id后根据Id查询员工信息
OK,查询员工的话,展示比较简单;那就先做员工的查询展示;
mapper层的接口和配置文件这里就不重复去写了;
Mybatis框架学习笔记(4)–>之中有整理
先在webapp
文件夹下创建一个js
文件夹;把jquery.1.8.3.min.js
文件放入;
当然,先去创建一个简易的字符编码过滤器;
在xiaozhi
包下创建filter
包,创建EncodingFilter
,进行字符编码过滤;
package com.xiaozhi.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* @author by CSDN@小智RE0
* @date 2021-10-30 15:20
*/
public class EncodingFilter implements Filter{
String encode;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//接收初始化参数;
encode = filterConfig.getInitParameter("encode");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("字符编码过滤中.......................");
servletRequest.setCharacterEncoding(encode);
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
在webapp
下的WEB-INF
的web.xml
中配置过滤器;
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置过滤器-->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.xiaozhi.filter.EncodingFilter</filter-class>
<!--初始化参数-->
<init-param>
<param-name>encode</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/do/*</url-pattern>
</filter-mapping>
</web-app>
在service
包下创建EmployeeService
;员工类的服务层;
package com.xiaozhi.service;
import com.xiaozhi.mapper.EmployeeMapper;
import com.xiaozhi.pojo.Employee;
import com.xiaozhi.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* @author by CSDN@小智RE0
* @date 2021-10-29 21:55
* 员工类的服务层
*/
public class EmployeeService {
//查询所有的员工;
public List<Employee> getAllEmployees(){
//调用工具类;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
//调用方法;
List<Employee> allEmp = mapper.getAllEmp();
//关闭;
sqlSession.close();
//传递到控制层;
return allEmp;
}
//根据Id查询员工;
public Employee getEmpById(Integer id){
//调用工具类;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理对象;
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
//调用方法;
Employee employee = mapper.getEmpById(id);
//关闭sqlSession;
sqlSession.close();
return employee;
}
}
在servlet
包下创建EmployeeServlet
,获取前端的参数;这里会调用服务层的方法进行处理,
package com.xiaozhi.servlet;
import com.google.gson.Gson;
import com.xiaozhi.pojo.Employee;
import com.xiaozhi.service.EmployeeService;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
/**
* @author by CSDN@小智RE0
* @date 2021-10-29 21:56
* 员工管理的servlet处理
*/
public class EmployeeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("-----在员工管理请求数据---");
PrintWriter out=null;
//获取到标记参数;
String mark = req.getParameter("mark");
//查询所有的员工
if(mark.equals("empList")){
try {
//请求编码;响应解码;
resp.setContentType("text/html;charset=utf-8");
//会以流的方式返回;
out = resp.getWriter();
//这里会调用服务层进行处理;
EmployeeService employeeService = new EmployeeService();
List<Employee> allEmployees = employeeService.getAllEmployees();
//控制台输出测试;
allEmployees.forEach(System.out::println);
//不为空就发出去;
if(!allEmployees.isEmpty()){
//以json格式发送到前端页面进行响应;
out.print(new Gson().toJson(allEmployees));
}else {
out.print(0);//-->抱歉,暂时没有员工
}
} catch (IOException e) {
e.printStackTrace();
out.print(500);
}
}
//根据Id查询员工;
else if(mark.equals("getEmpById")){
try{
//请求编码;响应解码;
resp.setContentType("text/html;charset=utf-8");
//会以流的方式返回;
out = resp.getWriter();
//获取传递的Id;
String empId = req.getParameter("empId");
//这里会调用服务层进行处理;
EmployeeService employeeService = new EmployeeService();
//根据ID查询员工;
Employee emp = employeeService.getEmpById(Integer.parseInt(empId));
//控制台输出测试;
System.out.println(emp);
//不为空才发出去;
if(emp!=null){
//以Json字符串格式返回;
out.print(new Gson().toJson(emp));
}else {
out.print(0);//-->抱歉,员工不存在
}
}catch (Exception e){
e.printStackTrace();
out.print(500);
}
}
}
}
当然,还要在webapp
下的WEB-INF
的web.xml
中配置servlet;
<!--配置员工servlet-->
<servlet>
<servlet-name>empServlet</servlet-name>
<servlet-class>com.xiaozhi.servlet.EmployeeServlet</servlet-class>
</servlet>
<!--servlet映射-->
<servlet-mapping>
<servlet-name>empServlet</servlet-name>
<url-pattern>/do/emp</url-pattern>
</servlet-mapping>
在webapp
文件夹下创建index.html
,一个简易的跳转首页;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>简易首页</title>
</head>
<body>
<a href="employee.html">员工列表</a>
<a href="dept.html">部门列表</a>
</body>
</html>
员工的展示页面;
在webapp
新建的employee.html
作为员工的展示页面
这个页面就比较粗糙了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>员工列表</title>
<!--部署jquery-->
<script src="js/jquery.1.8.3.min.js" type="text/javascript"></script>
<script type="text/javascript">
//页面打开时发送请求;
$(function () {
$.get("do/emp", {mark: "empList"}, function (res) {
//测试获取的数据;
//console.log(res)
if(res==500){
alert("抱歉,服务器出了点问题");
}else if(res==0){
//弹框提示;
alert("抱歉,暂时没有员工!")
}else {
//拼接存入表格;
var str2="";
for (var i = 0; i < res.length; i++) {
str2+="<tr class='allEmpClass' align='center'>";
str2+="<td>"+(i+1)+"</td>";
str2+="<td>"+res[i].name+ "</td>";
str2+="<td>"+res[i].sex+ "</td>";
str2+="<td>"+res[i].dept.name+ "</td>";
str2+="<td>"+res[i].user.account+ "</td>";
str2+="</tr>";
}
$("#table").append(str2);
}
}, "json");
});
//点击搜索时,查询员工;
function getEmp(){
//先判断是否输入了;
var idVal = $("input[name='id']").val();
if((idVal.trim()).length==0){
alert("请输入要查询的员工Id.");
}else {
//发送请求;进行查询;
$.get("do/emp",{mark:"getEmpById",empId:idVal},function (res){
if(res==500){
alert("抱歉,服务器出了点问题");
}else if(res==0){
//清除上一次的查询信息;
$(".oneEmpClass").empty();
//弹框提示;
alert("该员工不存在!!!");
}else {
//同样地,先清除全部的信息;
$(".allEmpClass").empty();
//清除上一次的查询信息;
$(".oneEmpClass").empty();
//拼接显示数据; 注意,携带的Class为 oneEmpClass
var str4="";
str4+="<tr class='oneEmpClass' align='center'>";
str4+="<td>"+1+"</td>";
str4+="<td>"+res.name+ "</td>";
str4+="<td>"+res.sex+ "</td>";
str4+="<td>"+res.dept.name+ "</td>";
str4+="<td>"+res.user.account+ "</td>";
str4+="</tr>";
$("#table").append(str4);
}
},"json")
}
}
//点击全部员工,刷新页面;
function getAll(){
location.reload();
}
</script>
</head>
<body>
<form style="width: 1080px" id="form">
<label>
<input type="text" name="id" placeholder="请输入要查询的Id:"/>
</label>
<input type="button" value="搜索" onclick="getEmp()"/>
<!--当然为了能够调回之前的全部员工,再次加载一次这个页面-->
<input type="button" value="显示全部员工" onclick="getAll()">
</form>
<br/>
<!--显示的表格-->
<table width="100%" border="1" cellspacing="0" id="table">
<th>编号</th>
<th>员工姓名</th>
<th>员工性别</th>
<th>所属部门</th>
<th>操作人</th>
</table>
</body>
</html>
展示效果;
我在做这个显示列表时,给tr标签
都加了一个类名allEmpClass
点击搜索时,会把之前的全部内容给清空;也就是说,会把类名class为allEmpClass
的行清空;然后还在这时给查询到的显示的指定员工那行的tr标签
携带定义了一个类名class为 oneEmpClass
;
所以还要考虑到还想看全部的员工;那么我就添加了一个显示全部员工的按钮,比较粗糙了;
直接用location的刷新函数reload()
把页面重新刷新了一次,然后再次请求查询全部的员工;
然后,在查不到员工的情况的时候;
当时做的时候,考虑的是,
- 删除所有显示的员工;就是清空定义了类名class为
allEmpClass
的tr标签
;- 删除之前已经查询到的信息;也就是说,我要把之前可能查到的员工那一行信息删除掉 ;也就是类名class为
oneEmpClass
的tr标签
;- 然后在表格上显示
提示信息
的字符串;
但是,经过频繁的测试;(先查询能查到的,然后查询查不到的;…往返试试有什么bug;)就是数据会覆盖;
暂时没想到怎么解决;
所以,就先用
alert("该员工不存在!!!");
的弹框进行提示;
然后效果就是,弹框提示;
还可以删除之前查询的存在的员工数据信息;
然后,这个刷新按钮就比较普通了;哈哈
3.部门信息查询(查询显示所有部门,且显示员工信息);(根据输入框的Id查询部门的信息)
先在service
包下创建DeptService
部门类服务层;
package com.xiaozhi.service;
import com.xiaozhi.mapper.DeptMapper;
import com.xiaozhi.pojo.Dept;
import com.xiaozhi.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* @author by CSDN@小智RE0
* @date 2021-10-29 21:54
* 部门类的服务层
*/
public class DeptService {
//查询所有的部门;会包括部门的员工;
public List<Dept> getAllDept(){
//调用工具类;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理类对象;
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
//调用方法;
List<Dept> allDept = mapper.getAllDept();
//关闭sqlSession;
sqlSession.close();
return allDept;
}
//根据Id查询部门;
public Dept getDeptById(Integer id){
//调用工具类;
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取代理类对象;
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
//调用方法;
Dept deptById = mapper.getDeptById(id);
//关闭sqlSession;
return deptById;
}
}
servlet
包下创建DeptServlet
,处理数据;
package com.xiaozhi.servlet;
import com.google.gson.Gson;
import com.xiaozhi.pojo.Dept;
import com.xiaozhi.service.DeptService;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
/**
* @author by CSDN@小智RE0
* @date 2021-10-29 21:55
* 部门类的servlet层处理
*/
public class DeptServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out=null;
//获取到标记参数;
String mark = req.getParameter("mark");
//查询所有的部门;
if(mark.equals("deptList")){
try{
//请求编码;响应解码;
resp.setContentType("text/html;charset=utf-8");
//会以流的方式返回;
out = resp.getWriter();
//调用;
DeptService deptService = new DeptService();
List<Dept> allDept = deptService.getAllDept();
//控制台输出;
allDept.forEach(System.out::println);
//不为空就响应;
if(!allDept.isEmpty()){
//以json格式的字符串返回;
out.print(new Gson().toJson(allDept));
}else {
out.print(0);//->抱歉,部门不存在;
}
}catch (Exception e){
e.printStackTrace();
out.print(500);
}
}
//根据ID查询部门;
else if(mark.equals("getDeptById")){
try {
//请求编码;响应解码;
resp.setContentType("text/html;charset=utf-8");
//会以流的方式返回;
out = resp.getWriter();
//获取传递的Id,
String deptId = req.getParameter("deptId");
System.out.println("--测试->"+deptId);
//调用;
DeptService deptService = new DeptService();
Dept deptById = deptService.getDeptById(Integer.parseInt(deptId));
//若存在就响应数据;
if(deptById!=null){
//以JSon字符串的格式返回;
out.print(new Gson().toJson(deptById));
}else {
out.print(0);//->抱歉,没有部门;
}
}catch (Exception e){
e.printStackTrace();
out.print(500);
}
}
}
}
需要在WEB-INF
下的web.xml
配置servlet
<!--配置部门servlet-->
<servlet>
<servlet-name>deptServlet</servlet-name>
<servlet-class>com.xiaozhi.servlet.DeptServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>deptServlet</servlet-name>
<url-pattern>/do/dept</url-pattern>
</servlet-mapping>
刚才的员工查询是单个数据;而部门查询的话,还需要显示部门下的员工姓名;
所以在前端表格页面需要两层循环存放数据;
在webapp
文件夹下创建dept.html
,作为部门展示页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>部门列表</title>
<!--部署JQuery-->
<script src="js/jquery.1.8.3.min.js" type="text/javascript"></script>
<script type="text/javascript">
//页面加载时,就会显示所有的信息;
$.get("do/dept",{mark:"deptList"},function (res){
//测试;
//console.log(res)
if(res==500){
alert("抱歉,服务器出了点问题");
}else if(res==0){
//弹框提示;
alert("抱歉,暂时没有部门!")
}else{
//拼接字符串; 这里会为这些行加上类名信息;
//需要两层循环取到员工的姓名信息;
var str="";
for (var i = 0; i < res.length; i++) {
str+="<tr class='allDeptClass'>";
str+="<td>"+(i+1)+"</td>";
str+="<td>"+res[i].name+"</td>";
str+="<td>"+res[i].user.account+"</td>";
//遍历员工;
str+="<td>";
for (var j = 0; j < res[i].employees.length; j++) {
str+=res[i].employees[j].name +" ";
}
str+="</td>";
str+="</tr>";
}
//拼接到表格;
$("#table").append(str);
}
},"json");
//根据Id查询部门;
function getDeptById(){
//先看输入框有没有东西;
var idVal = $("input[name='id']").val();
if((idVal.trim()).length==0){
alert("请输入ID后查询")
}else {
//发送请求;包括ID;
$.get("do/dept",{mark: "getDeptById",deptId:idVal},function (res){
//测试;
console.log(res)
if(res==500){
alert("抱歉,服务器出了点问题");
}else if(res==0){
//清除上一次查询的结果;
$(".oneDeptClass").empty();
//弹框提示;
alert("抱歉,当前部门不存在");
}else{
//先清空原先的全部信息;
$(".allDeptClass").empty();
//清除上一次查询的信息;
$(".oneDeptClass").empty();
//拼接字符串; 这里赋予类名为oneDeptClass
var str2="";
str2+="<tr class='oneDeptClass'>";
str2+="<td>"+1+"</td>";
str2+="<td>"+res.name+"</td>";
str2+="<td>"+res.user.account+"</td>";
str2+="<td>";
for (var i = 0; i < res.employees.length; i++) {
str2+=res.employees[i].name +" ";
}
str2+="</td>";
str2+="</tr>";
$("#table").append(str2);
}
},"json");
}
}
//点击显示所有部门;刷新一次页面;
function getAll(){
location.reload();
}
</script>
</head>
<body>
<form style="width: 1080px" id="form">
<label>
<input type="text" name="id" placeholder="请输入要查询的Id:"/>
</label>
<input type="button" value="搜索" onclick="getDeptById()"/>
<!--当然为了能够调回之前的全部部门,再次加载一次这个页面-->
<input type="button" value="显示全部部门" onclick="getAll()">
</form>
<br/>
<table width="100%" border="1" cellspacing="0" id="table">
<th>编号</th>
<th>部门名称</th>
<th>操作人</th>
<th>部门员工</th>
</table>
</body>
</html>
显示页面
同样地,我在拼接这些表格行的时候,给他们的
tr标签
定义共同的class类名为allDeptClass
;
方便统一操作;
然后,由于一次性的查询到的部门对象中包含有员工的集合;所以要双层循环取到里面的员工姓名;
然后就是这个搜索框;
先说能查到部门的情况;
在显示数据之前,会清空class类名为
allDeptClass
的tr标签行
;也就是清空数据;
当然还要考虑到用户在连续查询两次或多次的情况;
所以还要清除之前查询的数据;
那么,在显示这个查询数据的时候,我就给他定义了class类名为oneDeptClass
;
查询的时候还会清除class类名为oneDeptClass
的tr标签行
为啥要定义类名呢?;这个;我试过定义Id,但是;这个所谓的清空其实不是清空所有,而是清空里面的内容;也就是说结构还在;要是定义Id的话,我去调用
empty()
函数清空,由于Id是唯一的;它就只能清除出现的第一个;看起来只是一行数据,其实已经不知不觉存了多行tr标签
;
其实,只是清空数据,结构还在;
多查询几次试试;
比如说我查询了三次,他那个结构就出现了三行;之前的会被存起来;
查询不到的情况;会清除之前可能查询的class类名为
oneDeptClass
的tr标签行
显示全部部门;location对象的reload()函数
刷新页面
查询这部分暂时结束;很多地方还需要优化的;
比如说我在查询时的 清空
;都是调用了empty()
函数 ;去完成清空的;
这要是数据量大的话,或者被大量地查询,会不会出现一些问题;
还有弹框的使用确实不太美观;
所以说,还要继续学习,努力提升自己的技能
OK,终于找到办法去删除表格中之前的数据了;而且不会在页面中产生冗余的类名代码;
只需要;在发出请求之前;清除页面的表格第一行之外的所有<tr>
标签内容即可
$("tr:gt(0)").remove();