SpringMvc入门【一】
什么是SpringMvc
SpringMVC是一个基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于Spring Framework的后续产品,已经融合在Spring Web Flow中。
它解决WEB开发中常见的问题(参数接收、文件上传、表单验证、国际化等等),而且使用简单,与Spring无缝集成。支持RESTful风格的URL请求。
一、三层架构和MVC设计模式
a、三层架构
web层-- 表现层: 处理用户的请求和相应
技术:servlet
service层:业务层, 编写业务,处理业务逻辑,编写事务
技术:spring
dao层:持久层,数据的增删改查
技术:jdbc -- dbutils -- jdbcTemplate -- mybatis(主流) -- spring data jpa(趋势)
b、mvc设计模式
M:model --模型: pojo类,封装数据 , 广义上说:dao + service + model = 业务模型层
V:view -- 视图: jsp,html,freemarker:展示数据, 广义上讲:只要能展示数据就是视图
C:cotroller --控制层:servlet :处理用户的请求和相应
二、springMVC的概念
1. springMVC是spring体系中的一个子项目
2. springMVC是开源的轻量级框架
3. springMVC是满足了mvc设计的模式的一个表现层框架
4. 表现层框架大多都满足了MVC设计模式
三、SpringMVC的HelloWorld
1、引入依赖
<!--spring的核心-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--springMVC的jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<!--
maven 项目执行分为三个阶段
编译(需要) 测试(需要) 运行(不需要)
provided : 编译器生效,测试生效,运行不生效
servlet-api ,jsp-api:这两个包,需要配置依赖范围为provided ,其他都不需要
-->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
2、spring-mvc.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解,扫描包-->
<context:component-scan base-package="com.torlesse"></context:component-scan>
</beans>
3、web.xml配置
<!--配置servlet:前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--servlet中配置局部参数:读取配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
4、自定义核心控制类
@Controller
public class TestController {
@RequestMapping("/test")
public void test(){
System.out.println("helloWorld--测试成功");
}
}
5、页面配置
<a href="${pageContext.request.contextPath}/test">请求1</a>
<a href="/test">请求2</a>
四、入门案例的执行过程及原理分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V1xAYytR-1687704016020)(assets/1537855023082.png)]
五、@RequestMapping注解
1. @RequestMapping 请求路径映射,该注解可以标记在方法上,也可以标记在类上
标记在类上用来窄化路径
2. 属性
path:指定请求路径,别名value,所以属性名可以省略
method: 请求方式:
get: 路径和超链接请求都是get请求
post: 必须在表单中实现
params:声明请求路径的规则 -- 了解
"name":路径中必须有name
"age>20":路径中必须有age>20
"!name" :路径中不存在name
六、参数的绑定
1. 表单中提交的name值与方法中的参数(简单类型)名称一致,就可以直接获取到
2. 方法的参数:pojo类型
只要保证表单提交的name值与pojo的属性名一致,就可以封装数据
3. @RequestParam:请求参数绑定,name与参数名不一致
属性: value, name可以指定页面表单中的name值
requird: 是否必须的 , false ,不必要的(可有可无), true:必须有该参数
defaultValue: 默认值,如果页面传参了,则使用页面传参的值,如果没有指定,则使用默认值
4. 特殊情况:(自定义类型转换器)要转换类型是Date类型
1)自定义类型转换类
/**
*
* 自定义类型转换器
* 将字符串格式转换为日期格式
* 1. 实现接口converter<S,T>
* S:源类型 -- String
* T:目标类型-- Date
*/
public class StringToDateConverter implements Converter<String ,Date>{
/**
* 类型转换方法
* @param source 源
* @return 目标
*/
@Override
public Date convert(String source) {
//日期类型的转换对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Date date = null;
try {
date = sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
2. 在springmvc.xml文件中配置类型转换工厂
<!--类型转换工厂-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.torlesse.converter.StringToDateConverter"></bean>
</set>
</property>
</bean>
3. 在注解驱动中引入类型转换工厂
<!--注解驱动: 关联类型转换工厂-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
八、编码过滤器(重点)
<!--编码过滤器-->
<filter>
<filter-name>CharactorEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--配置初始化参数,指定编码格式:拦截的是post请求-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<!--
指定请求编码格式和相应编码格式: 了解,一般不用指定
-->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharactorEncoding</filter-name>
<!--拦截所有的请求:不包含静态资源的-->
<url-pattern>/*</url-pattern>
</filter-mapping>
SpringMvc入门【二】
一、ModelAttribute和SessionAttribute注解的使用
a. @ModelAttribute标记在方法上
特点:当执行控制器中任何一个方法时,都会先执行@ModelAttribute标记的方法
缺点:慎重使用,因为执行控制器中任何一个方法时,都会先执行@ModelAttribute标记的方法, 效率太低
UserUpdateController
UserQueryController
b. 用法一
@ModelAttribute
public User findById(Integer id){
User user = new User();
user.setUsername("王五");
user.setSex("女");
return user;
}
/**
* update user set username = ? ,sex = ? where id = ?
* @ModelAttribute:在执行控制器中任何一个方法时,都会先执行
* findById方法返回一个User对象
* 判断参数user中的属性是否为null,如果为null,则使用findById的方法返回值中的数据覆盖
* @param user
* @return
*/
@RequestMapping(value = "/testUpdate",method = RequestMethod.POST)
public String testUpdate(User user){
System.out.println(user);
System.out.println("更新");
return "show";
}
c.方法二:
@ModelAttribute
public void findById(Integer id, Map<String ,Object> map){
User user = new User();
user.setUsername("王五");
user.setSex("女");
map.put("aa",user);
}
@RequestMapping(value = "/testUpdate",method = RequestMethod.POST)
public String testUpdate(@ModelAttribute("aa") User user){
System.out.println(user);
System.out.println("更新");
return "show";
}
d. 注解@SessionAttributes:在session范围内存储对象
1) @SessionAttributes({"username","password"}) 在类上标记该注解
在session范围可以存储这两个变量名
2) /**
* 把用户名和密码存入到Session范围内
*/
@RequestMapping("/testPut")
public void testPut(Model model){
model.addAttribute("username","zhangsan");
model.addAttribute("password","123456");
}
3) /**
* 获取session范围内的对象
*/
@RequestMapping("/testGet")
public void testGet(ModelMap modelMap){
Object username = modelMap.get("username");
System.out.println(username);
Object password = modelMap.get("password");
System.out.println(password);
}
4) /**
* 清空session
* @param sessionStatus
*/
@RequestMapping("/testClear")
public void testClear(SessionStatus sessionStatus){
sessionStatus.setComplete();
}
二、RestFul风格
a. rest 是一种编程风格
b. 满足了rest风格的网站就是restful风格
c. 只是一种规范,不是规则
d. 根据id获取一个用户: /user/findById?id=1 restful风格:/user/operate/1 使用get方式提交
根据id删除一个用户:/user/delById?id=1 restful风格:/user/operate/1 使用delete方式提交
更新一个用户:/user/update?id=1&username=zzz restful风格:/user/operate/1 使用put方式提交
添加一个用户:/user/save?id=1&username=zzz restful风格:/user/operate 使用post方式提交
e. 根据id获取
页面
http://localhost:8080/user/operate/1
方法
/**
* 根据id查询
* @param id
* @return
*/
@RequestMapping(value = "/operate/{id}",method = RequestMethod.GET)
public String findById(@PathVariable("id") Integer id){
System.out.println("findById:"+id);
return "show";
}
f. 添加一个用户
页面
<%--请求保存用户--%>
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<input type="submit" value="提交">
</form>
方法
/**
* 保存用户
* @param id
* @return
*/
@RequestMapping(value = "/operate/{id}" , method = RequestMethod.POST)
public String save(@PathVariable("id") Integer id){
System.out.println("save:" + id);
return "show";
}
h. 更新用户
页面:
<%--请求更新用户--%>
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<%--要使用put,delete提交方式
1) 在web.xml开启put和delete提交方式
2) 表单的提交方式必须post
3) 表单中必须设置一个隐藏域 name=_method value=PUT
4) 请求的方法返回值必须以流的形式返回,在方法上标记注解:@ResponseBody
流的形式返回: response.getWriter().print()
--%>
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="更新">
</form>
方法
/**
* 更新用户
* @param id
* @return
*/
@RequestMapping(value = "/operate/{id}" , method = RequestMethod.PUT)
@ResponseBody
public String update(@PathVariable("id") Integer id){
System.out.println("update:" + id);
return "show";
}
i. 删除用户
页面
<%--请求删除用户--%>
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="删除">
</form>
方法
/**
* 删除用户
* @param id
* @return
*/
@RequestMapping(value = "/operate/{id}" , method = RequestMethod.DELETE)
@ResponseBody
public String delById(@PathVariable("id") Integer id){
System.out.println("delById:" + id);
return "show";
}
j, web.xml
<!--开启另外两种提交方式:put, delete-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三、控制器方法的返回值
1、返回值为void类型
a. 方法一:
@RequestMapping("/testVoid")
public void testVoid(){
System.out.println("测试没有返回值");
//因为没有指定返回值页面,会自动截取请求路径,进入视图解析器,拼接完整的路径
//可以对应的路径下创建对应的jsp页面
}
b. 方法二:response重定向
@RequestMapping("/testVoid2")
public void testVoid2(HttpServletResponse response){
System.out.println("测试没有返回值");
try {
//重定向不能进入web-inf路径
//转发可以进入web-inf路径
response.sendRedirect("/index.jsp");
} catch (IOException e) {
e.printStackTrace();
}
}
c. 方法二:servlet转发
@RequestMapping("/testVoid3")
public void testVoid3(HttpServletResponse response, HttpServletRequest request){
System.out.println("测试没有返回值");
try {
request.getRequestDispatcher("/WEB-INF/show.jsp").forward(request,response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
2、返回值为String类型(常用)
a. 默认的情况:转发请求,返回值直接进入视图解析器,拼接前缀和后缀,完整的路径
/**
* 方法的返回值为String类型
* 返回值直接进入视图解析器,拼接前缀和后缀,完整的路径
* @return
*/
@RequestMapping("/testReturnString")
public String testReturnString(){
return "show";
}
b. 请求重定向
/**
* 执行保存操作-- 重新查询 : save -- redirect:findAll
*
* 方法的返回值为String类型
* 返回值直接进入视图解析器,拼接前缀和后缀,完整的路径
* redirect:重定向, 不能进入web-inf
* redirect:添加了redirect后则不会进入视图解析器,需要配置完整的路径
* @return
*/
@RequestMapping("/testReturnString2")
public String testReturnString2(){
return "redirect:/index.jsp";
}
c. 请求转发
/**
* forward: 转发,不会进入视图解析器,需要配置完整的路径
* @return
*/
@RequestMapping("/testReturnString3")
public String testReturnString3(){
return "forward:/index.jsp";
}
3、返回值为ModelAndView类型(常用)
a. ModelAndView: Model 模型:封装数据 view 视图: 指定页面 ---> 模型和视图
b. /**
* 返回值类型为ModelAndView,包含数据和视图页面
* @return
*/
@RequestMapping("/testReturnModelAndView")
public ModelAndView testReturnModelAndView(){
//准备数据--数据库查询
List<User> userList = new ArrayList<>();
User user = new User();
user.setUsername("zhangsan");
user.setSex("男");
user.setId(2);
User user1 = new User();
user1.setUsername("zhangsan1");
user1.setSex("女");
user1.setId(1);
userList.add(user);
userList.add(user1);
ModelAndView modelAndView = new ModelAndView();
//添加数据
modelAndView.addObject("userList",userList);
//指定页面
modelAndView.setViewName("show");
return modelAndView;
}
四、交互JSON数据
1. 引入依赖
<!--引入json的依赖-->
<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>
b. ReqeustBody注解
@RequestMapping("/testRequestJson")
public void testRequestJson(String username ,Integer age){
System.out.println(username);
System.out.println(age);
}
/**
* @RequestBody: 可以把所有参数转换为字符串
* @param body
*/
@RequestMapping("/testRequestJson2")
public void testRequestJson2(@RequestBody String body){
System.out.println(body);
}
$.ajax({
url:"${pageContext.request.contextPath}/user/testRequestJson2",
data:{"username":"zhangsan","age":20},
type:"post",
dataType:"json",
success:function(data){
}
});
c. ResponseBody注解
/**
* @ResponseBody :标记了@ResponseBody注解的方法,数据会以流的方式返回
* @return
*/
@RequestMapping("/testResponseBody")
@ResponseBody
public List<User> testResponseBody(){
List<User> userList = new ArrayList<>();
User user = new User();
user.setUsername("zhangsan");
user.setSex("男");
user.setId(2);
User user1 = new User();
user1.setUsername("zhangsan1");
user1.setSex("女");
user1.setId(1);
userList.add(user);
userList.add(user1);
return userList;
}
$.ajax({
url:"${pageContext.request.contextPath}/user/testResponseBody",
data:{},
type:"post",
dataType:"json",
success:function(data){
alert(data[0].username);
alert(data[1].username);
}
});
d. 引入静态资源后,必须静态资源放行
<!--对静态资源放行
把js下的静态资源映射到js目录下
-->
<mvc:resources mapping="/js/*" location="/js/"></mvc:resources>
五、SpringMVC实现文件上传
1、文件上传
a、引入依赖
引入fileUpload会自动依赖commons-io
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
b、spring-mvc.xml 配置文件
<!-- 配置文件上传解析器 -->
<!-- id的值是固定的-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
c、页面配置
<%--
上传文件的表单前提
1) 提交方式必须是post
2) 表单的类型必须:multipart/form-data, 多功能表单数据
3) 必须有一个type=file的表单元素
--%>
<form action="${pageContext.request.contextPath}/user/upload" method="post" enctype="multipart/form-data">
<input type="text" name="username"> <br>
<input type="file" name="upload"><br>
<input type="submit" value="上传">
</form>
d、controller代码
/**
* 声明参数 变量接收数据
*
*/
@RequestMapping("/upload")
public String upload(String username , MultipartFile upload, HttpServletRequest request){
// System.out.println(username);
//1. 目标路径
//获取项目运行的路径
String realPath = request.getSession().getServletContext().getRealPath("/upload");
//判断该路径是否存在
File realFile = new File(realPath);
if(!realFile.exists()){
realFile.mkdirs();
}
//2. 获取唯一的文件名称(包含扩展名)
String uuidName = UUID.randomUUID().toString().replace("-", "");
//获取扩展名: 获取文件名
//获取真实的文件名
String originalFilename = upload.getOriginalFilename();
//截取字符串,获取文件的扩展名
String extendName = originalFilename.substring(originalFilename.lastIndexOf("."));
System.out.println(extendName);
//唯一的文件名
String fileName = uuidName + extendName;
System.out.println(fileName);
//文件上传
//transferTo: 执行文件上传
//参数file:目录文件
try {
upload.transferTo(new File(realFile, fileName));
} catch (IOException e) {
e.printStackTrace();
}
return "show";
}
2、跨服上传
a、引入依赖
<!--引入jersey服务器的包-->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
b、修改tomcat配置
1. tomcat默认不能跨服上传的
2. tomcat/conf/web.xml
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<!--需要添加的-->
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
c、配置图片服务器
1. 创建一个web项目
2. 配置一个tomcat,与原来tomcat端口号不一致
3. 在webapp目录下创建一个upload目录,空的文件夹不会编译,需要在upload目录添加(任意)一个文件
d、修改controller代码
/**
* 声明参数 变量接收数据
*
*/
@RequestMapping("/uploadServer")
public String uploadServer(String username , MultipartFile upload, HttpServletRequest request){
//1. 配置图片服务器的路径
String serverPath = "http://localhost:9090/img_server/upload/";
//2. 获取唯一的文件名称(包含扩展名)
String uuidName = UUID.randomUUID().toString().replace("-", "");
//获取扩展名: 获取文件名
//获取真实的文件名
String originalFilename = upload.getOriginalFilename();
//截取字符串,获取文件的扩展名
String extendName = originalFilename.substring(originalFilename.lastIndexOf("."));
System.out.println(extendName);
//唯一的文件名
String fileName = uuidName + extendName;
System.out.println(fileName);
//获取jersey服务器客户端
Client client = Client.create();
//配置上传路径的资源对象
WebResource resource = client.resource(serverPath + fileName);
//上传
//参数:资源的类型
//文件的字节内容
try {
resource.put(String.class,upload.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
return "show";
}
六、SpringMVC的统一异常处理
1. 自定义异常类
public class CustomException extends Exception {
private String message;
public CustomException(String message) {
super(message);
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2. 定义异常的统一处理对象--实现接口:HandlerExceptionResolver
/**
* 自定义的异常统一处理对象
*
* @author 黑马程序员
* @Company http://www.ithiema.com
* @Version 1.0
*/
//创建该类的对象
@Component
public class MyExceptionResolver implements HandlerExceptionResolver {
/**
* 解析异常
* @param request
* @param response
* @param handler
* @param e 其他模块传过来的异常对象
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
ModelAndView modelAndView = new ModelAndView();
//添加数据
//instanceof: 实例类型判断运算符
if(e instanceof CustomException){
//强制转换
CustomException customException = (CustomException) e;
modelAndView.addObject("message",customException.getMessage() );
}else{
modelAndView.addObject("message","系统错误,请联系管理员!!!");
}
//指定页面
modelAndView.setViewName("error");
return modelAndView;
}
}
3. 错误页面
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${message}
</body>
</html>
SpringMvc入门【三】
一、整合SSM
1、整合思路
a. SSM介绍
springmvc+ spring + mybatis=ssm
mybatis 持久层的CURD
spring 业务层 IOC、DI(解耦) 和AOP(事务问题), ssm 综合练习中:aop解决日志问题
springMVC 表现层 MVC的操作
b. 整合使用的技术
1). Spring 5.0.2
2). mybatis 3.4.5
3). SpringMVC 5.0.2
4). log4J2 2.9.1
5). bootstrap 3.3.5
6). jquery 1.9.1
......
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核心
2). mybatis-spring :mybatis与spring整合
3) 切面相关的
aspectjweaver : AOP切面
4) 数据源相关(选择使用):
c3p0
commons-dbcp
spring自带的数据源
5) 单元测试相关的:
junit : 单元测试,与spring-test放在一起做单元测试
6) ServletAPI相关的
jsp-api : jsp页面使用request等对象
servlet-api : java文件使用request等对象
7) 日志相关的:
log4j-core : log4j2核心包
log4j-api : log4j2的功能包
log4j-web : web项目相关日志功能
slf4j-api : 另外一种日志包,
slf4j:Simple Logging Facade for Java为java做简单的日志记录此处和log4j一起
log4j-slf4j-impl : slf4j的log4j实现类,也就是说slf4j的日志记录功能由log4j实现
log4j-jcl : 程序运行的时候检测用了哪种日志实现类现在叫Apache Common Logging
8) 数据库相关的
mysql-connector-java : mysql的数据库驱动包
ojdbc.jar : oracle的驱动jar包
9) 页面表达式
JSTL : JSTL标签库必须jar包 基础功能
standard : JSTL标签库的必须jar包 进阶功能
10) 文件上传
commons-fileupload : 上传插件
commons-io : IO操作包
3、表和实体类的创建
1. 表
2. 实体类
public class Account {
private Integer id;
private String name;
private Float money;
}
4、Dao层的编写
a、引入依赖
<!--mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
b、接口编写
package com.torlesse.dao;
import com.torlesse.domain.Account;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface AccountDao {
/**
* 查询所有
* @return
*/
@Select("select * from account")
public List<Account> findAll();
/**
* 根据id查询
* @param id
* @return
*/
@Select("select * from account where id = #{id}")
public Account findById(Integer id);
/**
* 保存账户
* @param account
*/
@Insert("insert into account values(null ,#{name},#{money})")
public void save(Account account);
/**
* 更新账户
* @param account
*/
@Update("update account set name = #{name},money=#{money} where id = #{id}")
public void update(Account account);
/**
* 删除一个账户
* @param id
*/
@Delete("delete from account where id = #{id}")
public void del(Integer id);
}
c、配置文件
<?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>
<!--引入数据的属性文件-->
<properties resource="jdbc.properties"></properties>
<!--数据库的环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--映射配置文件:指定持久层接口的包路径-->
<mappers>
<package name="com.torlesse.dao"></package>
</mappers>
</configuration>
d、测试
package com.torlesse;
import com.torlesse.dao.AccountDao;
import com.torlesse.domain.Account;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class TestDao {
@Test
public void test(){
// 配置文件的输入流对象
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("SqlMapConfig.xml");
// session工厂对象
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取一个SqlSession对象
SqlSession sqlSession = sessionFactory.openSession();
// 获取动态代理对象
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
// 执行方法
List<Account> accountList = accountDao.findAll();
// 遍历结果
for (Account account : accountList) {
System.out.println(account.getName());
}
// 释放资源
sqlSession.close();
}
}
e. spring 与mybatis整合操作
1)添加依赖
<!--整合mybatis与spring需要的jar包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!--spring的核心-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
2) 删除了SqlMapConfig.xml
3) 添加一个applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--引入数据库外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--创建数据源对象-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--创建sqlSessionFactory对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入数据源对象-->
<property name="dataSource" ref="dataSource"></property>
<!--配置方法一:引入SqlMapConfig.xml文件-->
<!--<property name="configLocation" value="classpath:SqlMapConfig.xml"></property>-->
<!--配置方法二-->
<!--别名映射-->
<!--<property name="typeAliasesPackage" value="com.torlesse.domain"></property>-->
<!--可以注入其他的属性-->
<!--<property name="configurationProperties" value=""></property>-->
</bean>
<!--扫描dao层接口的包, 创建动态代理对象, 存入到spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--需要指定dao层接口的包名-->
<property name="basePackage" value="com.torlesse.dao"></property>
</bean>
</beans>
4) 测试
@Test
public void testMybatisWithSpring(){
//创建spring容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取容器中的对象
AccountDao accountDao = ac.getBean(AccountDao.class);
//执行方法
List<Account> accountList = accountDao.findAll();
//遍历结果
for (Account account : accountList) {
System.out.println(account.getName());
}
}
5、Service层编写
a、引入依赖
<!--spring的核心-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--事务相关-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--aop的切面相 关-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<!--spring 的测试包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
b、接口编写
package com.torlesse.service;
import com.torlesse.domain.Account;
import java.util.List;
public interface AccountService {
/**
* 查询所有
* @return
*/
public List<Account> findAll();
/**
* 根据id查询
* @param id
* @return
*/
public Account findById(Integer id);
/**
* 保存账户
* @param account
*/
public void save(Account account);
/**
* 更新账户
* @param account
*/
public void update(Account account);
/**
* 删除一个账户
* @param id
*/
public void del(Integer id);
}
c、实现类编写
package com.torlesse.service.impl;
import com.torlesse.dao.AccountDao;
import com.torlesse.domain.Account;
import com.torlesse.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
AccountDao accountDao;
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
@Override
public Account findById(Integer id) {
return accountDao.findById(id);
}
@Override
public void save(Account account) {
accountDao.save(account);
}
@Override
public void update(Account account) {
accountDao.update(account);
}
@Override
public void del(Integer id) {
accountDao.del(id);
}
}
d、配置文件,在applicationContext.xml中添加
<!--业务层配置开始-->
<!--扫描包,创建业务层所有类对象-->
<context:component-scan base-package="com.torlesse.service"></context:component-scan>
<!--声明式事务-->
<!--1. 事务管理类对象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入:数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2. 事务增强对象-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--该类方法只读的事务, 如果有事务,加入事务执行,如果没有事务,非事务执行-->
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="get*" read-only="true" propagation="SUPPORTS"/>
<!--其他方法:非只读事务,如果没有事务,创建一个事务,如果有事务,加入事务执行-->
<tx:method name="*" read-only="false" propagation="REQUIRED"></tx:method>
</tx:attributes>
</tx:advice>
<!--3.aop配置:切面配置-->
<aop:config>
<!--切面配置-->
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.torlesse.service.impl.*.*(..))"></aop:advisor>
</aop:config>
<!--业务层配置结束-->
e、测试
package com.torlesse;
import com.torlesse.domain.Account;
import com.torlesse.service.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestService {
@Autowired
AccountService accountService;
@Test
public void test(){
List<Account> accountList = accountService.findAll();
for (Account account : accountList) {
System.out.println(account.getName());
}
}
}
6、dao和service最终配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--持久层配置 开始-->
<!--引入数据库外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--创建数据源对象-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--创建sqlSessionFactory对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入数据源对象-->
<property name="dataSource" ref="dataSource"></property>
<!--配置方法一:引入SqlMapConfig.xml文件-->
<!--<property name="configLocation" value="classpath:SqlMapConfig.xml"></property>-->
<!--配置方法二-->
<!--别名映射-->
<!--<property name="typeAliasesPackage" value="com.torlesse.domain"></property>-->
<!--可以注入其他的属性-->
<!--<property name="configurationProperties" value=""></property>-->
</bean>
<!--扫描dao层接口的包, 创建动态代理对象, 存入到spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--需要指定dao层接口的包名-->
<property name="basePackage" value="com.torlesse.dao"></property>
</bean>
<!--持久层配置结束-->
<!--业务层配置开始-->
<!--扫描包,创建业务层所有类对象-->
<context:component-scan base-package="com.torlesse.service"></context:component-scan>
<!--声明式事务-->
<!--1. 事务管理类对象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入:数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2. 事务增强对象-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--该类方法只读的事务, 如果有事务,加入事务执行,如果没有事务,非事务执行-->
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="get*" read-only="true" propagation="SUPPORTS"/>
<!--其他方法:非只读事务,如果没有事务,创建一个事务,如果有事务,加入事务执行-->
<tx:method name="*" read-only="false" propagation="REQUIRED"></tx:method>
</tx:attributes>
</tx:advice>
<!--3.aop配置:切面配置-->
<aop:config>
<!--切面配置-->
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.torlesse.service.impl.*.*(..))"></aop:advisor>
</aop:config>
<!--业务层配置结束-->
</beans>
7、web层编写
a、引入依赖
<!--springmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--servlet相关的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
b、配置文件:springmvc.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--扫描包,创建类对象-->
<context:component-scan base-package="com.torlesse.controller"></context:component-scan>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--自定义类型转换器-->
<!--文件上传-->
<!--拦截器-->
<!--静态资源放行-->
<!--<mvc:resources mapping="/js/*" location="/js/"></mvc:resources>-->
<!--静态资源全部放行-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
</beans>
c. 控制类的创建
package com.torlesse.controller;
import com.torlesse.domain.Account;
import com.torlesse.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@Controller
@RequestMapping("/account")
public class AccountController {
@Autowired
AccountService accountService;
/**
* 查询全部
* @return
*/
@RequestMapping("/findAll")
public ModelAndView findAll(){
//查询数据
List<Account> accountList = accountService.findAll();
System.out.println(accountList);
ModelAndView modelAndView = new ModelAndView();
//添加数据
modelAndView.addObject("accountList",accountList);
//指定页面
modelAndView.setViewName("show");
return modelAndView;
}
/**
* 保存操作
* 执行service中的save方法
* 最后查询数据库中所有的的内容,在页面展示
*
*/
@RequestMapping("/save")
public String save(Account account){
//执行保存操作
accountService.save(account);
//执行查询所有
return "redirect:findAll";
}
@RequestMapping("/del")
public String del(Integer id){
//执行删除操作
accountService.del(id);
//执行查询所有
return "redirect:findAll";
}
/**
* 更新页面数据回显
* @return
*/
@RequestMapping("/updateUI")
public ModelAndView updateUI(Integer id){
//根据id查询一个账户
Account account = accountService.findById(id);
//创建模型视图对象
ModelAndView modelAndView = new ModelAndView();
//添加数据
modelAndView.addObject("account", account);
//指定页面
modelAndView.setViewName("update");
return modelAndView;
}
/**
* 更新账户
* @param account
* @return
*/
@RequestMapping("/update")
public String update(Account account){
//更新操作
accountService.update(account);
//执行查询所有
return "redirect:findAll";
}
}
8、编写web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--配置一个全局的参数:指定spring容器的配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--配置监听器:创建spring容器对象-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--指定配置文件的路径-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
9、编写页面
bootstrap 文档网站:https://www.w3cschool.cn/bootstrap/
a, 查询页面编写
1. show.jsp
<%--
Created by IntelliJ IDEA.
User: sun
Date: 2018/11/22
Time: 16:15
To change this template use File | Settings | File Templates.
--%>
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<%--引入c 标签--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
<!-- 引入CSS样式 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
</head>
<body>
<table class="table table-bordered">
<caption>边框表格布局</caption>
<thead>
<tr>
<th>编号</th>
<th>账户名</th>
<th>余额</th>
</tr>
</thead>
<tbody>
<%--foreach循环
items: 要循环的集合对象
var:循环中的每一个对象
--%>
<c:forEach items="${accountList}" var="account">
<tr>
<td>${account.id}</td>
<td>${account.name}</td>
<td>${account.money}</td>
</tr>
</c:forEach>
</tbody></table>
</body>
<!-- 引入JS文件 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</html>
2. 引入bootstrap资源
3. jstl标签的依赖
<!-- 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>
b ,添加账户
<%--
Created by IntelliJ IDEA.
User: sun
Date: 2018/11/22
Time: 16:53
To change this template use File | Settings | File Templates.
--%>
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<!-- 引入CSS样式 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
</head>
<body>
<form class="form-horizontal" role="form" method="post" action="${pageContext.request.contextPath}/account/save">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">账户名</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="username" name="name"
placeholder="请输入账户名">
</div>
</div>
<div class="form-group">
<label for="money" class="col-sm-2 control-label">余额</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="money" name="money"
placeholder="请输入余额">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">保存</button>
</div>
</div></form>
</body>
<!-- 引入JS文件 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</html>
c, 删除操作
<a href="${pageContext.request.contextPath}/account/del?id=${account.id}" class="btn btn-success">删除</a>
d, 更新操作
<%--
Created by IntelliJ IDEA.
User: sun
Date: 2018/11/22
Time: 16:53
To change this template use File | Settings | File Templates.
--%>
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<!-- 引入CSS样式 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
</head>
<body>
<form class="form-horizontal" role="form" method="post" action="${pageContext.request.contextPath}/account/update">
<%--使用隐藏域,保存id的值,更新时作为条件--%>
<input type="hidden" name="id" value="${account.id}">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">账户名</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="username" name="name" value="${account.name}"
placeholder="请输入账户名">
</div>
</div>
<div class="form-group">
<label for="money" class="col-sm-2 control-label">余额</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="money" name="money" value="${account.money}"
placeholder="请输入余额">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">更新</button>
</div>
</div></form>
</body>
<!-- 引入JS文件 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</html>
二、拦截器
1、拦截器的作用
a. 拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
b. 拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
c. 拦截器,过滤器,监听器的区别
过滤器:是servlet的一部分,任何web项目都可以使用
配置 /* 后会过滤所有的资源(请求)
拦截器:是springMVC的一部分,只能在springMVC中使用
配置了/* 只会拦截请求,不会拦截静态资源
监听器:Web监听器是Servlet规范中的一种特殊类,用于监听ServletContext、HttpSession和 ServletRequest等域对象的创建与销毁事件,当Web应用启动时启动,当Web应用销毁时销毁。用于监听域对象的属性发生修改的事件,可以在事件发生前、发生后做一些必要的处理
d. 底层采用的是aop的思想
2、拦截器的代码
a. 引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
b.spring-mvc.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--扫描包,创建类对象-->
<context:component-scan base-package="com.torlesse.controller"></context:component-scan>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--自定义类型转换器-->
<!--文件上传-->
<!--引入拦截器:配置拦截器链-->
<mvc:interceptors>
<!--配置单个拦截器对象-->
<mvc:interceptor>
<!--拦截所有的请求-->
<mvc:mapping path="/**"/>
<!--指定拦截器类-->
<bean class="com.torlesse.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
<!--配置单个拦截器对象-->
<mvc:interceptor>
<!--拦截所有的请求-->
<mvc:mapping path="/**"/>
<!--指定拦截器类-->
<bean class="com.torlesse.interceptor.MyInterceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!--静态资源放行-->
<!--<mvc:resources mapping="/js/*" location="/js/"></mvc:resources>-->
<!--静态资源全部放行-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
</beans>
c. 创建拦截器类
package com.torlesse.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 创建自己的拦截器类,需要实现接口HandlerInterceptor
*/
public class MyInterceptor1 implements HandlerInterceptor{
/**
* 执行顺序:在控制器方法执行前执行
* 作用:拦截所有的请求,判断是否可以进行下一步执行
* 举例:如果判断你是否登录成功了,如果登录成功,则放行,返回值配置为true
* 如果登录失败,则拦截,返回值配置为false
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器1:preHandle执行了");
return true;
}
/**
* 执行的顺序: preHandel放行操作,可以执行
* 控制器方法返回值之前执行
* 作用:可以对返回的数据验证
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器1:postHandle执行了");
}
/**
* 执行顺序:preHandler必须放行, 执行完postHandle,之后执行
* 作用:释放资源
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器1:afterCompletion执行了");
}
}
3、多个拦截器测试
a. preHandler: 按照拦截器的配置顺序正序执行, 如果返回的都是true,则执行控制器的方法
b. postHandler: 所有的preHandler执行完之后,返回的都是true, 按照拦截器配置顺序倒序执行
c. afterCompletion: 所有postHandler执行完之后,
d. 配置多个拦截器
<!--引入拦截器:配置拦截器链-->
<mvc:interceptors>
<!--配置单个拦截器对象-->
<mvc:interceptor>
<!--拦截所有的请求-->
<mvc:mapping path="/**"/>
<!--指定拦截器类-->
<bean class="com.torlesse.interceptor.MyInterceptor2"></bean>
</mvc:interceptor>
<!--配置单个拦截器对象-->
<mvc:interceptor>
<!--拦截所有的请求-->
<mvc:mapping path="/**"/>
<!--指定拦截器类-->
<bean class="com.torlesse.interceptor.MyInterceptor1"></bean>
</mvc:interceptor>
</mvc:interceptors>
4、在ssm中使用拦截器示例
a, 登录页面
<%--
Created by IntelliJ IDEA.
User: sun
Date: 2018/11/22
Time: 16:53
To change this template use File | Settings | File Templates.
--%>
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<!-- 引入CSS样式 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
</head>
<body>
<form class="form-horizontal" role="form" method="post" action="${pageContext.request.contextPath}/login">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="username" name="username"
placeholder="请输入用户名">
</div>
</div>
<div class="form-group">
<label for="money" class="col-sm-2 control-label">密码</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="money" name="password"
placeholder="请输入密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">登录</button>
</div>
</div></form>
</body>
<!-- 引入JS文件 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</html>
b, spring-mvc.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.torlesse.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
c, 创建拦截器类
package com.torlesse.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInterceptor implements HandlerInterceptor{
/**
* 登录验证
* 如果session有登录信息,放行
* 如果session没有登录信息,拦截
* 判断是否是登录请求,如果登录请求,直接放行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求路径
String requestURI = request.getRequestURI();
//判断是否是登录请求
if(requestURI.contains("login")){
// 如果是登录请求,直接放行
return true;
}
//从session中获取登录信息
Object username = request.getSession().getAttribute("username");
if(username != null){
//session中有登录信息,放行
return true;
}else{
//session没有登录信息,跳转到登录页面
response.sendRedirect("/login.jsp");
return false;
}
}
}
书籍推荐
以下是一些关于Spring MVC的书籍推荐:
- 《Spring揭秘》:这本书主要是以 Spring3 的讲解为基础,但是,这本书对于 Spring 的编程思想讲的极为透彻,是有关 Spring 的书中,难得一见的好书。
- 《精通Spring 4.x》:这本书是一本非常全面的Spring框架入门书籍,内容涵盖了Spring的核心概念、配置、AOP、事务管理等方面。
- 《Spring MVC权威指南》:这本书从Spring MVC基础开始讲解,逐步深入到Spring MVC开发技术,内容由易到难,讲解由浅入深。包含大量实例,包括简单的代码演示,较大应用程序的实现步骤,方便阅读和实现。每章包含实践环节与课后习题,帮助读者巩固所学知识,提高编程能力。

1万+

被折叠的 条评论
为什么被折叠?



