Spring和SpringMvc详解
1.为什么使用Spring
1.spring框架是一个轻量级的开源的IOC和AOP的容器框架。
2.轻量级:相对于EJB(使用和设计框架都很麻烦)而言。
3.容器框架:将对象的创建和管理都交给spring框架去管理。
4.IOC:invers of control 控制反转;将对象创建的权利和依赖关系的维护(给字段赋值)交给spring去管理。
5.AOP:aspect oriented programming–面向切面编程=面向方面编程,将通用的逻辑抽取出来集中管理,以便于更好的管理。将可重用的功能提取出来,在合适的时候植入到应用程序中。如事务管理,权限控制,日志等。他并没有帮助我们去解决新的问题,而是提供了一种方法,用更少的工作量去解决问题,使系统更易维护,更加健壮。
使用spring的好处:
1…方便解耦,便于开发(它就是一个大工厂,可以将所有对象的创建和依赖关系维护都交给spring去管理)
2…支持AOP编程
3…声明式事务的支持(通过配置就可以完成对事务的支持,不需要手动编程)
4…方便给程序的测试,spring对junit4支持,可以通过注解方便的测试spring程序。
5.方便继承各种优秀的框架
6.降低javaEE API的使用难度(他对javaEE开发中一些难用的API都提供了封装,如jdbc等)
2.什么是Spring的事务管理?
基本理解:
1.事务:对一系列数据库操作进行统一的提交或回滚操作,如对多条数据插入的操作,如果其中有一条异常,那么会回滚之前所有的操作;如果插入成功,则一起成功。这样可以防止数据库出问题。
2.例子:比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱;然后ATM出1000元钱。这两个步骤必须是要么都执行要么都不执行。如果银行卡扣除了1000块但是ATM出钱失败的话,你将会损失1000元;如果银行卡扣钱失败但是ATM却出了1000块,那么银行将损失1000元。所以,如果一个步骤成功另一个步骤失败对双方都不是好事,如果不管哪一个步骤失败了以后,整个取钱过程都能回滚,也就是完全取消所有操作的话,这对双方都是极好的。
事务就是用来解决类似问题的。事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。
事务的四个特性:ACID
1.原子性(atomicity):事务是一个原子操作,由一系列动作组成。确保动作要么全部完成,要么完全不起作用。
2.一致性(consistency):一旦事务完成(不论成功还是失败),系统必须确保他所建模的业务处于一致的状态,而不是部分成功,部分失败。
3.隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据被破坏。
4.持久性(durability):一旦事务完成,无论发生什么系统错误,他的结果都不应该受到影响,这样就能从任何系统崩溃中恢复。通常情况下,事务的结果被写到持久化存储器中。
Spring的声明式事务通常是指在配置文件中对事务进行配置声明,其中包括了很多声明属性,他是通过spring proxy帮你做代理,自己不写额外的代码只要在spring配置文件中声明即可;通常用在数据库操作里面。
编程式事务就是通过硬编码的方式做事务处理,这样处理就需要自己写代码,事务的逻辑可以自己去定制,可以是数据库的操作,也可以是其他操作。
Spring中也有自己的事务管理机制,Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了
Public interface PlatformTransactionManager()...{
// 由TransactionDefinition得到TransactionStatus对象
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
// 提交
Void commit(TransactionStatus status) throws TransactionException;
// 回滚
Void rollback(TransactionStatus status) throws TransactionException;
}
3.Spring框架支持以下五种bean的作用域:
1…singleton:单例模式:在spring ioc容器中,使用这个定义的bean将只有一个实例:
2.Prototype:原型模式,每次通过容器的getBean方法都能获取一个新的实例:
3.Request:对于每次的http请求,都会产生一个新的实例,只有在web中,该作用域才有效
4.Session:对于每次http session请求,会产生一个新的实例,也是在web中才有效
5.Globalsession
前两种较多使用,未定义默认singleton
- 什么是Spring的MVC框架?
1.SpringMVC是一个基于MVC模式的WEB/表现层框架,它解决WEB开发中常见的问题:参数接收、文件上传/下载、表单验证、国际化等等;
2.SpringMVC作为Spring框架一个非常重要的功能模块,可以与Spring无缝集成,提高开发效率;
3.Spring是一个轻量级的Java 开发框架,为了解决企业应用开发的复杂性而创建。SpringMVC以Spring框架为核心,为应用程序中的Web层(表现层)提出的一套优秀的解决方案;
4.目前很多公司都使用SpringMVC,90%的招聘单位要求熟悉使用SpringMVC;
4.springMVC的配置:
<?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:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.静态资源放行:默认的Servlet处理静态资源。因为我们写的前端控制器匹配方式是/, 这个/会替换tomcat中default-servlet的配置。原来default-servlet处理静态资源的 -->
<mvc:default-servlet-handler />
<!-- 2.扫描包路径:Spring容器回去扫描cn.knd及其子包种的所有类,如果发现有 @Controller,@Service,@Repository,@Com......注解就创建对象 -->
<context:component-scan base-package="com.knd" />
<!-- 3.开启Spring对Mvc的支持:能够使用@RequetMapping注解 -->
<mvc:annotation-driven>
<!-- 避免在IE浏览器中返回JSON时出现下载文件的情况 -->
<mvc:message-converters>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 4.视图解析器:解析视图 -->
<!-- 设置视图路径的前后缀,该配置可以让我们写视图路径的时候更简单,只写视图名 -->
<!-- 只要配置了视图解析器,不管方法返回任何值,都要经过视图解析器:除了显式转发和重定向 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
<!-- 5.文件上传解析器:将复杂的表单数据解析成MultipartFile对象:
id属性值不能随便写,必须写multipartResolver
-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 最大上传大小 -->
<property name="maxUploadSize" value="20000000" />
<property name="defaultEncoding" value="utf-8"></property>
</bean>
<!-- 配置拦截器组 -->
<mvc:interceptors>
<!-- 拦截器 -->
<mvc:interceptor>
<!-- 要拦截的配置,该配置必须写在不拦截的上面,/*拦截一级请求,/**拦截多级请求 -->
<mvc:mapping path="/**" />
<!-- 设置不拦截的配置 -->
<mvc:exclude-mapping path="/json/list"/>
<!-- 配置拦截器 -->
<bean class="com.knd.interceptor.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
5.Spring MVC的请求流程:
1.浏览器发送请求,统一交给【前端控制器-DispatcherServlet】去处理。
2.前端控制器将请求交给【映射器-HandlerMapping】,找到执行该请求的处理器【处理器-handler】处理请求代码–>controller
3.前端控制器将处理器交给【适配器-HandlerAdaptor】去执行,返回一个ModelAndView对象。
4.前端控制器将ModelAndView对象交给【视图解析器】进行解析,解析成物理视图
5.前端控制器将视图响应给浏览器
6.浏览器渲染界面。
5.web.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>ssm</display-name>
<!-- 配置监听器:tomcat一启动就会为当前web项目创建一个唯一的上下文对象
监听器:只要上下文对象一创建,监听器就可以监听到了
监听到之后就自动实例化,初始化
在初始化的时候就会自动的去解析上下文对象的初始化参数:context-param
最终目的:加载Spring的配置文件:applicationContext.xml
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 1.前端控制器:接收所有的请求并分发出去,加载applicationContext-mvc.xml -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 在DispatcherServlet初始化时自动解析init-param标签 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-mvc.xml</param-value>
</init-param>
<!-- 服务器已启动就实例化DispatcherServlet,紧跟着要初始化 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 2.过滤器:解决post请求的中文参数乱码问题 过滤器比Servlet先执行,默认就是在服务器启动的时候就实例化了 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 指定字符集:初始化的时候会解析encoding -->
<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>
</web-app>
6.spring 与 mybatis,springmvc整合过程
1.整合数据层(dao)
Mybatis和spring整合,通过spring去管理mapper接口。
2.整合service层
通过spring去管理service接口
3.整合springmvc
Springmvc是spring的模块,不需要整合。
配置:创建resources文件夹
开始配置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:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.管理属性文件:
原因:Spring底层有一个系统属性username,与当前配置的属性冲突了
解决方法一:在属性文件中加前缀,前缀没有要求
解决方法二:system-properties-mode="NEVER" - 忽略系统属性
-->
<context:property-placeholder location="classpath:db.properties"
system-properties-mode="NEVER" />
<!-- 2.管理连接池对象 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
<!-- 3.管理SqlSessionFactory:从整合包去找 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入连接池对象 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 配置别名 -->
<property name="typeAliasesPackage" value="cn.knd.domain"></property>
<!-- 加载mapper映射文件:classpath: 一般加载属性文件和配置文件的时候使用 -->
<property name="mapperLocations" value="classpath:cn/knd/mapper/*Mapper.xml"></property>
</bean>
<!-- 4.管理Mapper的代理对象:MapperScannerConfigurer - mapper接口扫描配置 -->
<bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 自动注入sqlSessionFactory -->
<!-- <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> -->
<property name="basePackage" value="cn.knd.mapper"></property>
</bean>
<!--
Spring容器会到cn.knd.mapper中去扫描所有的mapper接口
然后为所有的mapper接口创建实现类
自动会创建实现类的对象
并且将该对象进行管理
-->
<!-- 5.扫描包路径 -->
<context:component-scan base-package="cn.knd.service"></context:component-scan>
</beans>
第二个配置:
<?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:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.静态资源放行 -->
<mvc:default-servlet-handler/>
<!-- 2.开启spring对Mvc的支持:能够使用@RequestMapping注解 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 3.扫描包路径 -->
<context:component-scan base-package="cn.knd.controller"></context:component-scan>
<!-- 4.视图解析器
:如果配置了视图解析器,不管返回是什么类型,都要经过视图解析器
不会经过视图解析器:
显示转发:"forward:url"
重定向:"redirect:url"
@ResponseBody //将当前方法的返回值转换成json格式的字符串,返回给调用方 - 不会经过视图解析器,显示转发和重定向不经过视图解析器
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
7.springmvc获取请求参数与向页面传值的方式
1.通过HttpServletRequest接收,post方式和get方式都可以:request.getParameter(“参数名”)
2.通过参数名:前提参数名和和name属性值一致
3.通过对象:前提:对象的bean属性和name属性值一致
4.通过类路径表达式获取:
/**
* 4、通过@PathVariable获取路径中的参数
* @param username
* @param password
* @return
*/
@RequestMapping(value="/addUser4/{username}/{password}",method=RequestMethod.GET)
public String addUser4(@PathVariable String username,@PathVariable String password) {
System.out.println("username is:"+username);
System.out.println("password is:"+password);
return "demo/index";
}
页面传值
(1)使用request绑订数据
(2)使用ModelAndView
(3)使用Model
(4)使用session绑订数据
1和4不介绍
具体见代码:
HelloController.java
package controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 二级控制器:
* 负责业务逻辑的处理。
* 1.不用实现Controller接口
* 2.在一个Controller类里面,可以添加
* 多个处理方法
* 这些方法的方法名可以自定义,返回值
* 可以是ModelAndView或者是String。
* http://ip:port/springmvc02/hello.do
*/
@Controller("user")
public class HeController {
@RequestMapping("/login1")
//向页面传值的第二种方式,使用ModelAndView
public ModelAndView login1(User user){
//ModelAndView(
//String viewName,Map data)
List<String,Object> list=
new arrayList<String,Object>();
//相当于执行了request.setAttribute(
//"user",user);
data.add("user", user);
return new ModelAndView(
"success",data);
}
@RequestMapping("/login2")
//向页面传值的第三种方式,使用ModelMap
public String login2(User user,
Model model){
//相当于request.setAttribute("user",user)
model.addAttribute("user", user);
return "success";
}
}