Spring&MVC入门笔记
本人小白一个,刚学习的spring与SpringMVC进行一下总结,提供借鉴,有错误麻烦帮忙指出,有参考另外几篇大牛的文章,侵删!
1、Spring
1.1、Spring原理
将对象交给Bean元素来进行管理,降低类与类之间的耦合度,由spring容器来对类的属性与关系进行处理
1.2、Spring控制反转IOC
将对对象的控制权转交给Spring的IOC容器来进行控制
1.3、Spring依赖注入DI
在Spring的IOC容器中,替你管理着一系列的类,在使用类型时,Spring容器会根据你的需求,去它所管理的类中进行查找,然后给你需要的类,该类中的成员由Spring来进行注入值进行初始化
1.4、Bean元素属性
-
**name属性:**给被管理的对象起个名字,获得对象时getBean(“name值”)
-
**class属性:**被管理对象的完整类名
-
**id属性:**与name属性一模一样,名称不可重复,不能使用特殊字符
-
**scope属性:**
(1)singleton 默认值
单例对象 :被标识为单例的对象在spring容器中只会存在一个实例
(2)prototype
多例原型:被标识为多例的对象,每次在获得才会被创建,每次创建都是新的对象 -
init-method属性:
配置一个方法作为生命周期初始化方法,spring会在对象创建之后立刻调用 init-method
-
destory-method属性:
配置一个方法作为生命周期的销毁方法,spring容器在关闭并销毁所有容器中的对象之前调用destory-method
注意
1、配置两个相同的 id 或者 name 都不能通过。
2、如果既配置了 id ,也配置了 name ,则两个都生效。如果id和name都没有指定,则用 包名.类名配置Bean
3、在配置Bean类是,当注解与配置都存在,若注释与配置文件的name相同则只有配置文件的name生效,若不同则两个 配置都可以生效
1.4.1、注解配置Bean属性
@Scope("实例类型")
@Bean(name="标识名",initMethod="初始化方法",destroyMethod="销毁方法")
public class ClassName{
@PostConstruct
public static void initMethodName(){
//这个方法会自动在bean初始化钱执行
}
@PreDestroy
public static void destroyMethod(){
//这个方法会自动在容器销毁Bean时执行
}
}
1.5 Spring依赖注入方式
1.5.1通过配置实现注入
<bean id="标识名" class="包名.类名">
<!--设值注入-->
<!--
对应类中必须有set访问器
-->
<property name="常量属性名" value="常量值"></property>
<property name="对象属性名" ref="声明的Bean的Id值"></property>
<!--构造注入-->
<!--
根据类的构造函数进行注入
一个<constructor-arg>表示一个参数,不区分顺序,从第一个构造开始匹配,类型与数量一致就进入匹配
属性index指定参数的索引,type指定该索引的类型
-->
<constructor-arg value="值"></constructor-arg>
<constructor-arg ref="声明的Bean的Id值"></constructor-arg>
<constructor-arg index="对应的索引" type="该索引的类型" value="值"></constructor-arg>
<!--命名空间注入-->
<!--
根据 命名空间:属性名 进行注入,加入xmlns:p="http://www.springframework.org/schema/p"配置
在bean元素的属性中 不论什么类型的值都要带"" 例:p:int类型的属性 = "值"
-->
<bean id = "标识名" class="包名.类名" p:属性名="值" p:属性名-ref="Bean的Id名"></bean>
<!--list集合注入-->
<!--
存储值类型<value>值</value>
存储对象类型<ref bean="Bean的id标识名"/>
-->
<property name="List集合属性">
<list>
<value>值</value>
<value>值</value>
<ref bean="Bean的id值"/>
</list>
</property>
<!--Array数组属性注入-->
<!--
存储值类型<value>值</value>
存储对象类型<ref bean="Bean的id标识名"/>
-->
<property name="Array数组属性">
<list>
<value>值</value>
<value>值</value>
<ref bean="Bean的id值"/>
</list>
</property>
<!--set集合属性注入-->
<!--
存储值类型<value>值</value>
存储对象类型<ref bean="Bean的id标识名"/>
-->
<property name="Set集合属性">
<set>
<value>值</value>
<value>值</value>
<ref bean="Bean的id值"/>
</set>
</property>
</bean>
1.5.2通过注解实现注入
- 步骤1
在要被管理的类中写注释
@Repository("") 用于标注dao类
@Service("") 用于标注业务类
@Controller("") 用于标注控制器类(提供增强方法的类)
@Component("") 用于标注一个类
- 步骤2
在需要填配值的属性上加入,当根据类型查找Bean元素装配时,不能出现多个类型一样的元素
@Autowired 根据类型自动装配
@Qualifier(“Bean标识名”) 配合@Autowired使用,根据标识名获得Bean,用于构造方法中、set方法中、属性名上;
@Resource(name=“Bean标识名”) 根据标识名查找Bean,省略标识名根据属性名匹配名称一致的Bean,再无一致则根据属 性类型匹配Bean元素
步骤3
在配置文件中配置
<?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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- 扫描包中注解标注的类 -->
<!-- base-package="包名"-->
<context:component-scan base-package="service,dao" />
</beans>
1.6、导入外部配置文件
<beans>
<import resource = “spring配置文件的全路径名" />
</beans>
1.7、Spring AOP
1.7.1、AOP的术语
连接点(JoinPoint)
spring只支持方法连接点,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点
切入点(Pointcut)
你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知,你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。
切面(Aspect)
切面是通知和切入点的结合,通知说明了执行什么和什么时候去执行,而切入点说明了在哪执行(指定到底是哪个方法),这就是一个完整的切面定义。
引入(introduction)
允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗
目标对象(target)
引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑类,他可以在毫不知情的情况下,被咱们织入切面。而自己专注于业务本身的逻辑。
代理(proxy)
它会截取对目标类中方法的调用,让调用者对目标类的调用都先变成调用代理类,代理类中就先执行了切面,再把调用转发给真正的目标类。
织入(weaving)
是把切面应用到目标对象,并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期中有多个点可以进行织入:
-
编译期: 在目标类编译时,切面被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。
-
类加载期:切面在目标加载到JVM时被织入。这种方式需要特殊的类加载器(class loader)它可以在目标类被引入应用之前增强该目标类的字节码。
-
运行期: 切面在应用运行到某个时刻时被织入。一般情况下,在织入切面时,通过连接点+执行的增强的方法+切入点创建一个拦截器 ,在把该拦截器使用对应的动态代理机制代理成代理对象;
1.7.2、通知类型
- 前置通知(Before):在目标方法被调用之前调用通知功能。
- 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么。
- 返回通知(After-returning):在目标方法成功执行之后调用通知。
- 异常通知(After-throwing):在目标方法抛出异常后调用通知。
- 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
1.7.3、JoinPoint类
- JoinPoint接口表示目标类连接点对象
- 如果是环绕增强时,ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。
- 任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。
方法名 | 返回值 | 方法描述 |
---|---|---|
getArgs() | Object[] | 获取连接点方法运行时的入参列表 |
getSignature() | Signature | 获取连接点的方法签名对象 |
Object | getTarget() | 获取连接点所在的目标对象 |
Object | getThis() | 获取代理对象本身 |
1.7.4、通过配置实现AOP
applicationContext.xml配置
<bean id="提供增强方法的类标识名" class="包名.增强方法类"></bean>
<!-- 配置切面 -->
<aop:config>
<!--
定义切入点,具体到为哪个方法织入增强
public void addNewUser()为所有方法名为addNewUser无参无返回值的方法织入增强
-->
<aop:pointcut id="切点标识名"
expression="execution(public void addNewUser())" />
<!-- 引用包含增强方法的Bean -->
<aop:aspect ref="增强方法类">
<aop:before method="前置方法名" pointcut-ref="pointcut"></aop:before>
<!-- 通过returning属性指定为名为result的参数注入返回值 -->
<aop:after-returning method="后置增强方法名" pointcut-ref="pointcut" returning="result" />
<aop:after method="最终增强方法名" pointcut-ref="切点"/>
<!--ex为异常方法的参数名-->
<aop:after-thrwoing method="异常方法名" pointcut-ref="切点" throwing="ex"/>
<aop:around method="环绕方法名" pointcut-ref="切点" />
</aop:aspect>
</aop:config>
提供增强方法的类
private static final Logger log = Logger.getLogger(AroundLogger.class);
//前置增强方法
public void 前置增强方法(JoinPoint jp) {
log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
+ " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
//后置增强方法
public void 后置增强方法名(JoinPoint jp, Object result) {
log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
+ " 方法。方法返回值:" + result);
}
//异常增强的方法
public void 异常处理方法名(JoinPoint jp,RuntimeException ex){
//异常处理方法
}
//最终增强的方法
public void 最终增强方法名(JoinPoint jp){
//最终处理方法
}
//环绕增强方法
public Object 环绕增强方法名(ProceedingJoinPoint jp) throws Throwable {
log.info("前置增强执行 " + jp.getTarget() + " 的 " + jp.getSignature().getName()+ "方法");
try {
//jp.proceed();为调用目标方法,不加入该代码不会执行目标方法
jp.proceed();
Object result = jp.proceed();
log.info("后置增强执行" + jp.getTarget() + " 的 "+ jp.getSignature().getName() + "方法.");
//这边的result为目标方法的返回值,通过修改该result可修改目标方法的返回值
return result;
} catch (Throwable e) {
log.error(jp.getSignature().getName() + " 方法发生异常:" + e);
throw e;
} finally {
log.info(jp.getSignature().getName() + " 方法结束执行。");
}
}
实验类
public class AopTest {
@Test
public void aopTest() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Service service = new Service();
//在执行addNewUser()方法的时会织入增强方法类提供的增强方法
service.addNewUser(user);
}
}
1.7.5、使用注解实现AOP
@Aspect 定义切面,在提供增强方法类的类名上标明,表示该类为提供增强方法的类
@Around 环绕增强,定义在环绕增强方法上
@Before 前置增强,@Before(“execution(条件)”)
@AfterReturning 后置增强,@AfterReturning(pointcut=“execution(条件)”,returning=“result”)
@After 最终增强,@After(“execution(条件)”)
@AfterThrowing 异常增强,@AfterThrowing(“execution(条件)”)
execution(条件)为定义切入点
@Pointcut配置切入点注解
//通过Pointcut使demo方法能代表execution(* service.UserService.*(..))表达式,来达到简写的作用
@Pointcut("execution(* service.UserService.*(..))")
public void demo(){}
@Pointcut("execution(* service.UserServiceTwo.*(..))")
public void demoTwo(){}
@Around("demo")
public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable {
//方法体
}
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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<context:component-scan base-package="依赖类的包名" />
<!--提供增强方法的类需要手动导入-->
<bean class="提供增强方法的类"></bean>
<aop:aspectj-autoproxy />
</beans>
1.7,6、AOP执行流程
1,解析xml;
2,实例化所有的bean;
3,解析aop:config;
1,解析**aop:aspect**,得到aspect引用的对象;
2,解析aop:aspect里面的每一个切面;
1,得到该aspect对应的pointcut-ref;
2,得到pointcut-ref对应的pointcut的表达式;
3,使用表达式中用于匹配类型的表达式;
4,使用该表达式去和spring里面配置的所有的bean的类型进行匹配;
1,如果匹配不上,不管;
2,如果匹配上了,该对象作为spring动态代理的目标对象;
1,如果该对象实现了接口,使用JDK的动态代理包装;
2,如果该对象没有实现接口,使用cglib包装;
3,得到要执行增强的连接点+执行的增强的方法+切入点创建一个拦截器
4,在把该拦截器使用对应的动态代理机制代理成代理对象;
5,替换spring容器中的对应bean的实例;
1.7.7、aop原理
**spring用代理类包裹切面,把他们织入到Spring管理的bean中。**也就是说代理类伪装成目标类,它会截取对目标类中方法的调用,让调用者对目标类的调用都先变成调用伪装类,伪装类中就先执行了切面,再把调用转发给真正的目标bean。
现在可以自己想一想,怎么搞出来这个伪装类,才不会被调用者发现(过JVM的检查,JAVA是强类型检查,哪里都要检查类型)。
实现和目标类相同的接口
实现和目标类相同的接口,我也实现和你一样的接口,反正上层都是接口级别的调用,这样我就伪装成了和目标类一样的类(实现了同一接口,咱是兄弟了),也就逃过了类型检查,到java运行期的时候,利用多态的后期绑定(所以spring采用运行时),伪装类(代理类)就变成了接口的真正实现,而他里面包裹了真实的那个目标类,最后实现具体功能的还是目标类,只不过伪装类在之前干了点事情(写日志,安全检查,事物等)。
spring会使用JDK的java.lang.reflect.Proxy类,它允许Spring动态生成一个新类来实现必要的接口,织入通知,并且把对这些接口的任何调用都转发到目标类。
生成子类调用
生成子类调用,这次用子类来做为伪装类,当然这样也能逃过JVM的强类型检查,我继承的吗,当然查不出来了,子类重写了目标类的所有方法,当然在这些重写的方法中,不仅实现了目标类的功能,还在这些功能之前,实现了一些其他的(写日志,安全检查,事物等)。
spring使用CGLIB库生成目标类的一个子类,在创建这个子类的时候,spring织入通知,并且把对这个子类的调用委托到目标类。
1.8、Spring整合MyBatis
SqlSessionFactoryBean 为整合应用提供SqlSession对象的资源
SqlSessionTemplate 负责管理MyBatis的SqlSession,调用SQL映射语句,来实现对数据库的操作
1.8.1通过配置信息实现
application.xml配置文件
<!--配置数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?
useUnicode=true&characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="chenbiao0409" />
</bean>
<!--配置SqlSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源,ref值为DataSource的id标识名-->
<property name="dataSource" ref="dataSource"></property>
<!--引入myBatis的配置文件,value值为myBatis的配置文件路径,该文件与application配置文件同级-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--引入SQL映射文件信息-->
<property name="mapperLocations">
<list>
<!--value为映射文件的路径,这里指匹配cn.smbms.dao包下的所有映射文件-->
<value>classpath:cn/smbms/dao/**/*.xml</value>
</list>
</property>
<!--配置SqlSessionTemplate-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!--ref值为sqlSessionFactoryBean的id值-->
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- 配置DAO -->
<bean id="userMapper" class="cn.smbms.dao.user.UserMapperImpl">
<!--这里SqlSessionTemplateBean元素就可以执行SQL映射文件中的方法-->
<property name="sqlSession" ref="sqlSessionTemplate" />
</bean>
<!--
实验类中获得该userService去操作sqlSessionFactory中配置接口的方法
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
UserService userService = (UserService) ctx.getBean("userService");
usersEntity entity= userService.findUsersWithConditions();
entity.toString();
-->
1.8.2通过注入器实现
**application.xml配置文件**
<!--配置数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?
useUnicode=true&characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="chenbiao0409" />
</bean>
<!--配置SqlSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--配置数据源,ref值为DataSource的id标识名-->
<property name="dataSource" ref="dataSource"></property>
<!--引入myBatis的配置文件,value值为myBatis的配置文件路径,该文件与application配置文件同级-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--引入SQL映射文件信息-->
<property name="mapperLocations">
<list>
<!--value为映射文件的路径,这里指匹配cn.smbms.dao包下的所有映射文件-->
<value>classpath:cn/smbms/dao/**/*.xml</value>
</list>
</property>
<!--
省略配置SqlSessionTemplate,直接将SqlSessionFactoryBean注入到MapperFactoryBean元素的sqlSessionFactory中
的sqlSessionFactory属性,映射接口指要具体执行方法的接口,包名.接口名 接口中的值与映射文件有关联
-->
<!-- 配置DAO -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!--
该映射接口只提供对应方法的声明,具体实现由与接口同名的映射文件中来具体实现,
该映射器中的namespace声明对应接口的路径(包名.类名)
该映射器中的Mapper操作的id对应接口的方法名,
该映射器中的Mapper操作的parameterType对应接口的参数类型
该映射器中的Mapper操作的resultType对应接口的对应方法的返回值类型
-->
<property name="mapperInterface" value="包名.映射接口名"></property>
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- 配置业务Bean -->
<bean id="userService" class="cn.smbms.service.user.UserServiceImpl">
<!--将MapperFactoryBean元素注入业务类的userMapper映射接口类型的属性中,该元素可使用映射文件中定义的Mapper操作-->
<property name="userMapper" ref="userMapper" />
</bean>
<!--
实验类中获得该userService去操作sqlSessionFactory中配置接口的方法
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
UserService userService = (UserService) ctx.getBean("userService");
usersEntity entity= userService.findUsersWithConditions();
entity.toString();
-->
1.9、Spring声明事务
spring提供基于AOP的声明事务实现
1.9.1、XML配置声明事务
定义事务管理器Bean,用于管理事务,并为其注入数据源的Bean
<bean id ="txtManager" class="DataSourceTransactionManager">
<proprty name="dataSource" ref="DataSource的Bean元素的Id值"></proprty>
</bean>
通过tx:advice配置事务增强,绑定事务管理器并针对不同方法定义对应的事务规则
<tx:advice id = "txAdvice" transaction-manager="事务管理器Bean的ID">
<!--事务规则-->
<tx:attributes>
<tx:method name="方法名可用通配符*" timeout="事务超时时间-1永不超时" read-only = "false"/>
<!--符合切入点的方法都会执行事务-->
<tx:method name="*" ...事务规则/>
</tx:attributes>
</tx:advice>
配置切面,将事务增强与方法切入点组合
<aop:config>
<aop:pointcut expression="execution(切入点表达式)" id="myPoint"/>
<aop:advisor advice-ref="事务增强的id" pointcut-ref="配置的切入点表达式的id -->myPoint"/>
</aop:config>
1.9.2、注解实现声明事务
<bean id ="txtManager" class="DataSourceTransactionManager">
<proprty name="dataSource" ref="DataSource的Bean的Id"></proprty>
</bean>
<tx:annotation-driven transaction-manager="设定的事务管理Bean的id">
在类名上加@Transactional可为该类下的所有方法加入事务
在方法上写@Transactional为该方法加入事务
事务规则在@Transactional(事务规则)
1.9.3、事务规则
read-only:事务是否为只读,默认false
rollback-for:设定能够触发回滚的异常类型,默认只有runtime Exception才触发事务回滚
no-rollback-for:设定不触发回滚的异常类型,默认 checked Exception不触发事务回滚
2、SpringMVC
2.1、Spring mvc介绍
SpringMVC框架是以请求为驱动,围绕Servlet设计,将请求发给控制器,然后通过模型对象,分派器来展示请求结果视图。
其中核心类是DispatcherServlet,它是一个Servlet,顶层是实现的Servlet接口。
MVC是一个架构,或者说是一个设计模式,它就是强制性使应用程序的输入,处理和输出分开。将一个应用程序分为三个部分:Model模型,View视图,Controller控制器
2.1.1、MVC执行流程
用户 → 发送请求 → 前端控制器(DispacherServlet类) → 发到控制器 → 控制器拿到结果 → 控制器发送视图 →
前端控制器(收回控制权,根据视图名选择相应的视图页面) → 将页面发送给客户端
2.1.2、MVC主要类
-
DispacherServlet
核心类,在web.xml文件中进行配置生成
-
Handler
处理器对应控制器方法,标注了@RequestMapping的方法都可以看做是一个Handler
-
ModelAndView
模型视图,在控制器类中也可以只返回String类型的视图名
-
HandlerMapping
处理器映射,告知控制器类由哪个控制器处理这个URL请求
BeanNameUrlHandlerMapping组件
当没有注解标明拦截什么请求时,根据Bean的name拦截,转到指明的控制器类
DefaultAnnotationHandlerMapping组件
将请求映射到标注@RequestMapping的方法上
-
HandlerAdapter
适配器,使用Handler来操作的对象
AnnotationHandlerMapping组件
RequestMappingHandlerAdapter组件
-
ViewReslover
视图解析器,将传过来的视图名转为一个视图
2.2、配置文件实现MVC
web.xml配置
<servlet>
<servlet-name>自定义类名1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--表示优先加载该类-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>自定义类名1</servlet-name>
<!--/指拦截.html请求-->
<url-pattern>/</url-pattern>
</servlet-mapping>
springmvc-servlet.xml配置
<!--表示将拦截到的请求中筛选出index.html请求将其转发到指定控制器类名中-->
<bean name="/index.html" class="包名.控制器类名"></bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<!--在返回的视图名前加上 /WEB-INF/jsp/ 前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--在返回的视图名后加上 .jsp 后缀-->
<property name="suffix" value=".jsp"/>
</bean>
控制器类
public class 控制器类名 extends AbstractController{
//将拦截到的请求进入该方法并返回另一个视图名
protected ModelAndView handleRequestInternal(HttpServletRequest arg0,HttpServletResponse arg1) throws Exception {
return new ModelAndView("视图名");
}
}
2.3、注释实现MVC
@Controller 标注了该注解的Bean(类)就是一个控制器类
@RequestMapping 放在控制器类的方法上,用来拦截请求
web.xml配置
<servlet>
<servlet-name>自定义类名1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--表示优先加载该类-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>自定义类名1</servlet-name>
<!--/指拦截.html请求-->
<url-pattern>/</url-pattern>
</servlet-mapping>
springmvc-servlet.xml配置
<mvc:annotation-driven/>
<context:component-scan base-package="包含了注释控制器类的包名"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<!--在返回的视图名前加上 /WEB-INF/jsp/ 前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--在返回的视图名后加上 .jsp 后缀-->
<property name="suffix" value=".jsp"/>
</bean>
控制器类
@Controller
public class 控制器类名 extends AbstractController{
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest arg0,HttpServletResponse arg1) throws Exception {
return new ModelAndView("demo");
}
//表示拦截indexTwo请求与indexThree请求
@RequestMapping({"/index.html","/indexThree.html"})
public ModelAndView indexTwo(){
return new ModelAndView("demo");
}
}
2.3.1、RequestMapping
//@RequestMapping("/demo")
@Controller
public class 控制器类名 extends AbstractController{
//可以在类上部加入了@RequestMapping("demo/"),添加后要输入 demo/index才可以筛选到该请求
//@RequestMapping("/index.html",method="RequestMethod.GET") 只拦截get请求
//@RequestMapping("/index.html", Params="参数名") 方法体的变量名要与该参数名一致
@RequestMapping({"/index.html","/indexThree.html"})
public ModelAndView indexTwo(@RequestParam 变量类名 变量名){
return new ModelAndView("demo");
}
}
2.4、MVC参数传递
2.4.1、方法中加参
//在运行对应的URL时,在 URL后?参数名:值 当参数名与变量名不一致时,值为null
@RequestMapping({"/index.html","/indexThree.html"})
//可用@RequestParam(value="值",required="true" 为true表示参数名可与变量名不一致 defaultValue="没参数时的默认值" )
public ModelAndView indexTwo(@RequestParam 变量类名 变量名){
System.out.print(变量名);
return new ModelAndView("demo");
}
2.5、向视图发送数据
2.5.1、ModelAndView
@Controller
public class 控制器类名 extends AbstractController{
//表示拦截indexTwo请求与indexThree请求
@RequestMapping("/indexThree.html")
public ModelAndView indexTwo(){
ModelAndView model = new ModelAndView("视图名");
//添加数据键值对
model.addObject("key",Object 值);
//添加map集合多条数据
model.addAllObjects(Map<string,值>);
//设置视图名
model.setViewName("视图名");
model.setView(视图);
return new ModelAndView("demo");
}
}
//在返回的页面中通过 ${key的值进行取值使用}
2.5.2、string类型
//可将Model该为 public String 方法名(变量类型 变量名,Map<String,Object> model)
public String 方法名(变量类型 变量名,Model model){
//当不指定key值时,会根据数据类型的类名全小写来作为key值,例如:字符串则key为string,User类则key为user
model.addAttribute("Key","值");
return "视图名";
}
3、获得Bean的两种方式
applicationContext & BeanFactory区别
-
BeanFactory接口
(1) spring的原始接口,针对原始接口的实现类功能较为单一
(2)BeanFactory接口实现类的容器,特点是每次在获得对象时才会创建对象 -
ApplicationContext接口
(1)每次容器启动时就会创建容器中配置的所有对象
(2)提供了更多功能
(3)从类路径下加载配置文件: ClassPathXmlApplicationContext
从硬盘的绝对路径下加载配置文件:FileSystemXmlApplication
.BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
BeanFacotry延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用 ApplicationContext。
应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。