Spring与SpringMVC笔记记录

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获取连接点的方法签名对象
ObjectgetTarget()获取连接点所在的目标对象
ObjectgetThis()获取代理对象本身

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&amp;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&amp;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 ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值