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>
      
    • 使用#{...}

      注意:因为#{…}解析成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
使用SpringBoot的@Scheduled注解,有一些注意事项需要牢记: 1. @Scheduled注解需要在一个被Spring管理的组件(如@Service、@Component等)中使用。 2. 确保在启动类中添加@EnableScheduling注解以启用定时任务功能。 3. 使用@Scheduled注解的方法必须是无参数的,并且返回类型为void或者Future。 4. 方法需要使用public修饰符,以便Spring能够访问和调度它。 5. 在方法上添加@Scheduled注解,并指定触发定时任务的时间表达式。时间表达式可以是固定的时间间隔、Cron表达式等。 6. @Scheduled方法不应该阻塞,这可能会导致其他定时任务无法按计划执行。如果需要执行长时间运行的任务,应该考虑使用异步机制。 7. 如果使用了集群环境,需要确保只有一个节点执行定时任务。可以通过配置分布式锁等机制来实现。 8. 尽量避免在定时任务中抛出异常,因为异常会中断整个定时任务的调度。建议在方法内部进行异常处理,以确保定时任务的稳定执行。 9. 定时任务不适合处理高并发场景,因为每次调度都会创建一个新的线程。如果需要处理高并发的任务,可以考虑使用线程池或者消息队列等机制。 10. 最后,建议在开发过程中对定时任务进行充分的测试和验证,以确保其准确性和稳定性。 希望以上注意事项对你有所帮助!如果你有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值