springMVC框架

打开资料 https://github.com/brianway/springmvc-mybatis-learning SpringMVC 和 MyBatis 学习笔记,搭配示例,主要讲解一些基础的概念、用法和配置

[完整登录流程分析] 参考 https://www.cnblogs.com/haolnu/p/7294533.html

web.xml

<context-param>的作用:
web.xml的配置中<context-param>配置作用
1. 启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> 和 <context-param></context-param>

2.紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文.

3.容器将<context-param></context-param>转化为键值对,并交给ServletContext.

4.容器创建<listener></listener>中的类实例,即创建监听.

5.在监听的类中会有一个contextInitialized(ServletContextEvent event)初始化方法,在这个方法中可以通过event.getServletContext().getInitParameter("contextConfigLocation") 来得到context-param 设定的值。在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法.用于关闭应用前释放资源,比如说数据库连接的关闭。

6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早.
换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行.

7.举例.你可能想在项目启动之前就打开数据库.
那么这里就可以在<context-param>中设置数据库的连接方式,在监听类中初始化数据库的连接.

8.这个监听是自己写的一个类,除了初始化方法,它还有销毁方法.用于关闭应用前释放资源.比如说数据库连接的关闭.

https://www.cnblogs.com/xuyuanjia/p/5847790.html

由上面的初始化过程可知容器对于web.xml的加载过程是context-param >> listener  >> fileter  >> servlet

如何使用
1.页面中
${initParam.contextConfigLocation}

2.Servlet中
String paramValue=getServletContext().getInitParameter("contextConfigLocation")

如果我们有配置ContextLoaderListener, Spring会去web.xml中看我们是否有定义contextConfigLocation这个参数,如果有则Spring容器(Bean工厂)会把定义在该xml文件中的bean加载到容器中,那如果没有定义contextConfigLocation参数,Spring容器会到一个约定的地方去找该文件[源码存在于XmlWebApplicationContext.]

 

在springmvc这个框架中,一般spring默认存在两个配置文件,一个是applicationContext.xml,另一个是spring-servlet.xml。一般情况下,我们会把注解中的自动加载,定时器的自动加载等内容写在spring-servlet.xml。

        <!-- 加载属性文件 -->
        <context:property-placeholder location="classpath:resource.properties"/>
        <!-- 配置扫描 器 -->
        <context:component-scan base-package="cn.itcast.core.web.controller"/>
        <!-- 配置处理器映射器  适配器 -->
        <mvc:annotation-driven/>
        
        <!-- 配置视图解释器 jsp -->
        <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <property name="suffix" value=".jsp"/>
        </bean>

然后把spring-servlet.xml,放在web.xml文件下的servlet中进行初始化。(<servlet><init-param><param-name>)

而将applicationContext.xml配置成全局的形式(<context-param><param-name>contextConfigLocation</param-name>
--->服务器启动即刻知道内容                                                       <param-value>classpath:applicationContext-*.xml</param-value>)

注: spring框架在加载web配置文件的时候。首先加载的是context-param配置的内容,而并不会去初始化servlet。只有进行了网站的跳转,经过了DispatcherServlet的导航的时候,才会初始化servlet,从而加载init-param中的内容。

详解contextConfigLocation|Spring启动过程详解

Spring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。他们都可代表Spring容器,Spring容器是生成Bean实例的工厂,并且管理容器中的Bean。

[部分源码分析] https://blog.csdn.net/weixin_36344031/article/details/83419784

过程全分析 https://blog.csdn.net/yilaguandemei/article/details/79589729

org.springframework.web.context.ContextLoaderListener类型是springframework中的原始加载上下文的监听器,通常我们会自定义一个Listener去继承ContextLoaderListener并另外实现我们需要初始化的接口(通常我们会选择实现一些接口来对session的管理) 

当监听器设置好了之后 ,启动web容器 监听器开始启动ContextLoaderListener类中的方法contextInitialized() 

方法中有下面的语句 ,就会借助容器的上下文去初始一个spring的应用上下文,使用到了ContextLoader这个类 

this.contextLoader.initWebApplicationContext(event.getServletContext());

ContextLoader初始化时可以看到一块static代码 : 属性文件中这样定义----引用---->

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext

这样我们就能根据属性文件中的定义反射出一个XmlWebApplicationContext上下了 

接着在XmlWebApplicationContext中看到默认加载spring文件的启动位置

public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; 

之后再看ContextLoader类,我们就会看到传说中的参数contextConfigLocation 

而XmlWebApplicationContext对象正是调用了这个参数去设置启动位置 

wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));  

再看XmlWebApplicationContext继承的AbstractRefreshableConfigApplicationContext类中的setConfigLocation方法将此抽象类中的String[] configLocations值填充 ,在AbstractRefreshableConfigApplicationContext类中支持spring对默认启动文件位置和配置启动文件位置

protected String[] getConfigLocations() {  
    return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());  

 

 

spring学习-ApplicationContext-spring上下文深入理解

创建Spring容器实例时,必须提供Spring容器管理的Bean的详细配置信息。Spring的配置信息通常采用xml配置文件来设置 , XML配置文件通常使用Resource对象传入。Resource接口是Spring提供的资源访问接口,通过使用该接口,Spring能够以简单、透明的方式访问磁盘、类路径以及网络上的资源。 对于Java EE应用而言,可在启动Web应用时自动加载ApplicationContext实例接受Spring管理的Bean无须知道ApplicationContext的存在。

开发者只要在web.xml文件中配置一个Listener,该Listener将会负责初始化Spring容器。在这种情况下,容器中Bean处于容器管理下,无须主动访问容器,只需要接受容器的注入管理即可。同时Bean实例的依赖关系通常也是由容器注入,无须Bean实例主动请求。

 

 

 

springmvc配置文件

IOC

IoC (DI是对IoC更准确的描述:由容器动态的将某种依赖关系注入到组件中,实现原理:通过反射创建实例;容器加载过程:创建配置文件的抽象资源,beanfactory,把BeanDefinitionReader配置给beanfactory) 

在IOC容器中配置bean:

使用标签来将一个类配置到IOC容器

获取IOC容器:

Spring提供两种IOC容器: 

  1. ApplicationContext容器 (ApplicationContext接口,可以代表spring容器,是生产及管理bean的工厂)
  2. BeanFactory容器(已废弃)

获取ApplicationContext容器:

/**
         * ApplicationContext代表IOC容器
         * ClassPathXmlApplicationContext从类路径下读取配置文件
         * FileSystemXmlApplicationContext从文件系统路径下读取配置文件
         * WebXmlApplicationContext:在web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
         */
        ApplicationContext context = new FileSystemXmlApplicationContext("config/beans.xml") ;

从IOC容器中获取bean的三种方式

bean的属性注入两种方式 

<!-- ref:引用其他已配置的bean -->

以上参考 https://blog.csdn.net/u013634252/article/details/80946404 [棒]

在Spring配置文件中开启注解扫描 :

<!-- 开启注解的扫描。到配置的包里面扫描类、方法、属性上面是否有注解 -->
<context:component-scan base-package="cn.itcast"></context:component-scan>

注意:也可以这样开启注解扫描,如下:

<context:annotation-config></context:annotation-config>

但是这种开启注解扫描的方式,只会扫描属性上面的注解。实际开发中用到的并不多!故不推荐使用。

  1. @Component:作用在类上
  2. @Repository:用于对DAO实现类进行标注(持久层)。
  3. @Service:用于对Service实现类进行标注(业务层)。
  4. @Controller:用于对Controller实现类进行标注(WEB层)。

后三个注解是Spring中提供的@Component的三个衍生注解(功能目前来讲是一样的),它们是为了让标注类本身的用途更清晰

bean的作用范围的注解: 

@Scope

  • singleton:单例,默认值
  • prototype:多例 

根据经验,对有状态的Bean应使用prototype作用域,而对无状态的Bean则应该使用singleton作用

 

AOP

面向切面编程 将交叉业务封装成切面类 植入到目标业务逻辑中去

Spring提供的AOP,利用AOP实现系统的日志管理功能

实现的大致思路是:

    1.前期准备,设计日志表和日志类,编写日志Dao和Service以及实现

    2.自定义注解,注解中加入几个属性,属性可以标识操作的类型(方法是做什么的)

    3.编写切面,切点表达式使用上面的注解直接定位到使用注解的方法,

    4.编写通知,通过定位到方法,获取上面的注解以及注解的属性,然后从session中直接获取或者从数据库获取当前登录用户的信息,最后根据业务处理一些日志信息之后调用日志Service存储日志。

https://www.jianshu.com/p/a6ba33da545b 参考

spring 配置扫描切面,开启@AspectJ注解的支持

继承统一的ContentGenerator类,便于共享一些常量。

https://blog.csdn.net/hanruikai/article/details/79315766 含有非注解方式

1.日志表@Table(name = "t_log")

   日志类 Dao (Log.java<....private String content;>    public interface LogRepository extends JpaRepository<Log, Integer>)

    Service及实例

/** 定义一个方法,用于声明切入点表达式,方法中一般不需要添加其他代码 * 使用@Pointcut声明切入点表达式 * 后面的通知直接使用方法名来引用当前的切点表达式;如果是其他类使用,加上包名即可 */

2.自定义注解?

3.切面 配置注解定位方法

4.方法增强 调用service存储日志

以后可以参考写 https://www.cnblogs.com/parryyang/p/5881523.html

 

slf4j是日志的接口(只定义了一些方法而没有去实现),和commons-logging一样。而log4j是具体的实现(即怎么来打印日志等),和logback是一样的。这里的slf4j-logo可以是log4j,可以是jdk的日志,可以是logback,还可以是slf4j-simple等等。这里其实用到了一种设计模式(Facade设计模式,门面设计模式)。

SLF4J所提供的核心API是一些接口以及一个LoggerFactory的工厂类。而在使用SLF4J的时候,不需要在代码中或配置文件中指定你打算用那个具体的日志系统。只需要在项目中加入定的slf4j-logo.jar包就可以。这个和Spring的IOC思想有点像,想用哪个就用哪个,随意切换。

切换参考 https://blog.csdn.net/qq_38136705/article/details/81055277

非注解方式的日志 有点儿类似~~!https://blog.csdn.net/liu_desheng/article/details/81589015 

如果注解@Slf4j注入后找不到变量log,需要IDEA安装lombok插件,

@Slf4j注解实现日志输出 

然后在类上写上@Slf4j注解 在方法中直接使用 logger ,@Slf4j替代掉了冗余的logger声明语句

private final Logger logger = LoggerFactory.getLogger(LoggerTest.class);

JpaRepository支持接口规范方法名查询。意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现, JpaRepository继承自PagingAndSortingRepository接口,JpaRepository基于JPA的Repository接口,极大减少了JPA作为数据访问的代码,JpaRepository是实现Spring Data JPA技术访问数据库的关键接口。

Spring Data(提供了一整套数据访问层(DAO)的解决方案,致力于减少数据访问层(DAO)的开发量。它使用一个叫作Repository的接口类为基础,它被定义为访问底层数据模型的超级接口。)给我们提供几个Repository(类似于我们通常所说的DAO数据访问层),基础的Repository提供了最基本的数据访问功能,其几个子接口则扩展了一些功能。它们的继承关系如下: 
Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类,方便Spring自动扫描识别 
CrudRepository: 继承Repository,实现了一组CRUD相关的方法 
PagingAndSortingRepository: 继承CrudRepository,实现了一组分页排序相关的方法 
JpaRepository: 继承PagingAndSortingRepository,实现一组JPA规范相关的方法 

JpaRepository<T, ID extends Serializable> 
这个接口提供了JPA的相关功能 
List<T> findAll();//查找所有实体 
        List<T> findAll(Sort sort);//排序 查找所有实体 
        List<T> save(Iterable<? extends T> entities);//保存集合 
        void flush();//执行缓存与数据库同步 
        T saveAndFlush(T entity);//强制执行持久化 
void deleteInBatch(Iterable<T> entities);//删除一个实体集合 

 

 

spring声明式事务实现原理: 主要得益于springMVC+AOP,使用一个事务拦截器,在方法调用的前后/周围进行事务增强(advice),来驱动事务完成.
AOP(实现原理:动态代理JDKProxy &cglibProxy两者区别,Spring的AOP是cglibProxy实现--两者区别:JDK动态代理只能用于带接口的,CGLIB带不带接口都行),只有public方法上的事务注解才起作用,而且必须在代理类外部调用才行~

Spring事务管理的亮点在于声明式事务管理,Spring允许通过声明的方式,在IoC配置中指定事务的边界和事务属性,Spring会自动在指定的事务边界上应用事务属性。

spring将事务管理委托底层具体的持久化实现框架去完成,因此针对不同的框架spring有的不同的接口实现类.

要实现事务管理,首先要在Spring中配置好相应的事务管理器,为事务管理器指定数据资源及一些其他事务管理控制属性。-->

-->Spring JDBC 和MybBatis都是基于数据源的Connection访问数据库,所以都可以使用DataSourceTransactionManager

 

Spring将JDBC的Connection、Hibernate的Session等访问数据库的连接或者会话对象统称为资源,这些资源在同一时刻是不能多线程共享的。为了让DAO、Service类可能做到singleton, Spring的事务同步管理类org.springframework.transaction.support.TransactionSynchronizationManager使用ThreadLocal不同事务线程提供了独立的资源副本,同时维护事务配置的属性和运行状态信息。事务同步管理器是Spring事务管理的基石,不管用户使用的是编程式事务管理,还是声明式事务管理,都离不开事务同步管理器。Spring框架为不同的持久化技术提供了一套从TransactionSynchronizationManager中获取对应线程绑定资源的工具类

*Spring  如何管理事务?(抽象层的三个接口:PlatformTransactionManager,TransactionDefinition,TransactionStatus)

PlatformTransactionManager根据TransactionDefinition提供的事务属性配置信息创建事务,并用TransactionStatus描述这个激活事务的状态。[TransactionStatus接口可以让事务管理器控制事务的执行,可以检查事务是不是一个新事务,或者是否只读。TransactionStatus还可以初始化回滚操作]

切面(Aepect):横切关注点(跨越应用程序多个模块的功能)被模块化的对象;

通知(Advice):切面必须要完成的工作;  ---->增强: 其中一个为ThransactionInterceptor ,它实现了advice接口,包含了把事务加进去的逻辑,也就是事务增强

目标(Target):被通知的对象;

代理(Proxy):像目标对象应用通知之后创建的对象;

连接点(Joinpoint):程序执行的某个特殊位置,如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;想对点表示的方位<是一个运行时的概念,只有运行时才存在>-->这里仍然用"源"获取事务属性,这才是真正用于事务.

切点(pointcut):每个类都拥有多个连接点,即连接点是程序类中客观存在的事务;----> TransactionAttributeSource<它是一个源,向外提供东西的意思,TransactionAttribute是事务属性的意思>不是pointcut,但它被pointcut所用,用于检测一个类的方法上是否有@Transaction注解,来确定该方法是否需要加强<TransactionAttributeSourcepointcut用于标识被拦截的方法---是一个静态概念> 

[整体的意思: pointcut拦截方法,然后使用"源"去方法和类上获取事务属性<用于判断>,如获得则说明方法需要参与事务,进行事务增强] 

AOP通过切点定位到特定的连接点。

AOP的主要编程对象是切面(aopect),而切面模块化横切关注点

AOP中 advisor = pointcut + advice

savepoint 当执行rollback时,通过指定保存点可以回退到指定的点。注意:这个回退事务,必须是没有commit前使用的;
如果事务提交了,那么无论你刚才做了多少个保存点,都统统没有。 如果没有手动执行commit,而是exit退出会话了,那么会自动提交 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值