第一章 整合SSM框架
整体流程原则:
先Dao层
再写Service调用Dao
做单元测试
没问题后再实现springmvc
1 整合思路
a. SSM介绍
springmvc+ spring + mybatis=ssm
mybatis 持久层的CURD
spring 业务层 IOC、DI(解耦) 和AOP(事务问题)
springMVC 表现层 MVC的操作
b. 整合使用的技术
1). Spring 5.0.2
2). mybatis 3.4.6
3). SpringMVC 5.0.2
4). log4J 日志
5). ElementUI UI
6). Vue ajax
......
c. 业务介绍
我们需要完成一张账户表的查询和修改功能
2 引入依赖和依赖分析
a. Spring相关的
1). spring-context : Spring 上下文
2). spring-tx : Spring事务
3). spring-jdbc : SpringJDBC
4). spring-test : Spring单元测试
5). spring-webmvc : SpringMVC
b. mybatis相关的
1). mybatis : mybatis核心
c. mybatis与spring整合包
1). mybatis-spring :mybatis与spring整合
d. 其他
1) 切面相关的
aspectjweaver : AOP切面
2) 数据源相关(选择使用):
c3p0
commons-dbcp
spring自带的数据源
druid : 德鲁伊
3) 单元测试相关的:
junit : 单元测试,与spring-test放在一起做单元测试
4) ServletAPI相关的
jsp-api : jsp页面使用request等对象
servlet-api : java文件使用request等对象
5) 日志相关的:
log4j2
log4j-core : log4j2核心包
log4j-api : log4j2的功能包
log4j-web : 当在Web应用中使用Log4j2或者其它日志框架时,需要确保:web应用启动时,日志组件能够被启动;web应用关闭时,日志组件能够被关闭。
slf4j-api : Simple Logging Facade for Java,为java提供的简单日志Facade。Facade门面,更底层一点说就是接口
slf4j:Simple Logging Facade for Java。 它提供了Java中所有日志框架的简单抽象。
log4j-slf4j-impl : slf4j的log4j实现类,也就是说slf4j的日志记录功能由log4j实现
log4j-jcl : 程序运行的时候检测用了哪种日志实现类现在叫Apache Common Logging
log4j
log4j: log4j 的jar包
slf4j-log4j12: log4j 通过slf4j-log4j12初始化Log4j,达到最终日志的输出
6 数据库相关的
mysql-connector-java : mysql的数据库驱动包
7) 页面表达式
JSTL : JSTL标签库必须jar包 基础功能
standard : JSTL标签库的必须jar包 进阶功能
8) 文件上传
commons-fileupload : 上传插件
commons-io : IO操作包
<dependencies>
<!--mybatis核心jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--spring的核心容器jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--Druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<!--mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--spring的jdbc操作数据库的jar包,包含spring自带数据源,jdbcTemplate-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--spring整合junit的jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--Junit测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--mybatis整合spring的jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
<!--事务管理器jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--aop切面-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
<!--日志开始-->
<!--引入日志的门脸-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
<!-- 日志工具包 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
</dependency>
<!--日志核心包-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
</dependency>
<!--web相关的功能包-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.9.1</version>
</dependency>
<!--为java做简单的日志记录-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!--slf4j的log4j实现类-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.9.1</version>
</dependency>
<!--程序运行的时候检测用了哪种日志实现类-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jcl</artifactId>
<version>2.9.1</version>
</dependency>
<!--日志结束-->
<!--springmvc的核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!-- JSTL标签库 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--servlet-api :引入servlet的功能-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--jsp-api: jsp页面的功能包 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- 文件上传 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
3 后端业务编写(Dao、Service)
3.1 表和实体类的创建
创建表
创建工程:
pom.xml:
设置为web工程:war包
添加jar包依赖
完善目录:webapp web.xml
创建pojo:
对应与数据库表的字段
3.2 Dao
创建Dao接口:
提供CRUD的四个方法:
其中:查询有两个:根据id查、查询所有
创建Mapper文件:xxxDao.xml:
完成对应方法的CRUD的SQL语句
3.3 Service
创建Service接口:
与Dao接口中的方法基本一致
接口实现类:
@Service
依赖注入dao:@Autowired
使用注入的dao层实现类对象调用Dao层的方法
3.4 配置文件
创建Spring主配置文件applicationContext.xml:
dao:
配置数据源
导入properties的数据库连接的配置文件
配置数据源
配置SQLSessionFactory(Mybatis与Spring的整合)
配置数据源
配置pojo别名
加载MyBatis的核心配置文件SqlMapConfig.xml
开启SpringIOC容器的注解扫描
扫描dao层
service:
开启SpringIOC容器的注解扫描
扫描service层
配置事务管理器:transactionManager
配置数据源
配置事务的AOP
配置CUD的事务控制*
默认
配置R的事务控制find*
只读,supports
配置事务控制与Service层方法绑定(织入):
配置切入点表达式
事务控制与Service层方法绑定
4 单元测试
引入日志log4j
导入log4j.properties
pom.xml加入依赖
单元测试:ServiceTest
测试dao与service的整合
依赖注入Service对象
以上测试通过后再编写web层即:springmvc部分
5 后端Web层和页面部分
5.1 准备部分
创建Controller的空文件添加@Controller,为了编写代码不会报错
5.2 配置部分
1 创建Springmvc配置文件
开启SpringIOC容器的注解扫描
配置SpringMVC的注解扫描(处理器映射器,处理器适配器):@ResponseBody @RequestBody @RestBody
配置视图解析器:等页面写完了再回来配
2 编写web.xml (Tomcat启动会读取web.xml)
监听ServletContext对象的创建
配置Spring配置文件加载:
当Tomcat启动时,会为每个web项目创建一个ServletContext对象,
ServletContext对象会执行加载这个Spring配置文件
配置SpringMVC的前端控制器
加载springmvc的配置文件
随着Tomcat启动,完成dispatchServlet的创建
配置拦截路径
配置编码过滤器:处理post的中文请求乱码
设置编码字符集
配置过滤路径
5.3 导入页面
将页面文件复制到webapp的目录下
编写index.html中创建超链接跳转到pages目录下的data.html
5.4 页面的ajax请求和Controller交互
页面简介:
当发送表单数据给后台时,用post
当发送非表单数据给后台时,用get
5.4.1 R(Retrieve)
当进入到页面,创建vue对象后,首先执行钩子方法findPage:发送Ajax给服务器,获取所有的账户信息,显示到界面上。
5.4.2 U (Update)
1 编辑窗口的内容回显,编辑按钮触发
findById() ——> 获取对象返回(@ResponseBody将对象转为json返回)
2 进行内容的编辑,确定按钮触发
当回显之后,用户在表单中输入新的内容,此时双向绑定到formData中,只要将formData传给后台存储即可。
5.4.3 C (Create)
5.4.4 D(Delete)
6 双向绑定
第二章 SpringMVC拦截器
1 SpringMVC拦截器
1.1 认识拦截器
- Servlet:处理Request请求和Response响应
- 过滤器(Filter):对Request请求起到过滤的作用,作用在Servlet之前,如果配置为/*可以对所有的资源访问(servlet、js/css静态资源等)进行过滤处理
- 监听器(Listener):实现了javax.servlet.ServletContextListener 接口的服务器端组件,它随Web应用的启动而启动,只初始化一次,然后会一直运行监视,随Web应用的停止而销毁
- 作用一:做一些初始化工作
- 作用二:监听web中的特定事件,比如HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控,比如统计在线人数,利用HttpSessionLisener等。
- 拦截器(Interceptor):是SpringMVC、Struts等表现层框架自己的,不会拦截jsp/html/css/image的访问等,只会拦截访问的控制器方法(Handler)。底层采用的是aop的思想
- 从配置的角度也能够总结发现:serlvet、filter、listener是配置在web.xml中的,而interceptor是配置在表现层框架自己的配置文件中的
- 在Handler业务逻辑执行之前拦截一次
- 在Handler逻辑执行完毕但未跳转页面之前拦截一次
- 在跳转页面之后拦截一次
1.2 自定义拦截器
- 实现接口HandlerInterceptor
- 重写方法:
- preHandle:handler之前执行,返回true表示放行
- postHandle:handler逻辑真正执行完成但尚未返回页面
- afterCompletion:返回页面之后
- 自定义拦截器
总体步骤:
1 编写自定义的拦截器:
MyHandlerInterceptor implements HandlerInterceptor
2 配置给springmvc
配置自定义的拦截器,使之生效
package com.itheima.interceptor;
public class MyInterceptor implements HandlerInterceptor {
//在Controller控制器中的Handler方法执行之前 执行
//返回值: true, 执行后续的请求(情况一: 执行后续的其他的拦截器; 情况二: 所有的拦截器都执行完毕并放行, 执行Handler方法)
//返回值: false, 后续的请求代码不再执行 (拦截住了)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle 执行了 ");
return true;
}
//handler逻辑真正执行完成但尚未返回页面
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle 执行了 ");
}
//返回页面之后
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion 执行了");
}
}
- springmvc.xml配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--/*只拦截当前目录,/**拦截当前目录并且当前目录下的所有子目录-->
<mvc:mapping path="/**"/>
<bean class="com.itheima.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
- handler处理请求
@Controller
@RequestMapping("default")
public class DefaultController {
@RequestMapping("gotoResult")
public String gotoResult(Model model){
System.out.println("====gotoResult===");
model.addAttribute("nowDate", new Date());
return "result";
}
}
<fieldset>
<h3>测试拦截器</h3>
<a href="${pageContext.request.contextPath}/default/gotoResult.action">点击测试拦截器</a>
</fieldset>
1.3 拦截器链
-
拦截器链执行时,拦截器链正常流程测试
- preHandle顺序执行
- postHandle倒序执行
- afterCompletion倒序执行
-
拦截器链中断流程测试
- 拦截器链中有中断时,整个链中的拦截器的postHandle都不会执行
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.itheima.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.itheima.interceptor.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
1.4 拦截器登录案例
应用案例介绍:
已登录:可以访问会员界面
未登录:拦截,进入登录页面,不能看登录成功后的页面
用户登录的拦截器:
每次新的请求都会被拦截器拦截
LoginInterceptor implement HandlerInterceptor
获取所有的请求的信息
如果请求登录:放行
如果当前用户已经登录:放行;否则都被拦截,跳转到登录界面
Controller:
login(name, password):
成功:
将登录的账户名存到session域中
重定向到另一个Controller访问界面result.jsp
失败:返回到登录页面index.jsp
- 需求
- 有一个登录页面,写一个Handler用于接收登录请求, 实现页面跳转
- 登录页面有一个提交表单的动作。需要在Controller中处理
- 判断用户名密码是否正确(zhangsan/123)
- 如果正确,向session中写入用户信息(写入用户名username),跳转到登录成功页面
- 如果不正确, 跳转到登录页面
- 开发拦截器
- 拦截用户请求,判断用户是否登录(登录页面跳转请求和登录提交请求不能拦截)
- 如果用户已经登录则放行
- 如果用户未登录则跳转到登录页面
- index.jsp 登录页面
<fieldset>
<h3>测试登录案例</h3>
<form method="post" action="${pageContext.request.contextPath}/user/login.action">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</fieldset>
- UserController
package com.itheima.controller;
@Controller
@RequestMapping("user")
public class UserController {
@RequestMapping("login")
public String login(String username, String password, HttpServletRequest request){
//模拟登录
if ("zhangsan".equals(username) && "123".equals(password)) {
System.out.println("登录成功");
request.getSession().setAttribute("username", username);
//跳转show页面, 显示数据
return "redirect:/account/findAll.action";
} else {
System.out.println("登录失败");
return "redirect:/index.jsp";
}
}
}
- AccountController
package com.itheima.controller;
@Controller
@RequestMapping("account")
public class AccountController {
@RequestMapping("findAll")
public String findAll(Model model){
model.addAttribute("nowDate", new Date() +"====查询所有账户");
return "result";
}
}
- result.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${nowDate}
</body>
</html>
- 拦截器
package com.itheima.interceptor;
public class LoginInterceptor implements HandlerInterceptor {
/*
首先判断是否登录了,如果登录了,放行,如果没有登录,跳转到登录页面
细节:
判断是否是登录请求,如果是登录请求,放行
如果不是登录请求: 判断session中是否存储了用户信息
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
//判断是否是登录请求,如果是登录请求,放行
if ("/user/login.action".equals(requestURI)) {
return true;
}
//如果不是登录请求: 判断session中是否存储了用户信息
//从session中获取用户信息
Object username = request.getSession().getAttribute("username");
if (username != null) {
return true;
} else {
//如果没有登录,跳转到登录页面
response.sendRedirect("/index.jsp");
}
return false;
}
}
- springmvc.xml
<!--拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!--资源放行-->
<!--<mvc:exclude-mapping path="/js/**"></mvc:exclude-mapping>-->
<!--<mvc:exclude-mapping path="/css/**"></mvc:exclude-mapping>-->
<!--<mvc:exclude-mapping path="/fonts/**"></mvc:exclude-mapping>-->
<bean class="com.itheima.intercetor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
2 资源放行问题
2.1 前端控制器
当前端控制器的路径拦截为/时,需要对静态资源放行
2.2 拦截器
当我们使用了拦截器的时候,需要放行静态资源,不走拦截器