SpringMVC高级(SSM整合)

SpringMVC高级 一、SSM整合 整合思路及流程: 创建SpringConfig类---设置配置类注解,设置注解扫描包,导入其他配置类,开启事务,导入配置文件 整合MyBatis---需要获取SqlSessionFactoryBean来创建SqlSessionFactory ,进而来创建Sql

SpringMVC高级

一、SSM整合

整合思路及流程:

  1. 创建SpringConfig类---设置配置类注解,设置注解扫描包,导入其他配置类,开启事务,导入配置文件
  2. 整合MyBatis---需要获取SqlSessionFactoryBean来创建SqlSessionFactory ,进而来创建SqlSession和创建MapperScannerConfigurer,用来扫描注册dao。创建配置SqlSessionFactoryBean需要DataSource
  3. 创建JdbcConfig类创建DataSource---根据jdbc.properties信息通过数据连接池中通过获取数据源DataSource和编写spring事务管理器,需要在SpirngConfig中开启事务@EnableTransactionManagement
  4. 配置SpringMvc:添加@Configuration注解,设置Controller包扫描,还需要WebApplicationInitializer来配置DispatcherServlet,而创建DispatcherServlet可以通过配置Servlet容器配置类进行继承AbstractDispatcherServletInitializer类或者AbstractAnnotationConfigDispatcherServletInitializer类
  5. 配置Servlet容器配置类:继承继承AbstractDispatcherServletInitializer类或者AbstractAnnotationConfigDispatcherServletInitializer类重写三个方法

SSM相关Maven依赖整理

<!--依赖-->
    <dependencies>
         <!--SpringMVC相关依赖-->
          <!--spring-webmvc包含了spring-context包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>

        <!--Servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided<scop>
        </dependency>

        <!--JSP-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>

        <!-- JSP中JSTL标签库 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!--Json相关依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>

         <!--Mybatis相关依赖---------------------------   -->
         <!--Spring的jdbc模块-->
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>

        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>

        <!--Mybatis整合-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>

        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!--数据库连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.1</version>
        </dependency>

          <!--测试相关依赖包 ------------------------------ -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.10.RELEASE</version>
            <scope>test</scope>
        </dependency>

         <!--Junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

1.1 Spring

1.1.1 SpringConfig

@Configuration
@ComponentScan("com.sys")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
@EnableTransactionManagement
public class SpringConfig{
}

1.2 MyBatis

1.2.1 MybatisConfig

使用 SqlSessionFactoryBuilder创建SqlSessionFactory ,进而来创建 SqlSession。一旦你获得一个 session 之后,你可以使用它来执行映射语句,提交或回滚连接,最后,当不再需要它的时候, 你可以关闭 session。

public class MybatisConfif(){

      //创建SqlSessionFactroyBean,设置数据源和别名包路径
      @Bean
      public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
          SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactroyBean();
          SqlSessionFactoryBean.setDataSource(dataSource);
          SqlSessionFactoryBean.setTypeAliasesPackage("com.sys.po");
          return sqlSessionFactroyBean;
      }

        //创建MapperScannerConfigurer,用来扫描注册dao
        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer(){
            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
            mapperScannerConfigurer.setBasePackage("com.sys.dao");
            return mapperScannerConfigurer;
        }
}

1.2.2 JdbcConfig

整合MyBatis:需要创建JdbcConfig类来根据jdbc.properties信息通过数据连接池中通过获取数据源DataSource

public class JdbcConfig{
    @Value(${jdbc.driver})
    private String drvier;

    @Value(${jdbc.url})
    private String url;

    @Value(${jdbc.username})
    private String username;

    @Value(${jdbc.password})
    private String password;

    //配置获取数据源DataSource
    @Bean
    public DataSource dataSource(){
      DruidDataSource druidDataSource = new DruidDataSource();
      druidDataSource.setDriverClassName(drvier);
      druidDataSource。setUrl(url);
      druidDataSource.setUsername(username);
      druidDataSource.setPassword(password);
      return druidDataSource;    
    }

    //编写spring事务管理器,需要在SpirngConfig中开启事务@EnableTransactionManagement
    @Bean
    public PlatformTransactionManager transactionManager(DataSource data Source){
      DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
      dataSourceTransactionManager.setDataSource(dataSourceTransactionManager);
      return dataSourceTransactionManager;
    }
}

当spring容器启动的时候,发现有@EnableTransactionManagement注解,此时会拦截所有bean的创建,扫描看一下bean上是否有@Transaction注解(类、或者父类、或者接口、或者方法中有这个注解都可以),如果有这个注解,spring会通过aop的方式给bean生成代理对象,代理对象中会增加一个拦截器,拦截器会拦截bean中public方法执行,会在方法执行之前启动事务,方法执行完毕之后提交或者回滚事务

1.2.3 jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://主机号:端口/数据库名称
jdbc.username=账号
jdbc.password=密码

1.3 SpringMVC

1.3.1 ServletConfig

继承AbstractDispatcherServletInitializer类实现它的三个方法
e84d9b4976c8edaa1979753e351e33d.png
AbstractDispatcherServletInitializer类的继承关系

tomcat 容器启动时,ServletContainerInitializer 实例化,然后把一系列标有HandlesTypes 注解的类,这里就是 SpringServletContainerInitializer 进行实例化,并被tomcat调用他的 onStartup()方法 。Set参数就是一系列 实现了 WebApplicationInitializer 接口的类,Set集合中的类统一进行 调用 initializer.onStartup(servletContext); 最终实现 tomcat 容器启动,将 DispatcherServlet 实例化,初始化,注册到tomcat中。

Public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer{
      //创建一个SpringMVC容器--表现层
      protected WebApplicationContext createrServletApplicationContext(){
         AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
          ctx.register(SpringMvcConfig.class);
          return ctx;
      }

      //设置哪些请求交给SpringMVC处理
      protected String[] getServletMappings(){
          retrn new String[]{"/"};
      }

      //创建spring容器 - service ,dao
      protected WebApplicationContext createRootApplicationContext(){
          AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
          ctx.register(SpringConfig.class);
          return ctx;
      }
}

继承AbstractAnnotationConfigDispatcherServletInitializer类实现它的三个方法
Spring3.2中引入AbstractAnnotationConfigDispatcherServletInitializer就是WebApplicationInitializer的基础实现,所以当部署到servlet3.0容器中时,容器会发现它的子类,并用子类来配置Servlet上下文。

  • getServletMappings():将一个或多个路径映射到DispatcherServlet上;
  • getServletConfigClasses():返回的带有@Configuration注解的类用来配置DispatcherServlet;
  • getRootConfigClasses():返回的带有@Configuration注解的类用来配置ContextLoaderListener;
public class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{
        protected String[] getServletMappings(){
            return new String[]{"/"};
        }

        protected Class<?>[] getServletConfigClasses(){
            return new Class[]{SpringMvcConfig.class};
        }
        
        protected Class<?>[] getRootConfigClasses(){
            return new Class[]{SpringConfig.class};
        }
}

1.32 SpringMvcConfig

@Configuration
@ComponentScan("com.sys.controller")
@EnableWebMvc
public class SpringMvcConfig(){
}

二、功能模块

数据库表——>实体层——>DAO层——>Mapper层——>Service层——>ServiceImpl——>Controller层

  1. 根据数据库表来新建相对应实体类

2.1表与实体类

public class Book{
  private Integer id;
  private String type;
  private String name;
  priavte Stirng description;

  set,get,构造函数等...
}

2.2 dao(接口+自动代理)

数据访问层、持久层

public interface BookDao {
      //插入
      @Insert("insert into tbl_book (type,name,description) values (#{type},#{name},#{description})") 
      Integer save(Book book);

      //查询全部
      @Select("select * from tbl_book")
      List<Book> getAll();

      //根据id查询
      @Select("select * from tbl_book where id = #{id}"")
      Book getById(Integer id);
}

2.3 service(接口+实现类)

业务逻辑层
接口类:

public class BookService {

      Boolean save(Book book);

      List<Book> getAll();

      Book getById(Integer id);
}

实现类

@Service
public class BookServiceImpl implements BookService{

      @Autowired
      private BookDao bookDao;

      public Boolean save(Book book){
          Integer save = bookDao.save(book);
          return save > 0;
      }

      public List<Book> getAll(){
          return bookDao.getAll();
      }

      public Book getById(Integer id){
          return bookDao.getById(id);
      }
}

2.3.1 业务层接口测试(整合JUnit)

  1. 在test文件夹下面新建包结构:com.sys.service.BookServiceTest
  2. 使用@RunWith注解启用JUnit4来运行

@RunWith(JUnit4.class)就是指用JUnit4来运行
@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境
@RunWith(Suite.class)的话就是一套测试集合,

@ContextConfiguration这个注解通常与@RunWith(SpringJUnit4ClassRunner.class)联合使用用来测试
当一个类添加了注解@Component,那么他就自动变成了一个bean,就不需要再Spring配置文件中显示的配置了。把这些bean收集起来通常有两种方式,Java的方式和XML的方式。当这些bean收集起来之后,当我们想要在某个测试类使用@Autowired注解来引入这些收集起来的bean时,只需要给这个测试类添加@ContextConfiguration注解来标注我们想要导入这个测试类的某些bean。

package com.sys.service;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)  //因为是测试service所以SpringConfig.class
public class BokkServiceTest {

      @Autowired
      private BookService bookService;

      @Test
      public void testGetAll(){
          List<Book> bookList = bookService.getAll();
          System.outprintln(bookList);
      }

      @Test
      public void getAll(){
          Book book = new Book();
          book.setName();
          .....
          Boolean save = bookService.save(book);
          System.outprintln(save);
        }

      @Test
      public void getById(){
          Book book = bookService.getById(3);
          System.outprintln(book);
      }
}

2.4 controller

表现层

@RestController
@RequestMapping("/books")
public class BookController{

  @Autowired
  priavte BookService bookService;

  @PostMapping
  Boolean save(@RequestBody Book book){
    Boolean isSave = bookService.save(book)
    if(isSave){
    return new Result(Code.SAVE_OK,"插入成功",isSave);
    }else{
    
    }
    return ;
  }

  @GetMapping
  List<Book> getAll(){
      return bookService.getAll();
  }

  @GetMapping("/{id}")
  Book getById(@PathVariable Integer id){
      return bookService.getById(id);
}
}

三、项目中数据封装

3.1表现层数据封装

  • 设置统一数据返回类,比如下面,可以根据项目需要进行更改和提供构造方法,方便操作
  • 一般兴建一个vo包来存放VO代表值对象,它用于封装业务逻辑中的数据,并且在应用程序的不同层之间进行传递
public class  Result {
    private Object data;
    private Interger code;
    private String msg;
}

还可以封装一下Code字段,新建一个Code类

public calss Code{
      public static final Integer SAVE_OK = 20011;
      public static final Integer DELETE_OK = 20021;
      public static final Integer UPDATE_OK = 20031;
      public static final Integer SELECT_Ok = 20041;

       public static final Integer SAVE_ERR = 20010;
      .....
}

3.2 异常处理器

出现异常现象的常见位置与常见诱因如下:

异常常见位置异常常见诱因
框架内部抛出的异常因使用不合规导致
数据层抛出的异常因外部服务器故障导致(例如:服务器访问超时)
业务层抛出的异常因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
工具类抛出的异常因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)

在系统当中, Dao、Service、Controller层代码出现都可能抛出异常。如果哪里产生异常就在哪里处理,则会降低开发效率。所以一般情况下我们会让异常向上抛出,最终到达DispatcherServlet中,此时SpringMVC提供了异常处理器进行异常处理,这样可以提高开发效率

1.png

3.2.1 单个控制器异常处理

使用实现单个控制器异常处理@ExceptionHandler注解

@Controller
public class MyController {
 
    // 处理单个Controller异常
    @RequestMapping("/t1")
    public String t1(){
        String str = null;
        // str.length();
        // int flag = 1/0;
        int []arr = new int[1];
        arr[2] = 10;
        return "index";
    }
 
    /**
     * 异常处理方法
     * @param ex 异常对象
     * @param model 模型对象
     * @return
     */
    // 添加@ExceptionHandler,表示该方法是处理异常的方法,属性为处理的异常类
    @ExceptionHandler({java.lang.NullPointerException.class,java.lang.ArithmeticException.class})
    public String exceptionHandler1(Exception ex, Model model){
        // 向模型中添加异常对象
        model.addAttribute("msg",ex);
        // 跳转到异常页面
        return "error";
    }
 
    // 方法一不能处理的异常交给方法二处理
    @ExceptionHandler({java.lang.Exception.class})
    public String exceptionHandler2(Exception ex,Model model){
        model.addAttribute("msg",ex);
        return "error2";
    }

3.2.2 全局异常处理

  • 在控制器中定义异常处理方法只能处理该控制器类的异常,要想处理所有控制器的异常,需要定义全局异常处理类。主要是使用@ControllerAdvice或者@RestControllerAdvice注解来创建一个异常处理器
  • 在项目中创建给exception包来创建一个异常处理器类ProjectExceptionAdvice,不要忘了在SpringConfig包扫描中标注此包
  • 创建自定义异常,继承RuntimeException类重载器构造函数
  • 在全局异常处理器中书写相对应异常捕获方法,用@ExceptionHandler注解后面选择捕获异常类型,传入书写的自定义异常类
  • 使用异常:可能出现异常的代码使用try catch来捕获抛出异常到new一个自定义异常类中,
  • 我们的全局异常处理器就会捕获到,进入处理器相对应的方法,执行一些横向开发的工作,比如通知运维人员报错了啊等等

@ControllerAdvice结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到全局不同类型的异常区别处理的目的。

  • @ExceptionHandler这个注解表示Controller中任何一个方法发生异常,则会被注解了@ExceptionHandler的方法拦截到。对应的异常类执行对应的方法,如果都没有匹配到异常类,则采用近亲匹配的方法
@RestControllerAdvice
public class ProjectExceptionAdvice{
    
    @ExceptionHandler(Exception.class)
    public Result doException(自定义异常类 e){
        return new Result(e.getCode(),e.getMessage(),null);
    }
}

3.2.3 异常处理涉及注释

  1. @ControllerAdvice注解作用原理
    Spring首先前端控制器DispatcherServlet对象在创建时会初始化一系列的对象,里面包含了initHandlerAdapters(context)和initHandlerExceptionResolvers(context)这两个方法,是我们重点关注的。

initHandlerAdapters(context)方法会取得所有实现了HandlerAdapter接口的bean并保存起来,其中就有一个类型为RequestMappingHandlerAdapter的bean,这个bean就是@RequestMapping注解能起作用的关键,这个bean在应用启动过程中会获取所有被@ControllerAdvice注解标注的bean对象做进一步处理:找到所有ModelAttribute标注的方法并缓存起来,找到所有InitBinder标注的方法并缓存起来。经过处理之后,@ModelAttribute和@InitBinder就能起作用了。
DispatcherServlet的initHandlerExceptionResolvers(context)方法,方法会取得所有实现了HandlerExceptionResolver接口的bean并保存起来,七张就有一个类型为ExceptionHandlerExceptionResolver的bean,这个bean在应用启动过程中会获取所有被@ControllerAdvice注解标注的bean对象做进一步处理

  1. @RestControllerAdvice和@ControllerAdvice
    @RestControllerAdvice是一个组合注解,是@ResponseBody和@ControllerAdvice的组合,而函数体中用到了@AliasFor注解,因此可以通过@RestControllerAdvice的属性传递将属性值传给@ControllerAdvice。

3.2.4 异常处理方案

  • 项目异常分类
    • 业务异常(BusinessExceptoin)
      • 规范的用户行为产生异常
      • 不规范的用户行为操作产生的异常
    • 系统异常(SystemException)
      • 项目运行过程中可预计且无法避免的异常
    • 其他异常(Exception)
      • 编程人员未预期的异常

我们可以在相应的exception包下书写相对应异常的处理器,利用继承RuntimeException类,实现构造器,为什么要继承这个类?

  1. 不需要在方法签名中声明:由于运行时异常不需要在方法上显式声明或捕获,所以继承 RuntimeException 的自定义异常可以在方法中抛出而无需修改方法签名。
  2. 异常不需要被强制捕获:运行时异常不需要被强制捕获,开发者可以选择是否捕获并处理这些异常。这样可以减少代码的冗余性,简化异常处理逻辑。
  3. 适合表示程序错误或逻辑问题:运行时异常通常用于表示程序错误、逻辑问题或不可恢复的错误情况。当出现这些异常时,通常意味着程序处于一个不可恢复的状态,需要进行修复或终止程序的执行。
public class BusinessException extends RuntimeException{
    private Integer code;

    public BusinessException(Integer code , String message){
        super(message);
        this.code = code;
    }

    public BusinessException(Integer code,Stirng message, Throwable cause){
        super(message,cause);
        this.code = code;
    }

    code,set,get方法
}

四、拦截器

4.1 过滤器和拦截器区别

Filter(过滤器):过滤器工作在 Servlet 容器中,它拦截客户端的请求和服务器的响应。过滤器链(Filter Chain)是多个过滤器按照一定的顺序执行的集合,一个请求可以依次通过多个过滤器,然后到达目标 Servlet,响应也会按相反的顺序经过这些过滤器返回给客户端。
Interceptor(拦截器):拦截器工作在 Spring 的 DispatcherServlet 和具体的 Controller 之间。当一个请求被发送到 Spring MVC 应用时,DispatcherServlet 首先接收到这个请求,然后根据配置的拦截器链对请求进行预处理,最后将请求转发到相应的 Controller 进行处理。
9390a8c507106ffef912f2f5096c78e.png

4.2 拦截器实现

  • 拦截器是与 Spring MVC 的 DispatcherServlet 集成的。当一个请求被 DispatcherServlet 接收后,它会处理和调度这个请求到相应的处理器(Controller)。
  • 在请求到达 Controller 之前,Spring 会根据请求的 URL 查找对应的 Handler Mapping,然后确定相应的 Controller。
  • 在请求达到 Controller 之前,以及响应返回给客户端之前,拦截器链中的拦截器会被依次调用。
  • 开发者可以自定义拦截器,并通过实现 WebMvcConfigurer 接口的 addInterceptors 方法将它们添加到应用中。

实现步骤:

  1. 创建拦截器类:
  • 实现 HandlerInterceptor 接口或继承 HandlerInterceptorAdapter 类。
  • 重写 preHandle、postHandle 和 afterCompletion 方法。
  1. 注册拦截器:
  • 创建一个配置类,实现 WebMvcConfigurer 接口或者继承WebMVcConfigurationSupport类。
  • 重写 addInterceptors 方法来添加拦截器。
  1. 编写拦截逻辑:
  • 在 前置处理preHandle、后置处理postHandle 和完成后处理 afterCompletion 方法中实现具体的拦截逻辑。

4.3 处理器链

pre1 --> pre2 --> pre3 -->controller --> post3 --> post2 --> post1 --> after3 --> after2 --> after1
如果前置pre3 返回false 则也跳过 controller 和全部post环节 还有自己的 after环节,执行after2,after1

  • 在请求达到 Controller 之前,以及响应返回给客户端之前,拦截器链中的拦截器会被依次调用。
  • 开发者可以自定义拦截器,并通过实现 WebMvcConfigurer 接口的 addInterceptors 方法将它们添加到应用中。
  • 实现:书写多个处理器,然后在注册的时候全部写入,执行拦截器按照addInterceptor的代码位置
//注册拦截器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private MyInterceptor myInterceptor1;
    @Autowired
    private MyInterceptor myInterceptor2;
    @Autowired
    private MyInterceptor myInterceptor3;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor1).addPathPatterns("/**");
        registry.addInterceptor(myInterceptor2).addPathPatterns("/books","/books/*");
        registry.addInterceptor(myInterceptor3).addPathPatterns("/books");
    }
}

4.4代码演示

创建一个interceptor包来书写拦截器类

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 请求处理前的逻辑
        return true; // 返回 true 继续流程,返回 false 中断流程
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        // 请求处理后的逻辑,但在视图渲染前
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 请求处理完毕后的逻辑
    }
}

注册拦截器:实现WebMvcConfigurer接口,重写 addInterceptors 方法来添加拦截器,重写addResourceHandlers可以设置静态资源访问路径
我们这里把拦截器剔出到一个SpirngWebSupport配置类,然后在SpringMvcConfig类中用注解@Improt导入即可

@Configuration
public class SpringWebSupport implements WebMvcConfigurer {

    @Autowired
    private MyInterceptor myInterceptor;

    //设置静态资源访问路径
    puablic void addResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/pages/**").addResourceLocation("/pages/")
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); // 应用于所有路径(可以注入自定义拦截器类就不用new了)
        registry.addInterceptor(myInterceptor).addPathPatterns("/**");
        
    }
}

五、注意事项

5.1 注释包扫描范围设置

  1. 精准扫描
    在包扫描注解利用数组写下多个需要扫描的路径
    @ComponentScan({"com.sys.service","com.sys.dao"})
  2. 排除扫描
    利用包扫描注解中Value和excludeFilters参数来排除子包
@ComponentScan(value = "com.sys",
        excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class))
LICENSED UNDER CC BY-NC-SA 4.0
Comment