Spring、SpringMVC、Shiro、Maven
一、Spring
Spring是一个为了解决企业应用程序开发复杂性而创建的开源框架,其核心是IOC–控制反转、AOP–面向切面编程。
框架的主要优势之一就是其分层架构(WEB层(springMvc)、业务层(Ioc)、持久层(jdbcTemplate)),分层架构允许选择使用哪一个组件,同时为J2EE(Java 2 Platform Enterprise EditionJava 2 平台企业版)应用程序开发提供集成的框架。
Spring是非侵入性的,这意味着业务逻辑代码可以不依赖于框架本身,开发人员可以专注于业务功能的实现,而不必关心框架内部的处理逻辑。
Spring 与 Spring Boot的区别
SpringBoot就是一个轻量级,简化配置和开发流程的web整合框架。
下面讨论Spring和Spring Boot之间的主要区别:
Spring Boot可以建立独立的Spring应用程序;
内嵌了如Tomcat,Jetty和Undertow这样的容器,也就是说可以直接跑起来,用不着再做部署工作了;
无需再像Spring那样搞一堆繁琐的xml文件的配置;
可以自动配置(核心)Spring。SpringBoot将原有的XML配置改为Java配置,将bean注入改为使用注解注入的方式(@Autowire),并将多个xml、properties配置浓缩在一个appliaction.yml配置文件中。
提供了一些现有的功能,如量度工具,表单数据验证以及一些外部配置这样的一些第三方功能;
整合常用依赖(开发库,例如spring-webmvc、jackson-json、validation-api和tomcat等),提供的POM可以简化Maven的配置。当我们引入核心依赖时,SpringBoot会自引入其他依赖。
Spring | Spring Boot |
Spring Framework是用于构建应用程序的广泛使用的Java EE框架。 | Spring Boot Framework被广泛用于开发REST API。 |
它旨在简化Java EE开发,从而使开发人员更加高效。 | 它旨在缩短代码长度,并提供最简单的方法来开发Web应用程序。 |
Spring Framework的主要功能是依赖项注入。 | Spring Boot的主要功能是自动配置,它会根据需求自动配置类。 |
通过允许我们开发松耦合应用程序,它可以使事情变得更简单。 | 它有助于创建配置更少的独立应用程序。 |
开发人员编写了大量代码(样板代码)来完成最小的任务。 | 它减少了样板代码。 |
为了测试Spring项目,需要显式设置服务器。 | Spring Boot提供了Jetty和Tomcat等嵌入式服务器。 |
它不提供对内存数据库的支持。 | 它提供了几个插件来处理嵌入式和内存数据库(例如H2)。 |
开发人员在pom.xml中手动定义Spring项目的依赖项。 Spring Boot在pom.xml文件中带有启动程序的概念,该文件在内部负责根据Spring Boot Requirement下载依赖项JAR。 |
Spring MVC的工作流程
Spring Boot与Spring MVC的区别
Spring MVC是Spring基础之上的一个MVC模式的WEB开发框架,涵盖面包括前端视图开发、文件配置、后台接口逻辑开发等,XML、config等配置相对比较复杂。
SpringBoot框架相对于SpringMVC框架来说,更专注于开发微服务后台接口,不开发前端视图,同时遵循默认优于配置,简化了插件配置流程,不需要配置xml,相对Springmvc,大大简化了配置流程。
Spring Boot和Spring MVC出于不同的目的而存在。 下面讨论了Spring Boot和Spring MVC之间的主要区别:
Spring Boot | Spring MVC |
Spring Boot是Spring的模块,用于使用合理的默认值打包基于Spring的应用程序。 | Spring MVC是Spring框架下基于模型视图控制器的Web框架。 |
它提供了默认配置来构建Spring支持的框架。 | 它提供了用于构建Web应用程序的即用型功能。 |
无需手动构建配置。 | 它需要手动进行构建配置。 |
不需要部署描述符。 | 部署描述符是必需的。 |
它避免了样板代码,并将依赖项包装在一个单元中。 | 它分别指定每个依赖项。 |
它减少了开发时间并提高了生产率。 | 实现相同目的需要更多时间。 |
总结:
1、Spring框架就像一个家族,有众多衍生产品例如:boot、security、jpa等等。但它们的基础都是Spring的ioc、aop等;ioc提供了依赖注入的容器,aop解决了面向横切面编程,然后在此两者的基础上实现了其他产品的高级功能;
2、SpringMVC主要解决WEB开发的问题,是基于Servlet的一个MVC框架,通过XML配置,统一开发前端视图和后端逻辑。
由于Spring的配置非常复杂,各种XML、JavaConfig、Servlet处理起来比较繁琐,为了简化开发者的使用,从而创造性地推出SpringBoot框架,默认优于配置,简化了SpringMVC的配置流程;但区别于SpringMVC的是,SpringBoot专注于单体微服务接口开发,和前端解耦,虽然SpringBoot也可以做成SpringMVC前后台一起开发,但是这就有点不符合springBoot框架的初衷了。
https://www.yiibai.com/spring-boot/spring_boot_introduction.html
Spring框架优点?
1、方便解耦、简化开发
Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给Spring容器管理,大大的降低了组件之间的耦合性。
2、支持AOP
Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事务、日志等进行集中式处理,从而提高了程序的复用性。
3、支持声明式事物管理
方便对程序进行声明式事物管理,无需手动编程,提高开发效率和质量。
4、方便程序的测试
Spring提供了对Junit4的支持,可以通过注解方便的测试Spring程序。
5、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持。
6、降低Java EE API的使用难度
Spring对Java EE开发中非常难用的一些API(如:JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。
7、非侵入式框架
Spring是一种非侵入式(non-invasive)框架,能减少应用程序对框架的依赖。
谈谈你对Spring IOC和DI的理解,它们有什么区别?
Spring IOC全面认知:https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484247&idx=1&sn=e228e29e344559e469ac3ecfa9715217&chksm=ebd74256dca0cb40059f3f627fc9450f916c1e1b39ba741842d91774f5bb7f518063e5acf5a0&scene=21##wechat_redirect
IoC(思想,设计模式)主要的实现方式有两种:依赖查找,依赖注入。
依赖注入是一种更可取的方式(实现的方式)。
IOC控制反转:将对象的创建,查找依赖,以及生命周期的控制权交给了Ioc容器。对象之间耦合较松,更加灵活。
依赖注入跟控制反转其实是从不同的方向表达同一种思想,依赖注入说的是对象的获取需要依赖spring ioc容器,当需要处理对象间的依赖关系时,spirng ioc容器会将需要的对象依赖关系注入到相应的对象中,不需要我们主动去创建对象。
依赖注入(DI),Spring 使用 javaBean 对象的 set 方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程,就是依赖注入的思想。
IoC 具体的实现方式是依赖注入。
简单的说之前我们在代码中创建一个对象是通过 new 关键字,而使用了 Spring 之后,我们不在需要自己去 new 一个对象了,而是直接通过容器里面去取出来,再将其自动注入到我们需要的对象之中,也就说创建对象的控制权不在我们程序员手上了,全部交由 Spring 进行管理。
交给 Spring 管理的也称为 Bean,所有的 Bean 都被存储在一个 Map 集合中,这个 Map 集合也称为 IoC 容器。
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。
比如说,在实际项目中一个 Service 类可能有几百甚至上千个类作为它的底层,假如我们需要实例化这个 Service,你可能每次都要搞清这个 Service 所有底层类的构造函数,这显然过于繁琐。如果利用 IoC 的话,你只需要配置好,然后在需要的地方引用就行了,这大大增加了项目的可维护性且降低了开发难度。
什么是AOP,AOP 的作用是什么?
面向切面编程(Aspect Oriented Programming(AOP)),是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
切面,指的是项目模块中某些业务逻辑。面向切面编程通俗一点就是面向业务的一种编程思想(当然业务需要一定的共性),然后通过代理完成类的创建,极大程度的降低代码的重复,有效的提高了代码的重用率和开发效率。
面向切面编程(AOP),在面向对象编程(oop)思想中,我们将事物纵向抽成一个个的对象。而在面向切面编程中,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制、事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。AOP 底层是动态代理,如果是接口采用 JDK 动态代理,如果是类采用CGLIB 方式实现动态代理。
Spring里面如何配置数据库驱动?
“org.springframework.jdbc.datasource.DriverManagerDataSource”数据源来配置数据库驱动。
示例如下:
<bean id=”dataSource”><property name=”driverClassName”><value>org.hsqldb.jdbcDriver</value></property><property name=”url”><value>jdbc:hsqldb:db/appfuse</value></property><property name=”username”><value>sa</value></property><property name=”password”><value></value></property>
</bean>
JDBC注册驱动方式
1、Class.forName("com.mysql.cj.jdbc.Driver");通过Class把类先装载到java的虚拟机中,并没有创建Driver类的实例。
最常见的注册驱动方式,也是推荐的注册方式,参数使用字符串,所以移植性好。
好处在于不依赖指定的驱动,也就减少了代码的依赖性,可以更改为在配置文件中配置,从而动态更新数据库驱动。
2、System.setProperty(“jdbc.drivers”,”com.mysql.cj.jdbc.Driver”);通过系统的属性设置注册驱动。
可以同时注册多个驱动,如System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver:com.Oracle.jdbc.Driver");
这种驱动注册方式很少使用。
3、实例化new com.mysql.jdbc.Driver();
这样的话我们不需要使用DriverManager.registerDriver(new Driver())去注册驱动,因为在com.mysql.cj.jdbc.Driver的静态代码块中已经帮我们完成了这样的操作。
数据连接池的工作机制是什么?
因为我们在操作数据库的时候 ,打开连接和关闭连接是耗时,耗性能,我们希望通过种机制减少这种开销,这就是数据连接池的初衷。
连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。
使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理,这样就能提高我们的访问性能。
同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。
Spring配置bean实例化有哪些方式?
1.使用类构造器实例化
2.使用工厂方法(静态工厂方法、实例工厂方法)
3.实现FactoryBean接口
使用类构造器实例化:
在配置bean时,使用class属性指定类的全名称(即全类名)
工厂方法实例化
1.静态工厂方法:
方法就是将对象创建过程封装到静态方法中,当客户端需要对象时,只需要简单的调用静态方法。
要声明通过静态方法创建的bean,需要在bean的class属性中指定拥有该工厂方法的类,同时在factory-method属性中指定工厂方法的名称,最后使用元素为该方法传递方法参数
静态方法如下所示:
public class FruitFactory {public static Fruit createApple() {Fruit fruit = new Fruit();fruit.setType("apple");return fruit;}public static Fruit createPear() {Fruit fruit = new Fruit();fruit.setType("pear");return fruit;}}
bean.xml中的配置如下所示
2.实例工厂方法配置方式:
将对象的创建过程封装到另一个对象实例的方法中。当客户端需要请求对象时,只需要简单的调用该实例方法。
使用方式:
先声明要使用实例化方法创建的bean
在第二个bean的factory-bean属性里指定拥有该工厂方法的bean
在factory-method属性里面指定该工厂方法的名称
实例方法如下所示:
public class FruitFactory {//实例工厂方法public Fruit createPeach(){Fruit fruit = new Fruit();fruit.setType("Peach");return fruit;}
}
bean中的配置如下所示(无参数)
<bean id="fruitFactory" class="anhui.FruitFactory"></bean>
<bean id="peach" factory-bean="fruitFactory" factory-method="createPeach"></bean>
如果有参数,bean中的配置情况如下
<bean id="fruitFactory" class="anhui.FruitFactory"></bean>
<bean id="peach" factory-bean="fruitFactory" factory-method="createPeach"><constructor-org>index="0" value="peach"</constructor-org>
</bean>
3.使用FactoryBean接口进行实例化
FactoryBean:由Spring提供
getObjectType:返回bean的实例
isSingleton:返回的bean是否是单例的。
配置时:
class指定为上面创建的FactoryBean实现类。实际返回的是FactoryBean的getObject方法返回的实例。
Property:为实现类的property
实现类代码如下所示:
import org.springframework.beans.factory.FactoryBean;public class FruitFactoryBean implements FactoryBean {//指定创建对象的方法public Fruit getObject() throws Exception {Fruit fruit = new Fruit();fruit.setType("strawberry");return fruit;}public Class<?> getObjectType() {return Fruit.class;}public boolean isSingleton() {return true;}
}
bean中的配置如下所示:
<bean id="strawberry" class="wanho.FruitFactoryBean"></bean>
请介绍一下Spring框架中 Bean 的生命周期和作用域
Bean 的生命周期
1. 实例化 Bean (不等于初始化) 【分配内存空间】
2. 设置属性【依赖注入DI】
3. Bean 的初始化
执行各种通知
初始化的前置方法. (以前是通过在 xml 中配置 init-method() 方法, 之后改用 @PostConstruct 注解)
初始化方法
初始化的后置方法
4. 使用 Bean
5.销毁 Bean. (以前通过 xml 的 destroy-method, 之后改用 @PreDestroy 注解)
Bean 的六大作用域
1. singleton:单例作⽤域
2. prototype:原型作⽤域(也叫多例作⽤域)
3. request:请求作⽤域
4. session:会话作⽤域
5. application:全局作⽤域
6. websocket:HTTP WebSocket 作⽤域
前两种作用域是在普通的 Spring 项目中使用,后四种作用域存在于 Spring MVC 项目中。(前四种要知道)
1.1.1 单例作用域 (singleton)
含义: 单例作用域是指在 Spring IoC 容器中只存储一份, 也就是说只有一个实例, 无论我们是通过 @Autowried, @Resource 去获取, 还是通过上下文对象去 getBean(), 拿到的 bean 对象都是同一份. (并且单例作用域是 Spring 中默认的作用域)
场景: 通常是无状态的 Bean 使用的作用域. (无状态表示 Bean 对象的属性状态不需要修改)
1.1.2 原型作用域 (prototype),原型作用域也叫作多例作用域
含义: 原型作用域也叫作多例作用域, 每次从 Spring 中获取 Bean 对象, 都会创建一份新的实例, @Autowired, @Resource 注入的对象以及 context 上下文 getBean 拿到的都是不同的 bean 对象。
场景: 通常是有状态的 Bean 使用的作用域 (有状态表示 Bean 对象的属性需要被修改)
1.1.3 请求作用域 (request)
含义: 每一次 HTTP 请求都会创建新的实例, 类似于 prototype.
场景: 一次 HTTP 的请求和响应共享一个 bean。(仅在 Spring MVC 中使用)
1.1.4 会话作用于 (session)
含义: 在一个 HTTP session 中, 定义一个 Bean 实例.
场景: 同一个用户的会话共享 Bean (例如在登录场景中记录一个用户的登录信息) 仅在 Spring MVC 中使用
1.1.5 全局作用于 (application)
含义: 在一个 HTTP Servlet Context 中, 定义一个 Bean 实例
场景: Web 应用的上下文信息, 记录一个应用的共享信息.(仅在 Spring MVC 中使用)
application 作用域和 单例作用域还是有区别的, 它只是同一份上下文对象共享同一个 bean, 当再次创建上下文对象时, 调用 getBean() 就是另一个 Bean 对象了.
1.1.6 HTTP WebSocket 作用域 (websocket)
含义: 在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例
场景: WebSocket的每次会话中,保存了⼀个 Map 结构的头信息,将⽤来包裹客户端消息头。第⼀次初始化后,直到WebSocket结束都是同⼀个Bean。(仅在 Spring MVC 中使用)
如何设置Bean的作用域
在Spring中,可以在元素的scope属性里设置bean的作用域,以决定这个bean是单实例的还是多实例的。Scope属性有四个参数(singleton:单例作⽤域、prototype:原型作⽤域(也叫多例作⽤域)、request:请求作⽤域、session:会话作⽤域)
具体的使用可以看下图:
<!-- singleton单实例bean1、在容器创建时被创建2、只有一个实例-->
<bean id="book02" class="com.spring.beans.Book" scope="singleton"></bean>
设置 Bean 的作用域有两种方式:
直接设置: @Scope("prototype")
使用类似枚举的方式设置: @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
1.2.1 直接设置: @Scope("prototype")
@Controller
public class CatBean {@Scope("prototype")@Beanpublic Cat cat() {Cat cat = new Cat();cat.setId(1);cat.setName("加菲猫");cat.setAge(12);return cat;}
}
我们只需要在前面的代码中的 CatBean 类中的 @Bean 注解上加上一个 @Scope 注解, 并设置 "prototype" , 此时我们运行程序, 如果李四拿到的是 "加菲猫", 那么就说明此时是多例作用域。
Bean注入属性有哪几种方式?
构造器注入:利用构造方法的参数注入依赖。
在实体类中添加两个构造方法:有参和无参
//默认构造函数
public Person(){}
//带参构造函数
public Person(Long pid,Student students){this.pid = pid;this.students = students;
}
在 applicationContext.xml 中进行赋值
1、如果Spring的配置文件中的bean中没有<constructor-arg>该元素,则调用默认的构造函数
2、如果Spring的配置文件中的bean中有<constructor-arg>该元素,则该元素确定唯一的构造函数
<!-- 根据构造函数赋值 -->
<!--index 代表参数的位置 从0开始计算type 指的是参数的类型,在有多个构造函数时,可以用type来区分,要是能确定是那个构造函数,可以不用写typevalue 给基本类型赋值ref 给引用类型赋值-->
<bean id="person_con" class="com.ys.di.Person"><constructor-arg index="0" type="java.lang.Long" value="1"></constructor-arg> <constructor-arg index="1" type="com.ys.di.Student" ref="student_con"></constructor-arg>
</bean>
<bean id="student_con" class="com.ys.di.Student"></bean>
Setter注入:调用Setter的方法注入依赖。
创建实体类 为实体类里的属性创建set get方法
在 applicationContext.xml 中进行赋值
如果需要使用set注入,那么必须要为属性提供set方法,Spring容器就是通过调用bean的set方法为属性注入值的。而在xml文件中,使用set注入的方式就是通过property标签,如下所示:
<!-- 定义car这个bean,id为myCar -->
<bean id="myCar" class="cn.tewuyiang.pojo.Car"><!-- 为car的属性注入值,因为speed和price都是基本数据类型,所以使用value为属性设置值;注意,这里的name为speed和price,不是因为属性名就是speed和price,而是set方法分别为setSpeed和setPrice,名称是通过将set删除,然后将第一个字母变小写得出;--><property name="speed" value="100"/><property name="price" value="99999.9"/>
</bean><!-- 定义user这个bean -->
<bean id="user" class="cn.tewuyiang.pojo.User"><property name="name" value="aaa" /><property name="age" value="123" /><!-- car是引用类型,所以这里使用ref为其注入值,注入的就是上面定义的myCar 基本数据类型或Java包装类型使用value,而引用类型使用ref,引用另外一个bean的id --><property name="car" ref="myCar" />
</bean>
字段注入:在字段上使用@Autowired/Resource注解。
构造器注入:强依赖性(即必须使用此依赖),不变性(各依赖不会经常变动)
Setter注入:可选(没有此依赖也可以工作),可变(依赖会经常变动)
Field注入:大多数情况下尽量少使用字段注入,一定要使用的话, @Resource相对@Autowired对IoC容器的耦合更低。
Field注入的缺点
不能像构造器那样注入不可变的对象
依赖对外部不可见,外界可以看到构造器和setter,但无法看到私有字段,自然无法了解所需依赖
会导致组件与IoC容器紧耦合(这是最重要的原因,离开了IoC容器去使用组件,在注入依赖时就会十分困难)
导致单元测试也必须使用IoC容器,原因同上
依赖过多时不够明显,比如我需要10个依赖,用构造器注入就会显得庞大,这时候应该考虑一下此组件是不是违反了单一职责原则
介绍一下Spring的事务管理
Spring事务可以分为两种:
编程式事务(通过代码的方式来实现事务)
声明式事务(通过配置的方式来实现事务),推荐使用(代码侵入性最小),实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)。
编程式事务在Spring实现相对简单一些,而声明式事务因为封装了大量的东西(一般我们使用简单,里头都非常复杂),所以声明式事务实现要难得多。
在编程式事务中有以下几个重要的了接口:
TransactionDefinition:定义了Spring兼容的事务属性(比如事务隔离级别、事务传播、事务超时、是否只读状态)
TransactionStatus:代表了事务的具体运行状态(获取事务运行状态的信息,也可以通过该接口间接回滚事务等操作)
PlatformTransactionManager:事务管理器接口(定义了一组行为,具体实现交由不同的持久化框架来完成---类比JDBC)
@Autowired和@Resource 之间的区别
@Resource、@Autowired都是Spring中用于实现Bean的依赖注入。
@Autowired是由Spring提供的,根据类型注入,默认情况下要求依赖对象必须存在,如果允许null值,可以设置require属性为false。当存在多个相同类型的bean时 可以通过@Primary注解或者@Qualifier注解解决依赖注入冲突。
@Resource是由Java提供的,默认根据name注入,当找不到与名称匹配的bean才会按照类型装配。
通知有哪些类型?
前置通知:在目标方法执行之前执行的通知
后置通知:在目标方法执行之后的通知。
环绕通知:在目标方法执行之前和之后都可以执行额外代码的通知。
异常通知:在目标方法抛出异常时执行的通知
最终通知:在目标方法执行之后执行的通知。和后置通知不同的是,后置通知是在方法正常返回后执行的通知,如果方法没有正常返回,比如说抛出异常,则后置通知不会执行。而最终通知无论如何都会在目标方法调用过后执行,即使目标方法没有正常的执行完成。另外,后置通知可以通过配置得到返回值,而最终通知无法得到。
二、SpringMVC
l.SpringMVC框架是什么?常见的 mvc 框架有哪些?他们的区别是什么?
Model. Veiw Cantnl
2.阐述一下SpringMVC的运行流程
3.Spring MVC的主要组件有哪些 他们的作用是什么?
4.SpringMVC 怎么样设定重定向和转发的?默认是请求转发还是重定向?
5.SpringMvc 怎么和AJAX 相互调用的?
6.SpringMvc 中如何解决 POST 请求中文乱码问题,GET 的又如何处理呢?
7.SpringMvc如何做异常处理 ?
9.SpringMvc常用的注解有哪些?
10.SpringMvc中函数的返回值是什么?
三、Shiro
1.说一下什么是 rbac,设计一个基于 rbac 的数据库模型,并解释每个模型之间的关系
2.说一下什么是 shiro,并且说出 shiro的优点
3.简述Shiro的核心组件
4、简述Shiro认证过程
5、简述Shiro授权过程
四、Maven
1.Maven 有哪些优点和缺点
优点:
是一个模块化的项目构建工具,方便维护与发布。
不需要手工找jar包,去下载。
缺点:
由于需要下载,导入等,导致加载缓慢,或者出现错误,和不稳定
缺少对Maven的文档描述(网上一大堆,但是没有标准)
中央存储库中的元数据不佳
POM.xml做为项目元数据的来源
2.Maven 坐标由什么组成,分别代表什么意思
那 Maven 是通过什么方式精确地找到用户想要的构件呢?
通过构件的坐标去唯一定位查找。反过来也就是说,在 Maven 仓库中,是用坐标标记来一一对应地管理每个构件的。
那坐标又是由哪些信息组成的呢?
一个完整的坐标信息,由 groupId、artifactId、version、packaging、classifier 组成。
如下是一个简单的坐标定义。
org.SpringFramework
spring-core
4.2.7.RELEASE
jar
这是 JUnit 的坐标,下面详细介绍一下各个元素。
1、groupId定义当前 Maven 项目从属的实际项目。
关于 groupId 的理解如下所示。
1)Maven 项目和实际项目不一定是一一对应的。比如 SpringFramework,它对应的 Maven 项目就有很多,如 spring-core、spring-context、spring-security 等。造成这样的原因是模块的概念,所以一个实际项目经常会被划分成很多模块。
2)groupId 不应该同开发项目的公司或组织对应。原因比较好理解,一个公司和一个组织会开发很多实际项目,如果用 groupId 对应公司和组织,那 artifactId 就只能是对应于每个实际项目了,而再往下的模块就没法描述了,而往往项目中的每个模块是以单独的形式形成构件,以便其他项目重复聚合使用。
3)groupId 的表述形式同 Java 包名的表述方式类似,通常与域名反向一一对应。
2、 artifactId定义实际项目中的一个 Maven 项目(实际项目中的一个模块)。
推荐命名的方式为:实际项目名称-模块名称。
比如,org.springframework 是实际项目名称,而现在用的是其中的核心模块,它的 artifactId 为 spring-core。
3、version定义 Maven 当前所处的版本。
如上的描述,用的是 4.2.7.RELEASE 版本。需要注意的是,Maven 中对版本号的定义是有一套规范的。具体规范请参考《版本管理》的介绍。
4、packaging定义 Maven 项目的打包方式。
打包方式通常与所生成的构件文件的扩展名对应,比如,.jar、.ear、.war、.pom 等。另外,打包方式是与工程构建的生命周期对应的。比如,jar 打包与 war 打包使用的命令是不相同的。最后需要注意的是,可以不指定 packaging,这时候 Maven 会自动默认成 jar。
5、classifier定义构件输出的附属构件。
附属构件同主构件是一一对应的,比如上面的 spring-core-4.2.7.RELEASE.jar 是 spring-core Maven spring-core 项目的主构。
Maven spring-core 项目除了可以生成上面的主构件外,也可以生成 spring-core-4.2.7.RELEASE-javadoc.java 和 spring-core-4.2.7.RELEASE-sources.jar 这样的附属构件。这时候,javadoc 和 sources 就是这两个附属构件的 classifier。这样就为主构件的每个附属构件也定义了一个唯一的坐标。
最后需要特别注意的是,不能直接定义一个 Maven 项目的 classifier,因为附属构件不是由 Maven 项目构建的时候直接默认生成的,而是由附加的其他插件生成的。
groupId、artifactId 和 version 是必需的,packaging 是可选的,默认是 jar,而 classifier 是不能直接定义的。同时,Maven 项目的构件文件名与坐标也是有对应关系的,一般规则是 artifactId-version[-classifier].packaging 。
3.pom 文件中常见的标签有哪些,分别代表什么意思
name标签:项目的名称。
version标签:项目的版本号,项目打包后的JAR文件的版本号跟这里对应。
url:指定项目站点,通常用于maven产生的文档中。
description:描述此项目,通常用于maven产生的文档中。
properties:pom文件中的配置信息,可以配置全局变量。
dependencies:依赖配置集,里面可以添加需要的jar的依赖信息。
dependencyManagement标签: 依赖管理标签。
plugins标签:使用的插件列表。
modelVersion标签:声明项目描述符遵循哪一个POM模型版本。模型本身的版本很少改变,虽然如此,但它仍然是必不可少的,这是为了当Maven引入了新的特性或者其他模型变更的时候,确保稳定性。
groupId标签:项目的全球唯一标识符,通常使用全限定的包名区分该项目和其他项目。并且构建时生成的路径也是由此生成, 如com.mycompany.app生成的相对路径为:/com/mycompany/app。
artifactId标签:构件的标识符,它和group ID一起唯一标识一个构件。换句话说,你不能有两个不同的项目拥有同样的artifact ID和groupID;在某个 特定的group ID下,artifact ID也必须是唯一的。构件是项目产生的或使用的一个东西,Maven为项目产生的构件包括:JARs,源 码,二进制发布和WARs等。
parent标签:父项目的坐标。如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值。 坐标包括group ID,artifact ID和 version。
packaging标签:项目产生的构件类型,例如jar、war、ear、pom。插件可以创建他们自己的构件类型,所以前面列的不是全部构件类型。
4.常见的Maven私服的仓库类型有哪些
(宿主仓库)hosted+repositor,(代理仓库)proxy+repository,(仓库组)group+repository。
hosted本地仓库:通常我们会部署自己的构件到这一类型的仓库。
代理仓库作用:
(1)作为仓库作用——可以把常用的jar包拷进去,这样客户端就可以从这里下载了。
(2)作为代理的作用——客户端先从私服下载,若私服没有该jar,客户会通过互联网从中央库下载,同时私服也会将jar从中央库下载到私服,这样下次客户端就可以从私服的代理库中下载。
group:仓库组,用来合并多个hosted/proxy仓库。如下图public Repositories的Configuration标签页下Ordered Group Repositories包含了四个仓库:Releases、Snapshots、3rd party和Central。也就是说我们在pom.xml引用这个仓库组,其包含的仓库也被引用。
5.Maven项目的关系有哪些?
依赖关系:A依赖B
继承关系:B和C的公共依赖、部分依赖被A统一管理
聚合关系:B、C功能模块开发完,被A统一进行聚合成完整的功能或项目。(聚合关系建立在继承关系上)
1. 依赖关系
1.1 标签<dependency>把另一个项目的 jar 引入到当过前的项目
1.2 自动下载另一个项目所依赖的其他项目
2. 继承关系
2.1 父项目是 pom 类型 。
2.2 子项目jar或war,如果子项目还是其他项目的父项目,子项目也是 pom 类型。
2.3 有继承关系后,子项目中出现<parent>标签 。
如果子项目和<groupId>和<version>与父项目项目,在子项目中可以不配置<groupId>和<version>
2.4 父项目 pom.xml 中是看不到有哪些子项目,在逻辑上具有父子项目的关系。
<parent> <groupId>com.bjsxt</groupId> <artifactId>parent</artifactId> <version>0.0.1-SNAPSHOT</version>
</parent>
3. 聚合关系
3.1 前提是继承关系,父项目会把子项目包含到父项目中。
3.2 子项目的类型必须是 Maven Module, 而不是 maven project 。
3.3 新建聚合项目的子项目时,点击父项目中右键新建 Maven -》 Module
3.4 具有聚合关系的父项目,在 pom.xml 中<modules>
<modules> <module>child2</module>
</modules>
3.5 具有聚合关系的子项目,在 pom.xml 中<parent>
<parent> <groupId>com.bjsxt</groupId> <artifactId>parent</artifactId> <version>0.0.1-SNAPSHOT</version>
</parent>
4. 聚合项目和继承项目区别
4.1 在语意上聚合项目父项目和子项目关系性较强
4.2 在语意上单纯继承项目父项目和子项目关系性较弱
5. <dependencyManagement> 写在父项目
5.1 作用:声明可能使用到的所有 jar
5.2 子项目中只需要有坐标的<groupid>和<artifactid>,<version>继承父项目
5.3 在父项目中<properties>把所有版本好进行统一管理
5.4 父项目 pom.xml
5.4.1 <properties>子标签名称自定义
5.4.2 ${名字} 引用标签的值
<properties> <spring-version>4.1.6.RELEASE</spring-version>
</properties>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-version}</version> </dependency> </dependencies>
</dependencyManagement>
5.5 子项目
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency>
</dependencies>
6.⼀个项目的依赖来源于不同的组织,可能这些依赖还会依赖别的Jar包,如何保证这些传递依赖不会引起版本冲突?
使⽤<dependency>中的<exclusion>元素将会把引起冲突的元素排除。
7.多模块如何聚合
配置⼀个打包类型为pom的聚合模块,然后在该pom中使⽤<module>元素声明要聚合的模块。
8.对于⼀个多模块项目,如果管理项目依赖的版本
通过在⽗模块中声明dependencyManagement和pluginManagement,然后让⼦模块通过<parent>元素指定⽗模块,这样⼦模块在定义依赖时就可以只定义groupId和artifactId,⾃动使⽤⽗模块的version,这样统⼀整个项⽬的依赖的版本。
相关文章:
Spring、SpringMVC、Shiro、Maven
一、SpringSpring是一个为了解决企业应用程序开发复杂性而创建的开源框架,其核心是IOC–控制反转、AOP–面向切面编程。框架的主要优势之一就是其分层架构(WEB层(springMvc)、业务层(Ioc)、持久层ÿ…...
element-plus 使用笔记
npm install element-plus --save自动导入 npm install -D unplugin-vue-components unplugin-auto-import// vite.config.jsimport AutoImport from unplugin-auto-import/vite import Components from unplugin-vue-components/vite import { ElementPlusResolver } from …...
《蓝桥杯每日一题》 前缀和·Acwing 3956. 截断数组
1.题目https://www.acwing.com/problem/content/3959/给定一个长度为 n 的数组a1,a2,…,an。现在,要将该数组从中间截断,得到三个非空子数组。要求,三个子数组内各元素之和都相等。请问,共有多少种不同的截断方法?输入…...
促进关键软件高层次人才培养:平凯星辰与华东师范大学签订联合博士培养合作协议
2022 年年初,平凯星辰入选首批工信部教育部支持联合培养国家关键软件高层次人才计划。该计划旨在探索关键软件产教融合育人模式,超常规加快培养一批急需高层次人才,以及探索关键软件联合技术攻关新模式。2022 年年底,在该计划下 平…...
Java程序员的日常——经验贴
关于文件的解压和压缩 如果你的系统不支持tar -z命令 前往讨论 如果是古老的Unix系统,可能并不认识tar -z命令,因此如果你想要压缩或者解压tar.gz的文件,就需要使用gzip或者gunzip以及tar命令了。 关于tar.gz可以这么理解,tar结…...
电商API社区,商品数据,关键词搜索等
1. 需要做的事情 l 商品详情页实现 1、商品查询服务事项 2、商品详情展示 3、添加缓存 2. 实现商品详情页功能 2.1. 功能分析 1、Taotao-portal接收页面请求,接收到商品id。 2、调用taotao-rest提供的商品详情的服务,把商品id作为参数传递给服务。接…...
LEADTOOLS 22.0.6 UPDATE-Crack
OCR SDK 库 许多 OCR 增强功能 LEAD 行业领先的人工智能 OCR SDK 在以下方面获得了显着的识别优化:斜体、大写和小写字母、文本行组装和单词构建、列检测、基线检测和文本行分割。 LEADTOOLS为.NET 6、. NET Framework、Xamarin、UWP、C#、VB、C/C、Java、Objective…...
什么是OJ? 东方博宜题库部分题解
什么是OJ ? Online Judge 比如这样的:Home - 一本通OJ Q:这个在线裁判系统使用什么样的编译器和编译选项? A:系统运行于Debian/Ubuntu Linux. 使用GNU GCC/G++ 作为C/C++编译器, C: gcc Main.c -o Main -fno-asm -O2 -Wall -lm --static -std=c99 -DONLINE_JUDGE C++: g++ …...
企业工程项目管理系统源码的各模块及其功能点清单
工程项目各模块及其功能点清单 一、系统管理 1、数据字典:实现对数据字典标签的增删改查操作 2、编码管理:实现对系统编码的增删改查操作 3、用户管理:管理和查看用户角色 4、菜单管理:实现对系统菜单的增删改查操…...
【电商开发手册】订单-下单
下单需求 所谓下单,本质上就是买卖双方通过确认一系列信息并且签订电子合同的过程 在电商平台的下单过程中,也需要确定买卖双方的一系列信息: 买方:用户确认收货地址、支付方式、配送方式等等 卖方:卖方需要进行供…...
数据结构 - 优先级队列(堆)
文章目录前言1.介绍优先级队列2. 认识堆3. 实现优先级队列3.1 了解优先级队列的构造方法:3.2 使用优先级队列解决问题:总结前言 本篇PriorityQueue优先级队列的介绍其底层是堆,关于堆的认识,使用优先级队列能解决的一些问题&…...
PDF内容提取器:ByteScout PDF Extractor SDK Crack
ByteScout PDF Extractor SDK – 用于 PDF 到 JSON、PDF 到 Excel、CSV、XML、从 .NET 和 ASP.NET 从 PDF 中提取文本的 PDF 提取器库 ByteScout PDF Extractor SDK – 用于 PDF 到 JSON、PDF 到 Excel、CSV、XML、从 .NET 和 ASP.NET 从 PDF 中提取文本的 PDF 提取器库 …...
字母板上的路径[提取公共代码,提高复用率]
提取公共代码前言一、字母版上的路径二、贪心1、idea2、go3、代码不断拆分复用的过程总结参考文献前言 写代码,在提高效率的同时,要方便人看,这个人包括自己。大函数要拆分成一些小函数,让每个函数的宏观目的和步骤都显得清晰&am…...
c# winform错误大全
c# winform 错误大全为了实现安装包安装完成后,启动程序。System.BadImageFormatException: 未能加载文件或程序集“file:///C:\xxxxxxxxx\xxxxxxx.exe”或它的某一个依赖项。生成此程序集的运行时比当前加载的运行时新,无法加载此程The version of the …...
AI_News周刊:第一期
2023.02.06—2023.02.12 关于ChatGPT的前言: 在去年年末,OpenAI的ChatGPT在技术圈已经火了一次,随着上周它的二次出圈,ChatGPT算得上是人工智能领域的一颗明星,它在聊天机器人领域有着不可忽视的影响力。其准确、快速…...
搭建mysql主从复制
前言: 👏 作者简介:我是笑霸final,一名热爱技术的在校学生。 📝 个人主页:个人主页1 || 笑霸final的主页2 📕 系列专栏:数据库 📧 如果文章知识点有错误的地方࿰…...
内存溢出、内存泄露的概述及常见情形
内存溢出(OutofMemoryError) 简述 java doc 中对 Out Of Memory Error 的解释是,没有空闲内存,并且垃圾收集器也无法提供更多内存。 JVM 提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,由于 GC&…...
Linux 中断实验
目录 一、Linux 中断简介 上半部与下半部 二、添加设备树 三、编写驱动 1、定义宏 2、编写一个key结构体 3、imx6uirq设备添加成员 编辑4、按键中断处理函数 5、按键初始化 6、在驱动入口添加初始化 7、 驱动出口函数 代码如下 四、利用定时器进行消抖处理 1、添…...
【c++】指针
文章目录指针的定义和使用指针所占的内存空间空指针野指针const修饰指针指针和数组指针和函数指针、数组、函数案例:冒泡排序指针的定义和使用 指针定义的语法:数据类型 * 指针变量名 使用指针: 可以通过解引用的方式来找到指针指向的内存&…...
别具一格的婚礼,VR全景+婚礼的优势展现在哪里?
随着90后、95后逐渐步入结婚的主力军中,如何策划一场别具一格的婚礼是许多年轻人所头疼的,那么今年我们就可以玩点新潮的,VR婚礼或许是个不错的选择。 VR全景婚礼就是通过全景摄像机对婚礼进行记录,不但可以帮助新人捕捉婚礼的精彩…...
【GD32F427开发板试用】5. SPI驱动TFTLCD屏幕
本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:hehung 之前发帖 【GD32F427开发板试用】1. 串口实现scanf输入控制LED 【GD32F427开发板试用】2. RT-Thread标准版移植 【GD32F427开发板试用…...
测试2年还拿实习生的薪资打发我,你后悔去吧····
20年7月大学毕业,学的计算机科学专业。因为考研之后,秋招结束了。没什么更多的岗位选择,就想找个工作先干着,然后亲戚在一家大厂公司上班说要招测试,所以就来做测试了。 虽然都是属于计算机大类,但自己专业…...
面向对象程序(C++)设计基础
一、类&对象C 在 C 语言的基础上增加了面向对象编程,C 支持面向对象程序设计。类是 C 的核心特性,通常被称为用户定义的类型。类提供了对象的蓝图,所以基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型…...
conda安装nodejs版本过低解决方法
conda命令直接安装nodejs时,可能会由于镜像源中nodejs版本过低导致没法安装高本版的nodejs,导致无法jupyterlab使用一些扩展插件。 解决方法如下:(windows环境下直接按提示下载版本安装就行,此处只介绍linux环境的解决…...
前端工程师leetcode算法面试必备-二分搜索算法(下)索算法(下)
一、287. 寻找重复数 给定一个包含 n 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。 1、HashMap 在没有其它附加条件的情况下&…...
使用Autowired为什么会被IDEA警告,应该怎么修改最佳
问题原因 关于这个问题,其实答案相对统一,实际上用大白话说起来也容易理解。 初始化问题 先看一下Java初始化类的顺序:父类的静态字段 > 父类静态代码块 > 子类静态字段 > 子类静态代码块 > 父类成员变量 > 父类构造代码块 &…...
面向对象(中)
面向对象(中) 一、 面向对象之继承性 继承性的好处 减少代码的冗余,提高了代码的复用性。 便于功能的扩展。 为多态性的使用,提供了前提。 继承性的格式 class A extends B{} A:子类、派生类、subclass B:…...
【云原生】promehtheus整合grafana实现可视化监控实战
文章目录前言一. 实验环境二. 安装grafana2.1 grafana的介绍2.2 为什么选择grafana?2.3 grafana下载及安装三. 网页端配置grafana3.1 浏览器访问grafana网页3.2 使用grafana 获取prometheus的数据源3.3 grafana导入prometheus模板总结前言 大家好,又见面…...
Linux 内核定时器实验
目录 一、内核时间管理简介 二、内核定时器简介 三、驱动编写 1、修改makefile 2、添加定义 3、初始化led函数 4、添加调用 5、初始化定时器与定时器处理函数 这部分代码如下 四、ioctl函数 五、内核添加unlocked_ioctl 函数 1、添加设备操作集unlocked_ioctl成员 2…...
喜欢大屏电视?那就选择酷开系统,实现智能生活享受
随着科技的发展和我们生活水平的提高,越来越多的消费者开始认可并习惯使用各种高质量的科技产品,比如喜欢玩游戏的消费者,他们往往会追求流畅性更强、刷新率更快的大显示屏,以此获得更真实刺激的游戏体验,而喜欢追剧的…...
phpmyadmin做网站/百度竞价推广费用
C语言程序设计实训之四价格竞猜游戏设计,周跃进徐州建筑职业技术学院电子信息工程系,在《购物街》游戏中,能否通过编程模拟整个过程,该如何做?,看一段录相,思考一个问题,《购物街》游戏节目是通过佳宾猜商品价格,本实训…...
dedecms 安防监控行业网站模板/凡科建站收费价目表
telnet命令通常用来远程登录。telnet程序是基于TELNET协议的远程登录客户端程序。Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的 能力。在终端使用者的电脑上使用telnet程序&…...
佛山顺德网站制作公司哪家好/hao123网址导航
为了提高减少频繁访问数据库,提高系统性能,使用Hibernate的二级缓存插件EHCache 详细实现如下:hibernate.cfg.xml文件 <?xml version1.0 encodingutf-8?> <!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernat…...
建筑工程发布网站/永州网站seo
包含头文件:stdlib.h 函数原型 用法:将字符串里的数字字符转化为整形数。返回整形值。 注意:转化时跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时(’/0’)才结束转换&#…...
做网站建设个体经营小微企业/外链屏蔽逐步解除
错误信息 消息号TA263 解决方法 Step 1、使用SCC4进入“集团管理”界面。 Step 2、双击要维护的集团,例如“010”,进入详细配置界面。 Step 3、设置“保护:客户拷贝和比较工具”为“保护级别 0:没有限制”,保存即可。 …...
东莞 包装制品 东莞网站建设/阿里巴巴指数查询
什么是OOPSOops是美国人比较常有的口语。就是有点意外,吃惊,或突然的意思。“oops”并不是很严重.对于linux内核来说,Oops就意外着内核出了异常,此时会将产生异常时出错原因,CPU的状态,出错的指令地址、数据…...