zoukankan      html  css  js  c++  java
  • springboot自动配置原理 and 一个简单的demo项目 and spring常用注解的使用

    Springboot自动配置原理:

    主类 @SpringBootApplication 开启了自动配置

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration//这里开启了自动配置
    @ComponentScan(excludeFilters = {
            @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    ...
    }
    @Import(EnableAutoConfigurationImportSelector.class) 通过注解的方式实现把实例EnableAutoConfigurationImportSelector加入springIOC容器中,
    EnableAutoConfigurationImportSelector实现了接口ImportSelector,并在其父类AutoConfigurationImportSelector中实现了ImportSelector定义的
    org.springframework.context.annotation.ImportSelector#selectImports 【String[] selectImports(AnnotationMetadata importingClassMetadata)】),
    selectImports返回了一系列的***AutoConfiguration配置类,例如org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,具体返回内容请查看动图一 
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(EnableAutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    ...
    }

    org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration 中通过注解 @ConditionalXXX 定义了创建bean的条件 ,

    例如下面代码片段的 @ConditionalOnMissingBean(CharacterEncodingFilter.class)定义了当CharacterEncodingFilter类型的bean不存在才创建bean,当我们通过maven引入某个starter后(例如 spring-boot-starter-web),会匹配@Conditional定义的条件从而创建bean
    @Configuration
    @EnableConfigurationProperties(HttpEncodingProperties.class)
    @ConditionalOnWebApplication
    @ConditionalOnClass(CharacterEncodingFilter.class)
    @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
    public class HttpEncodingAutoConfiguration {
    
        private final HttpEncodingProperties properties;
    
        public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
            this.properties = properties;
        }
    
        @Bean
        @ConditionalOnMissingBean(CharacterEncodingFilter.class)
        public CharacterEncodingFilter characterEncodingFilter() {
            CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
            filter.setEncoding(this.properties.getCharset().name());
            filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
            filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
            return filter;
        }
    ...
    }

    自动化配置类都有一个这样的注解@EnableConfigurationProperties ,例如 @EnableConfigurationProperties(HttpEncodingProperties.class) 来关联配置文件(application.yml或application.properties)的内容,可以打开这些类来看支持哪些配置项

    一个简单的demo项目

    下面贴出部分代码

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>lddxfs.springboot</groupId>
        <artifactId>springboot-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <name>springboot-demo</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.18.BUILD-SNAPSHOT</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
            <!--<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>-->
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-validation</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
            </dependency>
            <!-- Provided -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.7</version>
            </dependency>
    
            <!-- <dependency>
                 <groupId>org.apache.tomcat.embed</groupId>
                 <artifactId>tomcat-embed-jasper</artifactId>
                 <scope>provided</scope>
             </dependency>-->
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
        <repositories>
            <repository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/snapshot</url>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
            <repository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
        </repositories>
    
        <pluginRepositories>
            <pluginRepository>
                <id>spring-snapshots</id>
                <name>Spring Snapshots</name>
                <url>https://repo.spring.io/snapshot</url>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </pluginRepository>
            <pluginRepository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://repo.spring.io/milestone</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </pluginRepository>
        </pluginRepositories>
    
    
    </project>
    View Code

    入口类

    package lddxfs.springboot.springbootdemo;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    @SpringBootApplication
    @EnableTransactionManagement
    @MapperScan("lddxfs.springboot.springbootdemo.mapper")
    public class SpringbootDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootDemoApplication.class, args);
        }
    
    }

    yml

    application:
      message: bootJSP
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/dubbostudy?useUnicode=true&characterEncoding=utf8
        username: root
        password: 123456
        driver-class-name: com.mysql.jdbc.Driver
      mvc:
        view:
          prefix: /WEB-INF/jsp/
          suffix: .jsp
        formcontent:
          putfilter:
            enabled: true
      http:
        encoding:
          charset: utf-8
          force: true
    mybatis:
      mapper-locations: classpath*:mapper*.xml
    View Code

    使用外部tomcat运行(支持jsp)

    package lddxfs.springboot.springbootdemo;
    
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.support.SpringBootServletInitializer;
    
    /**
     * Author:lddxfs(lddxfs@qq.com;https://www.cnblogs.com/LDDXFS/)
     * Date:2018/10/24
     * 使用外置tomcat
     */
    public class DemoSpringBootServletInitializer extends SpringBootServletInitializer {
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
            return application.sources(SpringbootDemoApplication.class);
        }
    }
    View Code

    监听器

    package lddxfs.springboot.springbootdemo.web; /**
     * Author:lddxfs(lddxfs@qq.com;https://www.cnblogs.com/LDDXFS/)
     * Date:2018/10/24
     */
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.http.HttpSessionAttributeListener;
    import javax.servlet.http.HttpSessionBindingEvent;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    /**
     *  Author:lddxfs(lddxfs@qq.com;https://www.cnblogs.com/LDDXFS/)
     *  Date:2018/10/23
     */
    public class DemoListener implements ServletContextListener,
            HttpSessionListener, HttpSessionAttributeListener {
        private static Logger log = LoggerFactory.getLogger(DemoListener.class);
        public DemoListener() {
        }
    
        // -------------------------------------------------------
        // ServletContextListener implementation
        // -------------------------------------------------------
        public void contextInitialized(ServletContextEvent sce) {
          /* This method is called when the servlet context is
             initialized(when the Web application is deployed). 
             You can initialize servlet context related data here.
          */
            log.info("容器启动了");
        }
    
        public void contextDestroyed(ServletContextEvent sce) {
          /* This method is invoked when the Servlet Context 
             (the Web application) is undeployed or 
             Application Server shuts down.
          */
            log.info("容器销毁了");
        }
    
        // -------------------------------------------------------
        // HttpSessionListener implementation
        // -------------------------------------------------------
        public void sessionCreated(HttpSessionEvent se) {
            /* Session is created. */
            log.info("Session创建了 sessionId:{}",se.getSession().getId());
        }
    
        public void sessionDestroyed(HttpSessionEvent se) {
            /* Session is destroyed. */
            log.info("Session销毁了 sessionId:{}",se.getSession().getId());
        }
    
        // -------------------------------------------------------
        // HttpSessionAttributeListener implementation
        // -------------------------------------------------------
    
        public void attributeAdded(HttpSessionBindingEvent sbe) {
          /* This method is called when an attribute 
             is added to a session.
          */
            log.info("放入值到Session了 name:{}",sbe.getName());
        }
    
        public void attributeRemoved(HttpSessionBindingEvent sbe) {
          /* This method is called when an attribute
             is removed from a session.
          */
            log.info("Session移除值 name:{}",sbe.getName());
        }
    
        public void attributeReplaced(HttpSessionBindingEvent sbe) {
          /* This method is invoked when an attibute
             is replaced in a session.
          */
            log.info("Session修改值 name:{}",sbe.getName());
        }
    }
    View Code

      过滤器

    package lddxfs.springboot.springbootdemo.web;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    /**
     * Author:lddxfs(lddxfs@qq.com;https://www.cnblogs.com/LDDXFS/)
     * Date:2018/10/24
     */
    public class DemoFilter implements Filter {
        private static Logger log = LoggerFactory.getLogger(DemoFilter.class);
    
        @Override
        public void init(FilterConfig filterConfig) {
            log.info("DemoFilter.init()");
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            if (request instanceof HttpServletRequest) {
                HttpServletRequest req = (HttpServletRequest) request;
                log.info("请求uri:{}", req.getRequestURI());
            }
            chain.doFilter(request, response);
        }
    
        @Override
        public void destroy() {
            log.info("DemoFilter.destroy()");
        }
    }
    View Code

    三大组件注册配置类

    package lddxfs.springboot.springbootdemo.config;
    
    import lddxfs.springboot.springbootdemo.web.DemoFilter;
    import lddxfs.springboot.springbootdemo.web.DemoListener;
    import lddxfs.springboot.springbootdemo.web.DemoServlet;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
    import org.springframework.boot.web.servlet.ServletRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * Author:lddxfs(lddxfs@qq.com;https://www.cnblogs.com/LDDXFS/)
     * Date:2018/10/23
     * web三大组件注册配置类
     */
    @Configuration
    public class WebBeanConfig {
    
        /**
         * 注册serlet
         * @return
         */
        @Bean
        public ServletRegistrationBean servletRegistrationBean() {
            ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
            servletRegistrationBean.setServlet(new DemoServlet());
            servletRegistrationBean.addUrlMappings("/testServletA");
            return servletRegistrationBean;
        }
    
        /**
         * 注册filter
         * @return
         */
        @Bean
        public FilterRegistrationBean filterRegistrationBean() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            filterRegistrationBean.setFilter(new DemoFilter());
            filterRegistrationBean.setOrder(0);
            Set<String> urlPatterns = new HashSet<>();
            urlPatterns.add("/*");
            filterRegistrationBean.setUrlPatterns(urlPatterns);
            return filterRegistrationBean;
        }
    
    
    
        /**
         * 注册listener
         * @return
         */
        @Bean
        public ServletListenerRegistrationBean servletListenerRegistrationBean() {
            ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean();
            servletListenerRegistrationBean.setListener(new DemoListener());
            servletListenerRegistrationBean.setOrder(0);
            return servletListenerRegistrationBean;
        }
    }
    View Code

    异常处理

    package lddxfs.springboot.springbootdemo.web;
    
    import lddxfs.springboot.springbootdemo.common.resutcode.Result;
    import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestAttributes;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * Author:lddxfs(lddxfs@qq.com;https://www.cnblogs.com/LDDXFS/)
     * Date:2018/10/24
     */
    @Component
    public class DemoErrorAttribute extends DefaultErrorAttributes {
        @Override
        public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
            Result<Void> result =(  Result<Void>)requestAttributes.getAttribute("ext",RequestAttributes.SCOPE_REQUEST);
            Map<String, Object> errorMap=new LinkedHashMap<>();
            errorMap.put("message",result.getMessage());
            errorMap.put("data",result.getData());
            errorMap.put("code",result.getCode());
            return errorMap;
        }
    }
    View Code
    package lddxfs.springboot.springbootdemo.web;
    
    import lddxfs.springboot.springbootdemo.common.resutcode.Result;
    import lddxfs.springboot.springbootdemo.common.resutcode.ResultCode;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * Author:lddxfs(lddxfs@qq.com;https://www.cnblogs.com/LDDXFS/)
     * Date:2018/10/24
     * 异常处理
     */
    @ControllerAdvice
    public class DemoExeceptionHandler {
        private static final Logger LOGGER = LoggerFactory.getLogger(DemoExeceptionHandler.class);
    
        /**
         * 所有客户端返回json数据
         *
         * @param e
         * @return
         */
    /*    @ResponseBody
        @ExceptionHandler(Exception.class)
        public Result<Void> HandleException(Exception e) {
            Result<Void> result = ResultCode.ERROR.clone();
            result.setMessage(e.getMessage());
            return result;
        }*/
    
        /**
         * 不同客户端返回JSON或Html
         * @param e
         * @param request
         * @return
         */
        @ExceptionHandler(Exception.class)
        public String handleException(Exception e, HttpServletRequest request) {
            Result<Void> result = ResultCode.ERROR.clone();
            result.setMessage(e.getMessage());
            request.setAttribute("ext", result);
            request.setAttribute("javax.servlet.error.status_code", HttpStatus.INTERNAL_SERVER_ERROR.value());
            LOGGER.error("系统异常:", e);
            return "forward:/error";
        }
    }
    View Code

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
             id="WebApp_ID" version="3.0">
        <display-name>springboot-demo</display-name>
    </web-app>
    View Code

    Controller

    package lddxfs.springboot.springbootdemo.web.controller;
    
    import lddxfs.springboot.springbootdemo.common.resutcode.Result;
    import lddxfs.springboot.springbootdemo.common.resutcode.ResultCode;
    import lddxfs.springboot.springbootdemo.javabean.Category;
    import lddxfs.springboot.springbootdemo.service.CategoryService;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.*;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    
    /**
     * Author:lddxfs(lddxfs@qq.com;https://www.cnblogs.com/LDDXFS/)
     * Date:2018/10/6
     * REST风格 管理分类
     */
    @RequestMapping("api")
    @RestController
    public class CategoryController {
        private static Logger logger = LoggerFactory.getLogger(CategoryController.class);
        @Resource
        private CategoryService categoryService;
    
        @GetMapping("categories")
        public Result<List<Category>> categories() {
            Result<List<Category>> result = ResultCode.SUCCESS.clone();
            result.setData(categoryService.categories());
            return result;
        }
    
        public CategoryController() {
            System.out.println("CategoryController");
        }
    
        @GetMapping("/categories/{id}")
        public Result<Category> categories(@PathVariable("id") Integer id) {
            Result<Category> result = ResultCode.SUCCESS.clone();
            result.setData(categoryService.categoriesById(id));
            return result;
        }
    
        @DeleteMapping("/categories/{id}")
        public Result<Void> deleteCategories(@PathVariable("id") Integer id) {
            Result<Void> result = ResultCode.SUCCESS.clone();
            categoryService.deleteCategories(id);
            return result;
        }
    
        @PutMapping("/categories")
        public Result<Category> updateCategories(Category category) {
            Result<Category> result = ResultCode.SUCCESS.clone();
            result.setData(categoryService.updateCategories(category));
            return result;
        }
    
        @PostMapping("/categories")
        public Result<Category> createCategories(Category category) {
            Result<Category> result = ResultCode.SUCCESS.clone();
            result.setData(categoryService.saveCategories(category));
            return result;
        }
    
        @PostMapping(value = "/categories/transaction_test")
        public Result<List<Category>> transactionTest(@RequestBody List<Category> categories) {
            Result<List<Category>> result = ResultCode.SUCCESS.clone();
            result.setData(categoryService.transactionTest(categories));
            return result;
        }
    
    }
    View Code

    mybatis代码生成配置

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
      PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
      "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    <generatorConfiguration>
        <!--数据库驱动-->
        <classPathEntry    location="mysql-connector-java-5.1.45.jar"/>
        <context id="mysql">
            <commentGenerator>
                <property name="suppressDate" value="true"/>
                <property name="suppressAllComments" value="true"/>
            </commentGenerator>
            <!--数据库链接地址账号密码-->
            <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/dubbostudy?useSSL=true" userId="root" password="123456">
            </jdbcConnection>
            <javaTypeResolver>
                <property name="forceBigDecimals" value="false"/>
            </javaTypeResolver>
            <!--生成Model类存放位置-->
            <javaModelGenerator targetPackage="lddxfs.springboot.springbootdemo.javabean" targetProject="springboot-demosrc">
                <property name="enableSubPackages" value="true"/>
                <property name="trimStrings" value="true"/>
            </javaModelGenerator>
            <!--生成映射文件存放位置-->
            <sqlMapGenerator targetPackage="mapper" targetProject="springboot-demosrc">
                <property name="enableSubPackages" value="true"/>
            </sqlMapGenerator>
            <!--生成mapper类存放位置-->
            <javaClientGenerator type="XMLMAPPER" targetPackage="lddxfs.springboot.springbootdemo.mapper" targetProject="springboot-demosrc">
                <property name="enableSubPackages" value="true"/>
            </javaClientGenerator>
            <!--生成对应表及类名-->
    
            <table tableName="tb_good_category" domainObjectName="Category" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false">
            <!--<generatedKey column="id" sqlStatement="mySql"></generatedKey>-->
                <generatedKey column="id" sqlStatement="JDBC" identity="true" type="post"/>
            </table>
    
        </context>
    </generatorConfiguration>
    View Code

    其他代码就不贴了

    idea配置外部tomcat

    补充spring常用注解的使用

    上传代码到码云了,代码位置: https://gitee.com/lddxfs/spring-annotation-use

  • 相关阅读:
    码到成功——Beta冲刺随笔 day 6
    团队作业第六次——Beta冲刺
    Beta冲刺 —— 6.2
    用户调查报告
    Beta冲刺 —— 总结随笔
    Beta冲刺——测试随笔
    Beta冲刺 —— 6.1
    Beta冲刺 —— 5.31
    Beta冲刺 —— 5.30
    Beta冲刺 —— 5.29
  • 原文地址:https://www.cnblogs.com/LDDXFS/p/springboot.html
Copyright © 2011-2022 走看看