1.初识SpringMVC
简介
SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架。
SpringMVC已经成为目前最主流的MVC框架之一,并且随着Spring3.0 的发布,成为最优秀的MVC框架。它通过一套注解, 让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。
开发步骤
- 导入SpringMVC相关坐标
- 配置SpringMVC核心控制器DispathcerServlet
- 创建Controller类和视图页面
- 使用注解配置Controller类中业务方法的映射地址
- 配置核心文件spring-mvc.xml
- 客户端发起请求测试
代码实现
导包
<!--springMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.5</version>
</dependency>
配置前端控制器 web.xml
Controller控制层 视图
public class userController {
public String save (){
System.out.println("Controller save running......");
return ""; //返回要跳转的 页面 xxx.jsp
}
}
配置
@Controller //放到Spring容器中
public class userController {
@RequestMapping("/qd") //请求映射
public String save (){
System.out.println("Controller save running......");
return ""; //返回要跳转的 页面 xxx.jsp
}
}
组件扫描
在resources 文件夹中新建spring-mvc.xml
文件 (xxx.xml)
加载配置文件
测试 启动tomcat
代码角度
逻辑角度
组件解析
执行流程
注解解析 简单介绍
@RequestMapping
- 作用
- 用于建立请求URL和处理请求方法之间的对应关系
- 应用场景
- 类上,请求URL的第一-级访问目录。 此处不写的话,就相当于应用的根目录
- 方法上,请求URL的第二级访问目录, 与类上的使用@ReqquestMapping标注的一级目录一起组成访问虚拟路径
举例
@RequestMapping("/xxx")
类(){
@RequestMapping("/qd")
方法(){}
}
访问路径为 : http://localhost:8080/xxx/qd
属性
- value:用于指定请求的URL.它和path属性的作用是一样的 (默认为value)
- method:用于指定请求的方式
- params:用于指定限制请求参数的条件。支持简单的表达式。要求请求参数的key和value必须和配置的一模一样
举例
@RequestMapping(
value = "/qd" ,
method = RequestMethod.POST, //请求方式为post
params = {"accountName"}) //请求参数必须要有accountName
组件扫描
配置视图资源解析器
2.SpringMVC的数据响应
响应方式
- 页面跳转
- 直接返回字符串
- 通过ModleAndView对象返回
- 回写数据
- 直接返回字符串
- 返回对象或者集合
页面跳转
返回字符串形式
- 直接返回字符串 : 此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转。
@RequestMapping("/qd") //请求映射
public String save (){
System.out.println("Controller save running......");
return ""; //返回要跳转的 页面 xxx.jsp
}
//返回带有前缀的字符串
//转发
forward:/WEB-INF/view/index.jsp
//重定向
redirect:/index.jsp
返回ModelAndView对象
/*
* Model :模型 用于封装数据
* View :视图 展示数据
* */
@RequestMapping(value = "/qd1")
public ModelAndView save1() {
ModelAndView modelAndView = new ModelAndView();
//设置视图
modelAndView.setViewName("xxx"); //xxx.jsp
//设置模型数据
//相当于setAttribute("log","err")
// 取值 ${log}
modelAndView.addObject("log","err");
return modelAndView;
}
方式二 SpringMVC 自动注入
@RequestMapping(value = "/qd2")
public ModelAndView save2(ModelAndView modelAndView) {
//设置视图
modelAndView.setViewName("xxx"); //xxx.jsp
//设置模型数据
//相当于setAttribute("log","err")
// 取值 ${log}
modelAndView.addObject("log", "err");
return modelAndView;
}
//-----------------------------------------------------------------
@RequestMapping(value = "/qd3")
public String save3(Model model) {
model.addAttribute("log", "err");
return "";//xxx.jsp
}
//-----------------------------------------------------------------
//不常用
@RequestMapping(value = "/qd4")
public String save4(HttpServletRequest request) {
request.setAttribute("log","err");
return "";//xxx.jsp
}
回写数据
直接返回字符串
@RequestMapping(value = "/qd5")
public String save5(HttpServletRequest request) {
return reponse.getWriter().print("xxxxx");
}
//-----------------------------------------------------------------
@RequestMapping(value = "/qd6")
@ReponseBody //告知SpringMVC框架,不进行视图跳转 直接响应数据
public String save6( ) {
return "xxx";
}
实际应用场景 json
导包: Jackson-core Jack-databind jackson-annotations
@RequestMapping(value = "/qd7")
@ReponseBody //告知SpringMVC框架,不进行视图跳转 直接响应数据
public String save7( ) {
User user = new User();
user.setAge(10);
ObjectMapper mapper =new ObjectMapper();
String json = mapper.writeValueAsString( user ) //xx为json对象
return json;
}
返回对象或者集合
@RequestMapping(value = "/qd8")
@ReponseBody //告知SpringMVC框架,不进行视图跳转 直接响应数据
//SpringMVC 自动将User转换为json格式的字符串
public User save8( ) {
User user = new User();
user.setAge(10);
return user;
}
配置映射器过于繁琐 可以通过MVC的注解代替
<!-- mvc的注解驱动 -->
<mvc:annotation-driven/>
3.SpringMVC——获取请求
请求参数格式:name=value&name=value…
服务器端要获得请求的参数,有时还需要进行数据的封装,SpringMVC可以接收如下类型的参数:
- 基本类型参数
- POJO类型参数
- 数组类型参数
- 集合类型参数
获取请求参数
获得基本类型参数
获得POJO类型参数
获得数组类型参数
获得集合类型参数
- 获得集合参数时,要将集合参数包装到一个POJO中才可以。
- 特殊场景 当使用ajax提交时,可以指定contentType为json形式,那么在方法参数位置使用@RequestBody可以直接接收集合数据而无需使用POJO进行包装。
但是由于静态访问权限无法找到Jquery文件 我们需要在Spring-mvc.xml
中配置
开放资源的访问
<mvc:resources mapping="/js/**” 1ocation="/js/" />
<mvc:resources mapping="/img/**” 1ocation="/img/" />
资源地址 具体所在目录
<!--另外常用的方法-->
<mvc : default-servlet-handler/>
请求的乱码问题
在Spring-mvc.xml中配置filter
<!--配置全局过滤的filter-->
<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>
参数绑定注解@requestParam
当请求的参数名称与Controller的业务方法参数名称不一致时,就需要通过@RequestParam注解显示的绑定。
注解@RequestParam还有如下参数可以使用:
- value:与请求参数名称
- requireds:此在指定的请求参数是否必须包括,默认是true,提交时如果没有此参数则报错defaultValue:当没有指定请求参数时,则使用指定的默认值赋值
- defaultValue:当没有指定请求参数时,则使用指定的默认值赋值
获取Restful风格的参数
Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以==更简洁,更有层次,更易于实现缓存机制等。
Restful风格的请求是使用==“url+请求方式”==表示一次请求目的的,HTTP协议里面四个表示操作方式的动词如下:
- GET:用于获取资源
- POST:用于新建资源
- PUT:用于更新资源
- DELETE:用于删除资源
举例
//localhost:8080/qd9/zhangsan
@RequestMapping(value = "/qd9/{username}")
@ReponseBody
public void save9( @PathVariable("username") String userName) throws IOException {
System.out.println(userName); //打印zhangsan
}
自定义类型转换器
- SpringMVC默认已经提供了一些常用的类型转换器,例如客户端提交的字符串转换成int型进行参数设置。
- 但是不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据就需要自定义转换器。
步骤:
- 定义转换器类实现Converter接口
- 在配置文件中声明转换器
- 在中引用转换器
新建converter包 具体实现类
在Spring-mvc.xml中配置
<!-- mvc的注解驱动 -->
<mvc:annotation-driven conversion-service="conversionService"/> <!-- id -->
获得Servlet相关API
SpringMVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入,常用的对象如下:
- HttpServletRequest
- HttpServletResponse
- HttpSession
获取请求头
- @RequestHeader
使用@RequestHeader可以获得请求头信息,相当于web阶段学习的request.getHeader(name)@RequestHeader注解的属性如下:
- value:请求头的名称
- required:是否必须携带此请求头
- @CookieValue
使用@CookieValue可以获得指定Cookie的值@CookieValue注解的属性如下:
- value:指定cookie的名称
- required:是否必须携带此cookie
了解文件上传
- 文件上传客户端三要素
- 表单项type= “file"
- 表单的提交方式是post
- 表单的enctype属性是多部分表单形式,及enctype= “multipart/form-data”
- 文件上传原理
- 当form表单修改为多部分表单时,request.getParameter()将失效
- enctype= "application/x-vww-form-urlencoded”时,form表单的正文内容格式是:key=value&key=value&key=value
- 当form表单的enctype取值为Mutilpart/form-data时,请求正文内容就变成多部分形式:
单文件上传步骤
步骤:
1.导入fileupload和io坐标
2.配置文件上传解析器 (Spring-mvc.xml)
3.编写文件上传代码
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactid> <version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
多文件上传实现
若文件名相同则使用数组接收
4.Spring JdbcTemplate基本使用
概述:
它是spring框架中提供的一个对象,是对原始繁琐的JdbcAPI对象的简单封装。spring框架为我们提供了很多的操作模板类。例如:操作关系型数据的JdbcTemplate和bernateTemplate,操作nosql数据库的RedisTemplate,操作消息队列的JmsTemplate等等。
开发步骤
1.导入spring-jdbc和spring-tx坐标
2.创建数据库表和实体
3.创建JdbcTemplate对象
4.执行数据库操作
快速实现
- 导包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactid> <version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
- 创建一个数据库表与实体
- 创建JdbcTemplate对象
Spring产生 JdbcTemplate对象
因为Spring能通过无参构造创建对象 我们可以通过Spring容器产生
可以通过set方法注入数据源对象
步骤:
- 配置数据源对象
- 往数据源对象注入参数
- 产生模板对象
- 注入数据源对象
在resources中创建applicationContext.xml
抽取jdbc.properties
在resources中创建jdbc.properties
jdbc.driver=com.mysq1.jdbc.Driver
jdbc.ur1=jdbc:mysq1://localhost:3306/test
jdbc.username=root
jdbc.password=root
PS:加载jdbc.properties 数据源对象 jdbc模板对象为一套
模板常规操作
//查询全部 封装为集合
@Test
public void testQueryAll(){
List< 类名 〉 accountList = jdbcTemplate.query( sql:."select * from account",new BeanPropertyRowMapper< 类名 >( 类名.class ));
System.out.println( accountList );
}
//查询单个
public void testQueryOne(){
类名 xxx = jdbcTemplate.queryForObject( sql:."select * from account where name = ? ",new BeanPropertyRowMapper< 类名 >( 类名.class ) ,"前度");
System.out.println( xxx );
}
//聚合查询
public void testQueryCount(){
Long xxx = jdbcTemplate.queryForObject( sql:."select count(*) from account ",Long.class);
System.out.println( xxx );
}
5.练习——环境搭建
必要配置
注意:框架要集成到Web环境下 需要在web.xml配置监听器
项目实战
详情请移步bilibili前往观看视频:
https://www.bilibili.com/video/BV1WZ4y1P7Bp?p=89&spm_id_from=pageDriver
6.SpringMVC拦截器
拦截器作用 (interceptor)
-
Spring MVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
-
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(Interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。
拦截器与过滤器的区别
区别 | 过滤器 | 拦截器 |
---|---|---|
使用范围 | 是servlet规范中的一部分,任何Java Web工程都可以使用 | 是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用 |
拦截范围 | 在url-pattern中配置了*之后,可以对所有要访问的资源拦截 | 只会拦截访问的控制器方法,如果访问的是jsp, html,css,image或者js是不会进行拦截的 |
拦截器快速入门
自定义拦截器步骤:
1.创建拦截器类实现Handlerlnterceptor接口
2.配置拦截器
3.测试拦截器的拦截效果
//在目标方法执行之前执行
public boolean preHandle( HttpServletRequest request, HttpServletResponse response, 0bject handler) {return false;}
//在目标方法执行之后视图对象返回之前执行
public void postHandle( HttpServletRequest request, HittpServletResponse response,Object handler,
ModelAndView modelAndView ) { }
//在流程都执行完毕后 执行
public void afterCompletion( HttpServletRequest request, HttpServletResponse response,
Object handler,Exception ex ) { }
<!--配置拦截器-->
<mvc : interceptors>
<mvc : interceptor>
<!--对哪些资源执行拦截操作-->
<mvc :mapping path="/**"/>
<bean class="自定义拦截器的包地址"/>
</mvcmvc : interceptor>
</mvc : interceptors>
详解
preHandle
如果返回false 可以用reponse重定向到其他资源避开目标资源
postHandle
用modelAndView参数改变视图
//在目标方法执行之前执行
public boolean preHandle( HttpServletRequest request, HttpServletResponse response, 0bject handler) {
String param = request.getParameter( s: "param");
if("yes".equals(param)){
return true; }
else{
request.getRequestDispatcher( s: /error.jsp").forward(request,reponse)
return false; //返回true代表放行返回false代表不放行
}
}
//在目标方法执行之后视图对象返回之前执行
public void postHandle( HttpServletRequest request, HittpServletResponse response,Object handler,
ModelAndView modelAndView ) {
modelAndView.addObject("name","前度");
}
ps:当配置多个拦截器注意顺序
举个例子 当用户未登录时,不能访问其他资源跳转到登录页面
ps:还需要配置排除资源拦截的操作 在上面xml文件加入以下代码
<!--配置哪些资源排除拦截操作-->
<mvc :exclude-mapping path="/user/1ogin"/>
queryForObject 这个方法在查询不到时会返回一个EmptyResultDataAccessException
异常 我们要将此异常上抛出到前端控制器去捕获
7.SpringMVC异常处理机制
异常处理思路
系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生入
系统的Dao、Service、Controller出现都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常金理器进行异常处理,如下图:
异常处理方式
- 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver
- 实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器
简单异常处理器
自定义异常处理步骤
- 创建异常处理器类实现HandlerExceptionResolver
- 配置异常处理器
- 编写异常页面
- 测试异常跳转
<!--配置自定义异常处理器-->
<bean class="异常类包地址"/>
8.AOP
AOP (Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的-种技术。AOP是O0P的延续,是软件开发中的一个热点,也是Spring框架中的一 -个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
Spring笔记中也有介绍
AOP的作用与优势
- 作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
- 优势:减少重复代码,提高开发效率,并且便于维护
AOP的底层实现
AOP动态代理技术
常用的动态代理技术
- JDK代理:基于接口的动态代理技术
- cglib代理:基于父类的动态代理技术
基于JDK动态代理技术
- 新建接口
TargetInterface
public interface TargetInterface { public void save( ); }
- 实现接口
Target
public class Target implements TargetInterface {
public void save() {
System. out. println("save running.. . . .") ;
}
- 新建增强类
Advice
public c1ass Advice {
public void before() { System. out. println("前置增强...."); }
public void afterReturning( {System. out.println("后置增强....");}
}
- 测试类
public class ProxyTest {
public static void main(String[] args){
Target target = new Target() ;
//增强对象
Advice advice = new Advice();
//返回值,就是动态生成的代理对象
TargetInterface proxy=(TargetInterface)Proxy.newProxy Instance(
target.getClass().getClassLoader(),//目标对象类加载器
target.getClass().getInterfaces(),//目标对象相同的接口字节码对象数组
new InvocationHandler() {
//周用代理对象的任何方法实质执行的都是invoke方法
public 0bject invoke(Object proxy,Method method,,0bject[] args) throws Throwable {
advice.before(); //前置增强
Object invoke = method.invoke(target, args);/ /执行目标方法
advice.after();//后置增强
return invoke;
} }}
proxy.save();
}
基于cglib动态代理技术
- 实现类
Target
public class Target {
public void save() {
System. out. println("save running.. . . .") ;
}
- 测试类
public class ProxyTest {
public static void main(String[] args){
Target target = new Target() ;
//增强对象
Advice advice = new Advice();
//返回值,就是动态生成的代理对象 基于cglib
//1创建增强器
Erhancer enhancer = new Enhancer () ;
//2设置父类
enhancer.setSuperclass(target.class);
//3设置回调
enhancer. setCallback(new MethodInterceptor(){
public 0bject intercept(Object o,Method method,Object[] args,MethodProxy methodProxy) throws Throwable {
advice.before(); //前置增强
Object invoke = method.invoke(target, args);/ /执行目标方法
advice.after();//后置增强
return invoke;
}) ;
//4创建代理对象
Target proxy =(Target) enhancer. create();
proxy. save();
}
}
Spring的AOP相关概念
-
Target(目标对象)∶代理的目标对象
-
Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
-
Joinpoint(连接点)︰所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点 可以被增强的方法
-
Pointcut(切入点) ∶所谓切入点是指我们要对哪些 Joinpoint进行拦截的定义
-
Advice(通知/增强) ∶所谓通知是指拦截到Joinpoint之后所要做的事情就是通知
-
Aspect(切面)︰是切入点和通知(引介)的结合
-
Weaving (织入)︰是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而Aspect采用编译期织入和类装载期织入
AOP开发明确的事项
1.需要编写的内容
- 编写核心业务代码(目标类的目标方法)
- 编写切面类,切面类中有通知(增强功能方法)
- 在配置文件中,配置织入关系,即将哪些通知与哪些连接点进行结合
2.AOP技术实现的内容
Spring框架监控切入点方法的执行。一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行。
3. AOP底层使用哪种代理方式
在spring中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。
xml与注解实现Aop
快速入门
- 导入AOP相关坐标
- 创建目标接口和目标类(内部有切点)
- 创建切面类(内部有增强方法)
- 将目标类和切面类的对象创建权交给spring
- 在pplicationContext.xml中配置织入关系
- 测试代码
Spring笔记中也有介绍,前往观看
9.Spring的事务控制
编程式事务控制相关对象
PlatformTransactionManager接口(了解)
TransactionDefinition
事务隔离级别
事务传播行为
- 解决调用业务方法时事务统一性的问题
TransactionStatus
基于xml与注解的声明式事务控制
Spring的声明式事务顾名思义就是采用声明的方式来处理事务。这里所说的声明,就是指在配置文件中声明,用在Spring配置文件中声明式的处理事务来代替代码式的处理事务。
-
事务管理不侵入开发的组件。具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可。
-
在不需要事务管理的时候,只要在设定文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便。
注意: Spring声明式事务控制底层就是AOP。
声明式事务控制的实现
声明式事务控制明确事项:
- 谁是切点?
- 谁是通知?
- 配置切面?
基于xml的声明事务控制
快速入门
<!--applicationContext.xml-->
<beans>
<!--目标对象内部的方法就是切点-->
<bean id="accountService" class="包地址">
<property name="accountDao" ref="accountDao"/>
</bean>
<!--配置平台事务管理器-->
<bean id="transactionManager" class="org.springframework. jdbc.datasource.DataSourceTransactionManager"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!--通知 事务的增强 引入 tx 命名空间-->
<tx : advice id="txAdvice" transaction-manager="transactionManager">
<!--设置事务的属性信息-->
<tx:attributes>
<tx : method name="*"/>
</tx:attributes>
</tx :advice>
<!--配置事务的aop织入-->
<aop : config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com. itheima. service.impl.*.*(..))"></aop:advisor>
</aop : config>
</beans>
-
advice-ref : 通知引用
-
transaction-manager :引入平台事务管理器
基于注解的声明事务控制
详情:请移步B站观看更加详细的操作 6分钟左右
黑马程序员最全SSM框架教程|Spring+SpringMVC+MyBatis全覆盖_SSM整合_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
要加事务的注解驱动
<!--事物的注解驱动-->
<tx : annotation-driven transaction-manager="transactionManager"/>
注解配置声明式事务控制解析:
- 使用@Transactional在需要进行事务控制的类或是方法上修饰,注解可用的属性同xml配置方式,例如隔离级别、传播行为等。
- 注解使用在类上,那么该类下的所有方法都使用同一套注解参数配置。
- 使用在方法上,不同的方法可以采用不同的事务参数配置。
- Xml配置文件中要开启事务的注解驱动
结束啦~~