2020.12.5–尚硅谷SSM高级整合
写在前面:本人是看完框神ssm框架系列,然后找的其他的ssm整合的资源来练手的,这个尚硅谷的是用eclipse写的,我觉得可以接受就练习了,需要资源的可以私信我
基本配置:
jdk 1.8
idea 2018
mysql 5.6
maven 3.6.2
tomcat 9.0.30
1,导入依赖
<dependencies>
<!--常用其他依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!--Servlet - JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
</dependencies>
2,前端框架
1,jQuery
使用下载版的
<script src="${pageContext.request.contextPath}/static/jsp/jquery-3.5.1.min.js"></script>
2,Bootstrap
使用在线cdn
<%--引入 Bootstrap,美化界面--%>
<link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
3,常用的xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
">
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper>
</mapper>
4,mybatis的逆向工程
mybatis generator
1,导入依赖
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
2,mybatis逆向工程xml文件配置
注意
- 需要注意的是xml配置文件的位置,要和pom文件是一级别的
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="DB2Tables" targetRuntime="MyBatis3">
<!--1,配置数据库连接-->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ssm_crud"
userId="root"
password="123456">
</jdbcConnection>
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!--2,指定javabean生成位置-->
<javaModelGenerator
targetPackage="com.zp.pojo"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!--3,指定sql映射文件生成位置-->
<sqlMapGenerator
targetPackage="com.zp.dao"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!--4,指定dao接口生成位置-->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.zp.dao"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!--5,table:指定每个表的生成策略-->
<table tableName="tbl_emp" domainObjectName="Employee"/>
<table tableName="tbl_dept" domainObjectName="Department"/>
</context>
</generatorConfiguration>
3,java运行文件
注意点:
- File configFile = new File(“mg.xml”);
- 这个是找到逆向工程配置文件的位置
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class bgTest {
public static void main(String[] args)throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("mg.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
4,运行
- 运行成功就能生成响应的bean,dao接口以及mapper文件了
5,测试Mapper
-
先看下生辰的Mapper文件,如果需要修改下
-
因为需要联表查询,所以要加入引用对象
-
测试使用spring的单元测试
-
导入依赖
-
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.9.RELEASE</version> <scope>test</scope> </dependency>
-
-
需要注意的是,因为导入了新的依赖,所以要在lib中引入依赖,
-
同时还要注意在spring各个依赖之间可能会因为版本问题而报错
6,spring 的单元测试
第10集:修改mybatis逆向工程所产生的mapper
1,新建两个带部门信息的查询
思考:字符集映射 result 和 association 的 区别 ;
<!--思考,id,result的区别-->
<association property="department" javaType="department">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
</association>
第11集:测试mapper
1,推荐使用spring的单元测试,可以自动注入我们需要的组件
-
原生的测试方法
- 1,创建spring IOC 容器
- 2,从容器中获取Mapper
-
使用spring 单元测试的步骤
- 1,导入spring test 依赖
- 2,使用 @ContextConfiguration 注解来创建 IOC 容器 其中的 location 方法会定位配置文件的位置; 以及使用 @RunWith 来指定使用哪种单元测试 这里使用 :@RunWith(SpringJUnit4ClassRunner.class)
- 3,3,直接@AutoWired 要使用的组件(AutoWired : spring 的自动装配)
-
批量插入
-
1,首先在配置文件中写一个可以批量插入的SqlSession,就是SqlSessionTemplate
-
<!--5,创建一个可以执行批量操作的sqlsession;这是spring 和 mybatis 整合使用的SqlSessionTemplate--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/> <constructor-arg name="executorType" value="BATCH"/> </bean>
-
第12集 :查询(采用分页)
- 1,访问index.jsp 页面
- 2,index.jsp 页面发出查询员工列表请求
- 3,EmployeeController 来接收请求,查出员工数据
- 4,来到list.jsp 页面来展示
分页查询
-
1,在pom中导入pagehelper的依赖
-
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency>
-
2,在mybatis的配置文件中加入plugins(插件)(按照分页使用文档来)
-
<!--3,分页pagehelper5--> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!--分页参数合理化--> <property name="reasonable" value="value1"/> </plugin> </plugins>
-
3,就是具体的使用方法了
13集 :使用spring单元测试测试分页请求
-
MockMvc :意思是虚拟的mvc请求,获得处理结果
-
import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.internal.DefaultShellCallback; import java.io.File; import java.util.ArrayList; import java.util.List; public class bgTest { public static void main(String[] args)throws Exception{ List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("mg.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } }
第14集 搭建分页页面
-
web路径问题
-
不以/开始的相对路径,找资源,以当前路径为基准,经常容易出现问题
-
以/开始的相对路径,找资源,以服务器路径为基准(http://localhost:3306); 需要加上项目名开始,
- http://localhost:3306/crud
-
<% /*java代码,来获取项目路径*/ pageContext.setAttribute("APP_PATH",request.getContextPath()); %>
-
使用bootstrap完成员工列表页面
-
引用bootstrap
-
<%--引入 Bootstrap,美化界面--%> <link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
-
第15集 显示分页数据
-
首先大致分三步;(使用bootstrap)
-
首先是当前页码高亮
-
点击页码跳转
-
前一页,后一页,首页,末页的逻辑实现
-
<%--2,分页栏--%> <div class="col-md-6"> <nav aria-label="Page navigation"> <ul class="pagination"> <li><a href="${APP_PATH}/emps?pn=1">首页</a></li> <c:if test="${pageInfo.hasPreviousPage}"> <li> <a href="${APP_PATH}/emps?pn=${pageInfo.pageNum-1}" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> </c:if> <c:forEach items="${pageInfo.navigatepageNums}" var="page_Num"> <c:if test="${pageInfo.pageNum== page_Num}"> <li class="active"><a href="#">${page_Num}</a></li> </c:if> <c:if test="${pageInfo.pageNum != page_Num}"> <li><a href="${APP_PATH}/emps?pn=${page_Num}">${page_Num}</a></li> </c:if> </c:forEach> <c:if test="${pageInfo.hasNextPage}"> <li> <a href="${APP_PATH}/emps?pn=${pageInfo.pageNum+1}" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </c:if> <li><a href="${APP_PATH}/emps?pn=${pageInfo.pages}">末页</a></li> </ul> </nav> </div>
第16集 使用json查询
- 原因是B/S的缺陷,如果客户端不是浏览器,相对比较麻烦
- 查询 ajax
- 1,index.jsp 页面直接发送ajax请求进行员工分页数据的查询
- 2,服务器将查出的数据,以json字符串的形式返回给浏览器
- 3,浏览器收到json字符串,可以使用js对json进行解析,使用js通过dom增删改来改变页面
- 4,返回json,实现客户端的无关性(意思就是无论客户端是什么形式,都可以正常请求和响应)
- 注意点
- 使用json(需要导入Jackson Databind 依赖)
- 、
第17集 使用ajax重新构建index首页
-
<%--引入 Bootstrap,美化界面--%> <link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <%--引入jquery:(本地引入模式)--%> <script src="${pageContext.request.contextPath}/static/js/jquery-3.5.1.min.js"></script>
-
append() 与 appendTo()
-
//append()方法执行完成以后返回的还是原来的方法 (比如下例,返回到
-
//同时需要加入要拼接到的地方(appendTo())
-
.appendTo("#emps_table tbody");
第18集 查询 使用ajax构建分页条
-
//3,解析并显示分页条 function build_page_nav(result) { //page_nav_area 要插入的地址 //ul 是li 的父元素 var ul = $("<ul></ul>").addClass("pagination"); var FirstPageLi = $("<li></li>").append($("<a></a>").append("首页").attr("href","#")); var prePageLi = $("<li></li>").append($("<a></a>").append("«")); var nextPageLi = $("<li></li>").append($("<a></a>").append("»")); var NextPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#")); //添加首页和前一页的提示 ul.append(FirstPageLi).append(prePageLi); // 取出来的是页码号 $.each(result.extend.PageInfo.navigatepageNums,function (index,item) { //index :是下标 item :是要遍历的元素 var NumLi = $("<li></li>").append($("<a></a>").append(item)); //遍历中给ul添加li页码 ul.append(NumLi); }) //添加末页和下一页的提示 ul.append(nextPageLi).append(NextPageLi); //把ul添加到nav中(nav指的是分页0) var navEle = $("<nav></nav>").append(ul); //添加要拼接到的地址 navEle.appendTo("#page_nav_area") }
-
jquery 语法,可以查看jquery的开发手册
-
attr()是用来 attr(“href”,"#") 实现超链接这样的
-
其次就是使用ajax,jquery 语法来拼接的时候,要注意整体的构成位置
第19集 查询 实现分页条的点击事件以及具体逻辑
-
1,首先要实现 页码的禁用和激活状态(即页面的效果显示)
-
链接在不同情况下可以定制。你可以给不能点击的链接添加
.disabled
类、给当前页添加.active
类。 -
if (result.extend.PageInfo.hasPreviousPage == false){ FirstPageLi.addClass("disabled"); prePageLi.addClass("disabled"); }
-
if (result.extend.PageInfo.hasNextPage == false) { nextPageLi.addClass("disabled"); NextPageLi.addClass("disabled"); }
-
if (result.extend.PageInfo.pageNum == item) { NumLi.addClass("active"); }
-
2,实现页面的动作 ,即添加点击跳转事件
-
//点击跳转 NumLi.click(function () { to_page(item); });
-
如果只是这样写的话会出现之前的数据也出现在页面上
-
修改:在点击刷新之前先清空之前的数据
-
//在页面刷新之前先清空之前的数据 $("#emps_table tbody").empty();//这是清空员工列表 $("#page_info_area").empty();//这是清空分页数据 $("#page_nav_area").empty();//这是清空分页条
-
然后是实现点击首页末页,上一页下一页
-
//为元素添加点击翻页事件 //FirstPageLi:点击跳转首页 FirstPageLi.click(function () { to_page(1); }); //prePageLi :点击跳转前一页 prePageLi.click(function () { to_page(result.extend.PageInfo.pageNum-1); }); //nextPageLi :点击跳转下一页 nextPageLi.click(function () { to_page(result.extend.PageInfo.pageNum+1); }); //NextPageLi :点击跳转到最后一页 NextPageLi.click(function () { to_page(result.extend.PageInfo.pages); });
-
最后出现的问题是 :虽然写了判断首页等禁用的逻辑,但是因为添加了点击事件,尽管是出现不能点击的提示,但是点击依然会发出请求而且分页信息也会更新,所以
-
reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。
-
在mybatis的配置文件里添加一个分页合理化,将其值设置为true
-
<!--3,分页pagehelper5--> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!--分页参数合理化--> <property name="reasonable" value="true"/> </plugin> </plugins>
-
最后直接把判断是否有末页等逻辑与点击事件结合一起,当判断没有下一页的时候直接没有点击事件,有下一页的时候才能有点击事件
-
//判断时候有下一页和末页 if (result.extend.PageInfo.hasNextPage == false) { nextPageLi.addClass("disabled"); NextPageLi.addClass("disabled"); }else{ //nextPageLi :点击跳转下一页 nextPageLi.click(function () { to_page(result.extend.PageInfo.pageNum+1); }); //NextPageLi :点击跳转到最后一页 NextPageLi.click(function () { to_page(result.extend.PageInfo.pages); }); }
第20集 实现新增
-
1,在index.jsp 页面点击“新增”
-
2,弹出新增对话框
-
3,去数据库查询部门列表,显示在对话框中
-
4,用户输入数据完成保存
-
我出现的问题,由于这里的新增是使用bootstrap的js的插件来实现的,我以为引入了bootstrap的css的cdn就完事了,但是在引入js的插件以后运行并不成功,在浏览器的调试界面显示js插件引入出现错误,于是我又返回bootstrap官网查看,在检查完js插件使用并没有任何问题,于是我再次进行调试还是出现了错误,于是我又看了下官网的教程,发现css和js插件是需要分别引入的,而且在引入js插件之前是需要把jquery的引入的
-
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) --> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script> <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 --> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
-
使用bootstrap 提供的 css样式来填充 首页新增按钮的模态框
-
<!-- 首页新增按钮的模态框 --> <div class="modal fade" id="empAddBtnModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title" id="myModalLabel">新增员工</h4> </div> <div class="modal-body"> <%--表单--%> <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-2 control-label">empName</label> <div class="col-sm-10"> <input type="text" name="empName" class="form-control" id="input_add_empName" placeholder="empName"> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">email</label> <div class="col-sm-10"> <input type="text" name="email" class="form-control" id="input_add_email" placeholder="email"> </div> </div> <%--复选框--%> <div class="form-group"> <label class="col-sm-2 control-label">gender</label> <div class="col-sm-10"> <label class="radio-inline"> <input type="radio" name="inlineRadioOptions" id="input_add_gender1" value="M" checked="checked"> 男 </label> <label class="radio-inline"> <input type="radio" name="inlineRadioOptions" id="input_add_gender2" value="F"> 女 </label> </div> </div> <%--下拉列表--%> <div class="form-group"> <label class="col-sm-2 control-label">email</label> <div class="col-sm-4"> <select class="form-control"> </select> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button type="button" class="btn btn-primary">保存</button> </div> </div> </div> </div>
第21集 实现模态框中下拉框选择部门信息
-
1,查出部门信息,显示在下拉框中
-
写一个查询部门信息的方法,并且绑定在点击新增的按钮上
-
//这里是点击新增按钮弹出模态框 $("#emp_add_btn_modal").click(function () { getDepts(); $("#empAddBtnModal").modal({ //发送ajax请求,查出部门信息,显示在下拉列表中 //弹出模态框 backdrop:"static" }); }); //查出部门信息,显示在下拉列表中 function getDepts() { $.ajax({ url:"${APP_PATH}/depts", type:"GET", success:function (result) { // console.log(result); //{code: 100, msg: "处理成功!",…} // extend: {depts: [{deptId: 1, deptName: "开发部"}, {deptId: 2, deptName: "测试部"}]} $.each(result.extend.depts,function () { var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId); optionEle.appendTo( $("#select_add_dept")); }); } }); }
-
创建部门的控制类,创建部门的service以及业务实现类,并调用查询方法
-
//DepartmentController 中写的 /* * 返回所有的部门信息 * */ @RequestMapping("/depts") @ResponseBody public Msg getDepts(){ //查出所有部门信息 List<Department> list = departmentService.getDepts(); return Msg.success().add("depts",list); }
-
DepartmentService 中没啥好写的
-
List<Department> getDepts();//就是创建一个新的方法
-
//这是DepartmentServiceImpl中的 public List<Department> getDepts() { List<Department> list = departmentMapper.selectByExample(null); return list; }
-
注意点,由于我使用的是配置文件注册的
-
<!--2,注入spring容器--> <bean id="EmployeeServiceImpl" class="com.zp.service.EmployeeServiceImpl"> <property name="employeeMapper" ref="employeeMapper"/> </bean>
-
所以要手动把部门添加到spring容器中
-
<!--2,注入spring容器--> <bean id="EmployeeServiceImpl" class="com.zp.service.EmployeeServiceImpl"> <property name="employeeMapper" ref="employeeMapper"/> </bean> <bean id="DepartmentServiceImpl" class="com.zp.service.DepartmentServiceImpl"> <property name="departmentMapper" ref="departmentMapper"/> </bean>
-
其中我最开始的时候使用的是@Service,注解的方式,爆了一个空指针的异常,具体是因为啥我现在也没有头绪
-
最后就是把得到的部门的信息在下拉框中遍历出来
-
$.each(result.extend.depts,function () { var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId); optionEle.appendTo( $("#select_add_dept")); });
-
其中在选择拼接到的地址的时候,除了**KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲select_add_dept…("#empAddBtnModal select") ,不过也是因为我们这个模态框的特殊,因为它只用了这一个下拉框,所以可以不用id
-
99,出现的新点
- 1,mybatis的逆向工程
- 2,spring 的单元测试
- 3,数据的分页显示