springboot 使用一些注意事项

分析问题流程

  • 先分析前后台
    • 4 xxx 404 400 403 405 前台为主
      • 先看console控制台 =》 js 请求报错会有提示
      • 然后分析f12 network =》 后台地址、header参数
        • 确认后台地址是否正确
        • 确认前台参数 name:value 是否按照预期传到后台
    • 5 xx想 500 504 后台
      • 后台如果抛出异常,从出现错误的第一行最右边开始向左分析

idea debug 调试使用

  • 基本用 法& 快捷键
    • f8 + f9
  • 变量查看
  • 计算表达式 alt + f8
  • 去除所有断点
    • alt+shift+f8
  • 条件断点
    • 光标放在断点所在行,alt+shift+f8 => 给断点添加条件

Spring Boot

集成日志框架log4j2

- 常用日志框架
   - log4j、log4j2(log4j的升级版)、**logback(spring boot默认)**、Jboss-logging...等
   - slf4 是日志接口规范,代码对接slf4,实现和具体日志框架解耦,无需修改编码即可切换日志框架。
  • spring boot 集成 log4j2

    • 修改pom依赖
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <!--移除框架中的logback依赖-->
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-logging</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            
            
            <!-- 支持log4j2的模块-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-log4j2</artifactId>
            </dependency>
    
    • 添加xml配置文件:log4j2.xml

    • 测试

      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
         protected Logger logger = LoggerFactory.getLogger(getClass());
      

集成拦截器

  • 登录验证为例

  • 添加拦截器

    public class LoginInterceptor implements HandlerInterceptor {
    
        private Logger log = LoggerFactory.getLogger(getClass());
    
        //Controller逻辑执行之前
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("preHandle....");
            Object user = WebUtils.getHttpSession().getAttribute("user");
            log.info("user:{}",user);
            String uri = request.getRequestURI();
            log.info("uri:"+ uri);
            if (user == null) {
                response.sendRedirect("/");
                return false;
            } else {
                return true;
            }
        }
    
        //Controller逻辑执行完毕但是视图解析器还未进行解析之前
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
            log.info("postHandle....");
        }
    
        //Controller逻辑和视图解析器执行完毕
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
            log.info("afterCompletion....");
        }
    }
    
  • 注册,配置拦截路径和排除登录需访问路径

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**")
                    .excludePathPatterns("/", "/login",  "/user/login","/user/login",
                            "/images/**", "/user/getCode", "/js/**", "/page/**",  "/layui/**",
                            "/layui_ext/**", "/login.html", "/webjars/**", "/css/**");
        }
    }
    
  • 退出登录清除session

        /**
         * 跳转到登录
         * @return
         */
        @RequestMapping("toLogin")
        public String toLogin(){
            WebUtils.getHttpSession().removeAttribute("user");
            return "/";
        }
    
    

spring mvc 参数传递方式

  • 基础参数:https://blog.csdn.net/qq_33721382/article/details/82931388
  • 复杂参数传递(对象嵌套List)

mybatis xml语法

  • 参数传递

    • #$
      • 不论是单个参数,还是多个参数,一律都建议使用注解@Param("")
      • 能用 #{} 的地方就用 #{},不用或少用 ${}
        • $符号 =》 sql注入
      • 表名作参数时,必须用 ${}。如:select * from ${tableName}
      • order by 时,必须用 ${}。如:select * from t_user order by ${columnName}
      • 使用 ${} 时,要注意何时加或不加单引号
  • 模糊查询

    • 使用CONCAT拼接(首选)

       <if test="article.title != null">
      	 title  like CONCAT('%',#{article.title},'%')
       </if>
      
    • 使用#{...}

      扫描二维码关注公众号,回复: 13115333 查看本文章

      注意:因为#{…}解析成sql语句时候,会在变量外侧自动加单引号’ ',所以这里 % 需要使用双引号" ",不能使用单引号 ’ ',不然会查不到任何结果。

      title like "%"#{title}"%"
      
    • 使用${...}

      注意:由于$是参数直接注入的,导致这种写法,大括号里面不能注明jdbcType,不然会报错

      name like '%${name}%'
      
  • foreach标签

    • collection:表示迭代集合的名称,自定义名称,可以使用@Param注解指定
      • 只有一个List/Array/Map类型参数时,如果不加@Param注解,collection分别必须填:list、array、map中的key属性
      • 有多个参数时,不加@Param注解,collection和默认参数名称一致
      • 如果加@Param注解,都和注解定义一致
    • item:表示本次迭代获取的元素,自定义名称
    • separator:分隔符
    delete from  xxx_table where id  in 
    <foreach collection="list" item="item" open="(" separator="," close=")"> 
    		#{item}
    </foreach>  => (1,2,3,4)
    
  • 数据库操作

    • 单表CRUD

      • 回填主键

        useGeneratedKeys="true" keyProperty="id"
        
    • 连表查询

      • collections
      • association
    • 批量操作

事务相关

  • C Service(事务) D/M

    • 添加教师 & 添加教课班级 =》 一个请求 =》Service(事务) 插入教师、教师和班级的关联表
      • A方法
        • 事务开启
        • 执行service方法代码 =》 如果执行一半抛出异常,事务回滚,之前进行的操作全部撤回
        • 事务提交 ==》 数据库操作才会生效
      • B 方法
        • 事务开启
        • 执行service方法代码 =》 如果执行一半抛出异常,事务回滚,之前进行的操作全部撤回
        • 事务提交 ==》 数据库操作才会生效
      • A方法调用B方法 =》 service 提交都提交 回滚都会滚
  • 要么都做要么多不做

    • 原子性
    • 隔离性
    • 一致性
    • 持久性
  • 隔离级别org.springframework.transaction.annotation.Isolation

    public enum Isolation {
          
            
        DEFAULT(-1),
        READ_UNCOMMITTED(1),
        READ_COMMITTED(2),
        REPEATABLE_READ(4),
        SERIALIZABLE(8);
    }
    
    • DEFAULT :这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是: READ_COMMITTED
    • READ_UNCOMMITTED :该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
    • READ_COMMITTED :该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
    • REPEATABLE_READ :该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
    • SERIALIZABLE :所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

    指定方法:通过使用 isolation 属性设置,例如:

    @Transactional(isolation = Isolation.DEFAULT)
    
  • 传播机制org.springframework.transaction.annotation.Propagation

    所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。

    public enum Propagation {  
        REQUIRED(0),
        SUPPORTS(1),
        MANDATORY(2),
        REQUIRES_NEW(3),
        NOT_SUPPORTED(4),
        NEVER(5),
        NESTED(6);
    }
    
    • (,默认)REQUIRED如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
    • SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
    • MANDATORY :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
    • REQUIRES_NEW创建一个新的事务,如果当前存在事务,则把当前事务挂起。
    • NOT_SUPPORTED :以非事务方式运行,如果当前存在事务,则把当前事务挂起。
    • NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。
    • NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED

    指定方法:通过使用 propagation 属性设置,例如:

    @Transactional(propagation = Propagation.REQUIRED)
    
  • 验证测试

       @Transactional
    @Service
    public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements IStudentService {
    
       @Override
        public void testTx1(){
            try {
                Student student = new Student();
                student.setName("0327888888888888");
                this.baseMapper.deleteSutdentById(6L);
                int i = 1/0;
                this.baseMapper.insertOne(student);
            }catch (Exception e){
                //  进入异常分支,记录错误日志,插入数据库
                teacherService.testTx2(e.getMessage());
                throw  new RuntimeException(e.getMessage());
            }
    
        }
        }
    
    /**
     * <p>
     * 教师表 服务实现类
     * </p>
     *
     * @author lp
     * @since 2020-10-29
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)  // 模拟异常日志,新开启事务
    @Service
    public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements ITeacherService {
    
    
    
        @Override
        public void testTx2(String text){
            this.baseMapper.insert(new Teacher().setName(text));
        }
    }
    
        @Test
        public void testTx1(){
            studentService.testTx1();
        }
    

maven相关

  • 下载安装
  • 配置
    • 仓库位置
  • 常用标签
  • 下载失败如何处理
    • 删除掉旧文件,重新下载
    • 手动下载jar包到本地,通过maven命令安装到本地仓库
  • 常用命令
  • idea 常用

spring aop应用

spring boot 注解

  • @SpringBootApplication

    • @Configuration 配置类
    • @EnableAutoConfiguration 开启自动配置
    • @ComponentScan 扫描组件
  • @Bean 注册一个bean

  • @Autowired

    • @Qualifier:当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用。
  • @Resource

  • @Conditional

    • 符合注解 @ConditionalOnXxx 条件注解
    @ConditionalOnBean:当SpringIoc容器内存在指定Bean的条件
    @ConditionalOnClass:当类路径下有指定Class的条件
    @ConditionalOnExpression:基于SpEL表达式作为判断条件
    @ConditionalOnJava:基于JVM版本作为判断条件
    @ConditionalOnJndi:在JNDI存在时查找指定的位置
    @ConditionalOnMissingBean:当SpringIoc容器内不存在指定Bean的条件
    @ConditionalOnMissingClass:当SpringIoc容器内不存在指定Class的条件
    @ConditionalOnNotWebApplication:当前项目不是Web项目的条件
    @ConditionalOnProperty:指定的属性是否有指定的值
    @ConditionalOnResource:类路径是否有指定的值
    @ConditionalOnSingleCandidate:当指定Bean在SpringIoc容器内只有一个,或者虽然有多个但是指定首选的Bean
    @ConditionalOnWebApplication:当前项目是Web项目的条件
    

spring boot自动配置实现原理

  • https://blog.csdn.net/qq_25283709/article/details/103227517

猜你喜欢

转载自blog.csdn.net/LvFengQi/article/details/115274209
今日推荐