• Java的基础框架之SpringMvc第二讲(SSM框架整合和拦截器)


    SSM框架整合

    SSM框架整合

    SSM整合配置

    SSM整合流程

    1. 创建工程
    2. SSM整合
      • Spring
        • SpringConfig
      • MyBatis
        • MybatisConfig
        • JdbcConfig
        • jdbc.properties
      • SpringMVC
        • ServletConfig
        • SpringMvcConfig
    3. 功能模块
      • 表与实体类
      • dao(接口+自动代理)
      • service(接口+实现类)
        • 业务层接口测试(整合JUnit)
      • controller
        • 表现层接口测试(PostMan)

    SSM整合配置

    创建工程,添加依赖和插件
    <dependencies>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webmvcartifactId>
            <version>5.2.10.RELEASEversion>
        dependency>
    
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>5.2.10.RELEASEversion>
        dependency>
    
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
            <version>5.2.10.RELEASEversion>
        dependency>
    
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.5.  6version>
        dependency>
    
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatis-springartifactId>
            <version>1.3.0version>
        dependency>
    
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.47version>
        dependency>
    
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.1.16version>
        dependency>
    
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
    
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>3.1.0version>
            <scope>providedscope>
        dependency>
    
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-databindartifactId>
            <version>2.9.0version>
        dependency>
    dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.mavengroupId>
                <artifactId>tomcat7-maven-pluginartifactId>
                <version>2.1version>
                <configuration>
                    <port>80port>
                    <path>/path>
                configuration>
            plugin>
        plugins>
    build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    Spring整合Mybatis
    创建数据库和表
    jdbc.properties属性文件
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mydb
    jdbc.username=root
    jdbc.password=123456
    
    • 1
    • 2
    • 3
    • 4
    JdbcConfig配置类
    public class JdbcConfig {
        @Value("${jdbc.driver}")
        private String driver;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
    	//配置连接池
        @Bean
        public DataSource dataSource(){
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(driver);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            return dataSource;
        }
    	//Spring事务管理需要的平台事务管理器对象
        @Bean
        public PlatformTransactionManager transactionManager(DataSource dataSource){
            DataSourceTransactionManager ds = new DataSourceTransactionManager();
            ds.setDataSource(dataSource);
            return ds;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    MybatisConfig配置类
    public class MyBatisConfig {
        @Bean
        public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
            SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
            factoryBean.setDataSource(dataSource);
            factoryBean.setTypeAliasesPackage("com.baiyang.domain");
            return factoryBean;
        }
    
        @Bean
        public MapperScannerConfigurer mapperScannerConfigurer(){
            MapperScannerConfigurer msc = new MapperScannerConfigurer();
            msc.setBasePackage("com.baiyang.dao");
            return msc;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    SpringConfig配置类
    @Configuration
    @ComponentScan({"com.baiyang.service"})
    @PropertySource("classpath:jdbc.properties")
    @Import({JdbcConfig.class,MyBatisConfig.class})
    @EnableTransactionManagement //开启Spring事务管理
    public class SpringConfig {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    Spring整合SpringMVC
    SpringMvcConfig配置类
    @Configuration
    @ComponentScan("com.baiyang.controller")
    @EnableWebMvc
    public class SpringMvcConfig {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    ServletConfig配置类,加载SpringMvcConfig和SpringConfig配置类
    public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
        protected Class<?>[] getRootConfigClasses() {
            return new Class[]{SpringConfig.class};
        }
    
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{SpringMvcConfig.class};
        }
    
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    功能模块开发

    数据层开发(BookDao)

    Book实体类

    BookDao接口

    public interface BookDao {
    
        @Insert("insert into tbl_book (type,name,description) values(#{type},#{name},#{description})")
        public int save(Book book);  //返回值表示影响的行数
    
        @Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
        public int update(Book book);
    
        @Delete("delete from tbl_book where id = #{id}")
        public int delete(Integer id);
    
        @Select("select * from tbl_book where id = #{id}")
        public Book getById(Integer id);
    
        @Select("select * from tbl_book")
        public List<Book> getAll();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    业务层开发(BookService/BookServiceImpl)

    BookService接口

    @Transactional //表示所有方法进行事务管理
    public interface BookService {
    
        /**
         * 保存
         * @param book
         * @return
         */
        public boolean save(Book book);
    
        /**
         * 修改
         * @param book
         * @return
         */
        public boolean update(Book book);
    
        /**
         * 按id删除
         * @param id
         * @return
         */
        public boolean delete(Integer id);
    
        /**
         * 按id查询
         * @param id
         * @return
         */
        public Book getById(Integer id);
    
        /**
         * 查询全部
         * @return
         */
        public List<Book> getAll();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    BookServiceImpl实现类

    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookDao bookDao;
    
        public boolean save(Book book) {
            bookDao.save(book);
            return true;
        }
    
        public boolean update(Book book) {
            bookDao.update(book);
            return true;
        }
    
        public boolean delete(Integer id) {
            bookDao.delete(id);
            return true;
        }
    
        public Book getById(Integer id) {
            return bookDao.getById(id);
        }
    
        public List<Book> getAll() {
            return bookDao.getAll();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    表现层开发(BookController)

    @RestController
    @RequestMapping("/books")
    public class BookController {
    
        @Autowired
        private BookService bookService;
    
        @PostMapping
        public boolean save(@RequestBody Book book) {
            return bookService.save(book);
        }
    
        @PutMapping
        public boolean update(@RequestBody Book book) {
            return bookService.update(book);
        }
    
        @DeleteMapping("/{id}")
        public boolean delete(@PathVariable Integer id) {
            return bookService.delete(id);
        }
    
        @GetMapping("/{id}")
        public Book getById(@PathVariable Integer id) {
            return bookService.getById(id);
        }
    
        @GetMapping
        public List<Book> getAll() {
            return bookService.getAll();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    接口测试

    Spring整合Junit测试业务层方法

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfig.class)
    public class BookServiceTest {
    
        @Autowired
        private BookService bookService;
    
        @Test
        public void testGetById(){
            Book book = bookService.getById(1);
            System.out.println(book);
        }
    
        @Test
        public void testGetAll(){
            List<Book> all = bookService.getAll();
            System.out.println(all);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    postman测试表现层接口

    测试保存图书

    测试保存图书

    表现层数据封装

    表现层响应数据的问题

    我们表现层增删改方法返回true或者false表示是否成功,getById()方法返回一个json对象,getAll()方法返回一个json对象数组,这里就出现了三种格式的响应结果,极其不利于前端解析

    表现层响应数据的问题

    解决

    我们需要统一响应结果的格式

    定义Result类封装响应结果

    Result类封装响应结果

    public class Result {
        //描述统一格式中的数据
        private Object data;
        //描述统一格式中的编码,用于区分操作,可以简化配置0或1表示成功失败
        private Integer code;
        //描述统一格式中的消息,可选属性
        private String msg;
    
        public Result() {
        }
        public Result(Integer code,Object data) {
            this.data = data;
            this.code = code;
        }
        public Result(Integer code, Object data, String msg) {
            this.data = data;
            this.code = code;
            this.msg = msg;
        }
         //同学们自己添加getter、setter、toString()方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    注意

    Result类中的字段并不是固定的,可以根据需要自行增减

    Code类封装响应码

    //状态码
    public class 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 GET_OK = 20041;
    
        public static final Integer SAVE_ERR = 20010;
        public static final Integer DELETE_ERR = 20020;
        public static final Integer UPDATE_ERR = 20030;
        public static final Integer GET_ERR = 20040;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    注意

    Code类的常量设计也不是固定的,可以根据需要自行增减,例如将查询再进行细分为GET_OK,GET_ALL_OK,GET_PAGE_OK

    表现层数据封装返回Result对象

    @RestController
    @RequestMapping("/books")
    public class BookController {
    
        @Autowired
        private BookService bookService;
    
        @PostMapping
        public Result save(@RequestBody Book book) {
            boolean flag = bookService.save(book);
            return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag);
        }
    
        @PutMapping
        public Result update(@RequestBody Book book) {
            boolean flag = bookService.update(book);
            return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERR,flag);
        }
    
        @DeleteMapping("/{id}")
        public Result delete(@PathVariable Integer id) {
            boolean flag = bookService.delete(id);
            return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);
        }
    
        @GetMapping("/{id}")
        public Result getById(@PathVariable Integer id) {
            Book book = bookService.getById(id);
            Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
            String msg = book != null ? "" : "数据查询失败,请重试!";
            return new Result(code,book,msg);
        }
    
        @GetMapping
        public Result getAll() {
            List<Book> bookList = bookService.getAll();
            Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;
            String msg = bookList != null ? "" : "数据查询失败,请重试!";
            return new Result(code,bookList,msg);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    异常处理器

    异常介绍

    • 程序开发过程中不可避免的会遇到异常现象,我们不能让用户看到这样的页面数据

    • 出现异常现象的常见位置与常见诱因

      • 框架内部抛出的异常:因使用不合规导致

      • 数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)

      • 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)

      • 表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)

      • 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)

    异常处理器

    编写异常处理器

    @RestControllerAdvice  //用于标识当前类为REST风格对应的异常处理器
    public class ProjectExceptionAdvice {
    
        //统一处理所有的Exception异常
        @ExceptionHandler(Exception.class)
        public Result doOtherException(Exception ex){
            return new Result(666,null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用异常处理器之后的效果

    使用异常处理器之后的效果

    @RestControllerAdvice注解介绍

    • 名称

      @RestControllerAdvice

    • 类型

      类注解

    • 位置

      Rest风格开发的控制器增强类定义上方

    • 作用

      为Rest风格开发的控制器类做增强

    • 说明

      此注解自带@ResponseBody注解与@Component注解,具备对应的功能

    @ExceptionHandler注解介绍

    • 名称

      @ExceptionHandler

    • 类型

      方法注解

    • 位置

      专用于异常处理的控制器方法上方

    • 作用

      设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行

    • 说明

      此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常

    项目异常处理方案

    项目异常分类

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

    项目异常处理方案

    • 业务异常(BusinessException)
      • 发送对应消息传递给用户,提醒规范操作
    • 系统异常(SystemException)
      • 发送固定消息传递给用户,安抚用户
      • 发送特定消息给运维人员,提醒维护
      • 记录日志
    • 其他异常(Exception)
      • 发送固定消息传递给用户,安抚用户
      • 发送特定消息给编程人员,提醒维护(纳入预期范围内)
      • 记录日志

    项目异常处理代码实现

    根据异常分类自定义异常类

    自定义项目系统级异常
    //自定义异常处理器,用于封装异常信息,对异常进行分类
    public class SystemException extends RuntimeException{
        private Integer code;
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public SystemException(Integer code, String message) {
            super(message);
            this.code = code;
        }
    
        public SystemException(Integer code, String message, Throwable cause) {
            super(message, cause);
            this.code = code;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    自定义项目业务级异常
    //自定义异常处理器,用于封装异常信息,对异常进行分类
    public class BusinessException extends RuntimeException{
        private Integer code;
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public BusinessException(Integer code, String message) {
            super(message);
            this.code = code;
        }
    
        public BusinessException(Integer code,String message,Throwable cause) {
            super(message, cause);
            this.code = code;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    自定义异常编码
    public class Code {
    
    	//之前其他状态码省略没写,以下是新补充的状态码,可以根据需要自己补充
        
        public static final Integer SYSTEM_ERR = 50001;
        public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
        public static final Integer SYSTEM_UNKNOW_ERR = 59999;
        public static final Integer BUSINESS_ERR = 60002;
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    触发自定义异常
    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookDao bookDao;
    
    	//在getById演示触发异常,其他方法省略没有写进来
        public Book getById(Integer id) {
            //模拟业务异常,包装成自定义异常
            if(id <0){
                throw new BusinessException(Code.BUSINESS_ERR,"请不要使用你的技术挑战我的耐性!");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    在异常通知类中拦截并处理异常
    @RestControllerAdvice //用于标识当前类为REST风格对应的异常处理器
    public class ProjectExceptionAdvice {
        //@ExceptionHandler用于设置当前处理器类对应的异常类型
        @ExceptionHandler(SystemException.class)
        public Result doSystemException(SystemException ex){
            //记录日志
            //发送消息给运维
            //发送邮件给开发人员,ex对象发送给开发人员
            return new Result(ex.getCode(),null,ex.getMessage());
        }
    
        @ExceptionHandler(BusinessException.class)
        public Result doBusinessException(BusinessException ex){
            return new Result(ex.getCode(),null,ex.getMessage());
        }
    
        //除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常
        @ExceptionHandler(Exception.class)
        public Result doOtherException(Exception ex){
            //记录日志
            //发送消息给运维
            //发送邮件给开发人员,ex对象发送给开发人员
            return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙,请稍后再试!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    测试

    在postman中发送请求访问getById方法,传递参数-1

    测试

    拦截器

    拦截器概念和作用

    拦截器概念和作用

    • 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行

    • 作用

      1. 在指定的方法调用前后执行预先设定的代码
      2. 阻止原始方法的执行
      3. 总结:增强
    • 核心原理

      AOP思想

    拦截器和过滤器的区别

    • 归属不同

      Filter属于Servlet技术,Interceptor属于SpringMVC技术

    • 拦截内容不同

      Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强

    拦截器和过滤器的区别

    拦截器代码实现

    定义拦截器

    定义一个类,实现HandlerInterceptor接口即可

    @Component //注意当前类必须受Spring容器控制
    //定义拦截器类,实现HandlerInterceptor接口
    public class ProjectInterceptor implements HandlerInterceptor {
        @Override
        //原始方法调用前执行的内容
        //返回值类型可以拦截控制的执行,true放行,false终止
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle..."+contentType);
            return true;
        }
    
        @Override
        //原始方法调用后执行的内容
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle...");
        }
    
        @Override
        //原始方法调用完成后执行的内容
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    配置加载拦截器

    @Configuration
    public class SpringMvcSupport extends WebMvcConfigurationSupport {
        @Autowired
        private ProjectInterceptor projectInterceptor;
    
        @Override
        protected void addInterceptors(InterceptorRegistry registry) {
            //配置拦截器
            registry.addInterceptor(projectInterceptor)
                .addPathPatterns("/books","/books/*");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    使用标准接口WebMvcConfigurer简化开发

    注意

    侵入式较强

    @Configuration
    @ComponentScan({"com.baiyang.controller"})
    @EnableWebMvc
    //实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
    public class SpringMvcConfig implements WebMvcConfigurer {
        @Autowired
        private ProjectInterceptor projectInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //配置多拦截器
            registry.addInterceptor(projectInterceptor)
                .addPathPatterns("/books","/books/*");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    拦截器流程分析

    拦截器流程分析

    拦截器参数

    前置处理

    //原始方法调用前执行的内容
    //返回值类型可以拦截控制的执行,true放行,false终止
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle..."+contentType);
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 参数

      1. request:请求对象
      2. response:响应对象
      3. handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
    • 返回值
      返回值为false,被拦截的处理器将不执行

    后置处理

    //原始方法调用后执行的内容
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 参数

      modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行跳转

    注意

    如果处理器方法出现异常了,该方法不会执行

    完成后处理

    //原始方法调用完成后执行的内容
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 参数
      ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理
    注意

    无论处理器方法内部是否出现异常,该方法都会执行

    拦截器链配置

    多个拦截器配置

    • 定义第二个拦截器
    @Component
    public class ProjectInterceptor2 implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle...222");
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle...222");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion...222");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 配置第二个拦截器
    @Configuration
    @ComponentScan({"com.baiyang.controller"})
    @EnableWebMvc
    //实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
    public class SpringMvcConfig implements WebMvcConfigurer {
        @Autowired
        private ProjectInterceptor projectInterceptor;
        @Autowired
        private ProjectInterceptor2 projectInterceptor2;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //配置多拦截器
            registry.addInterceptor(projectInterceptor)
                .addPathPatterns("/books","/books/*");
            registry.addInterceptor(projectInterceptor2)
                .addPathPatterns("/books","/books/*");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    多个连接器工作流程分析

    • 当配置多个拦截器时,形成拦截器链
    • 拦截器链的运行顺序参照拦截器添加顺序为准
    • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
    • 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作

    多个连接器工作流程分析

  • 相关阅读:
    EdgeX Foundry - 导出数据到 HTTP 服务
    java毕业设计演唱会门票订售及管理系统Mybatis+系统+数据库+调试部署
    帝国CMS灵动标签如何调用$ecms_hashur[‘ehref‘]函数
    读写算杂志社读写算编辑部读写算杂志2022年第30期目录
    喜大普奔!有软考电子版证书可以正式办理广州落户了!
    面试官:IoC 和 DI 有什么区别?
    Docker-compose 安装mysql8
    C语言的头文件
    K8S Pod Sidecar 应用场景之一-加入 NGINX Sidecar 做反代和 web 服务器
    【Linux复习汇总】得分秘籍,考前速看,可以多考几分
  • 原文地址:https://blog.csdn.net/weixin_48548208/article/details/126540115