工作中使用框架

1、Spring

1、管理Bean

Spring的IOC容器管理Bean一共有两种方式,基于xml文件和基于注解,其中基于注解是最常用的。

创建Bean实例:一共四个,四个的作用都是一样的创建Bean,只是意义不同。

  • @Component:基于注解创建Bean,用于创建一般的对象。以下三个注解都是它的子注解;

  • @Service:用于创建业务逻辑层Bean,Service层;

  • @Controller:用于创建表现层,接口层对象;

  • @Repository:用于创建数据层Bean定义;

  • @Scope("xxx"):和创建Bean的注解一起使用,用于声明对象域。

    • singleton:单例,默认,全局只有一个实例;

    • prototype:多实例懒创建的,每次从容器中获取Bean的时候都新建一个。容易导致频繁GC;

    • request:同一个请求,每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP请求内有效;

    • session:同一个会话级别。

属性注入

  • @Autowired:根据属性类型进行自动装配;

  • @Qualifier(value = "userDaoImpl1"):根据Bean名称进行注入。但是注意:@Qualifier使用时必须和@Autowired 一起使用。作用是区别多个同类型的Bean

  • @Resource(name = "userDaoImpl1"):既可以根据类型注入,也可以根据名称注入,这里是根据名称进行注入,如果不用name属性就是根据类型注入;

  • @Value(value = "abc"):注入基本数据类型属性,上述三个都是注入容器中的Bean属性,而这个是注入基本数据类型的属性。

配置类

  • @Configuration :作为配置类,替代 xml配置文件;

  • @ComponentScan(basePackages = {"com.atguigu"}):作用于配置类,配置包扫描路径,也就是配置要去识别哪个路径下的,声明Bean的注解;

  • @Bean:声明方法返回值为Bean,并注入容器中;

  • @Value注解也可用于为配置类中的基本属性赋值;

  • 条件注解:该注解可以定义在类上,一般使用在configuration配置类上,用于限制该配置类是否生效。也可以定义在方法上和@Bean组合使用,用于判断该bean是否需要注入;

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Configuration</span> <span style="color:#aa5500">// 表明这是一个配置类</span>
<span style="color:#555555">@ComponentScan</span>(<span style="color:#000000">basePackages</span> <span style="color:#981a1a">=</span> {<span style="color:#aa1111">"com.atguigu"</span>})
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">AppConfig</span> {
​
   <span style="color:#555555">@Bean</span>(<span style="color:#000000">initMethod</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"init"</span>, <span style="color:#000000">destroyMethod</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"destroy"</span>)  <span style="color:#aa5500">// 1、配置类中的方法使用@Bean注解,配置一个Bean实例放入IOC容器中,Bean名字就是方法名,效果和@Component类似。2、方法返回值就是实例对象。3、它也可作用于@Component及其子注解类的方法中。4、同时接受生命周期的方法回调。</span>
   <span style="color:#770088">public</span> <span style="color:#000000">MyBean</span> <span style="color:#000000">myBean</span>(<span style="color:#000000">Student</span> <span style="color:#000000">stu</span>) { <span style="color:#aa5500">// 方法若有参数,需要自动从容器中获取,获取不到就报错</span>
       <span style="color:#770088">return</span> <span style="color:#770088">new</span> <span style="color:#000000">MyBean</span>();
   }
​
   <span style="color:#555555">@Value</span>(<span style="color:#aa1111">"${app.database.url}"</span>)
   <span style="color:#770088">private</span> <span style="color:#008855">String</span> <span style="color:#000000">databaseUrl</span>;
    
   
}</span></span>

2、AOP

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Component</span> <span style="color:#aa5500">// 该AOP类也要交给Spring管理</span>
<span style="color:#555555">@Aspect</span> <span style="color:#aa5500">// 表示该类是用于增强逻辑的</span>
<span style="color:#555555">@Order</span>(<span style="color:#116644">1</span>) <span style="color:#aa5500">// 多个增强类作用于一个方法时,可以设置优先级</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">UserProxy</span> {
    <span style="color:#aa5500">//@Before 注解表示作为前置通知,value值是切点匹配</span>
    <span style="color:#555555">@Before</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(* com.atguigu.spring5.aopanno.User.add(..))"</span>)
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">before</span>() {
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"before........."</span>);
    }
    <span style="color:#aa5500">//后置通知(返回通知)</span>
    <span style="color:#555555">@AfterReturning</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(*com.atguigu.spring5.aopanno.User.add(..))"</span>)
        <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">afterReturning</span>() {
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"afterReturning........."</span>);
    }
    <span style="color:#aa5500">//最终通知</span>
    <span style="color:#555555">@After</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(* com.atguigu.spring5.aopanno.User.add(..))"</span>)
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">after</span>() {
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"after........."</span>);
    }
    <span style="color:#aa5500">//异常通知:方法抛异常后执行</span>
    <span style="color:#555555">@AfterThrowing</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(*com.atguigu.spring5.aopanno.User.add(..))"</span>)
        <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">afterThrowing</span>() {
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"afterThrowing........."</span>);
    }
    <span style="color:#aa5500">//环绕通知</span>
    <span style="color:#555555">@Around</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(* com.atguigu.spring5.aopanno.User.add(..))"</span>)
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">around</span>(<span style="color:#000000">ProceedingJoinPoint</span> <span style="color:#000000">proceedingJoinPoint</span>) <span style="color:#770088">throws</span> 
        <span style="color:#000000">Throwable</span> {
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"环绕之前........."</span>);
        <span style="color:#aa5500">//原始方法执行</span>
        <span style="color:#000000">proceedingJoinPoint</span>.<span style="color:#000000">proceed</span>();
        <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"环绕之后........."</span>);
    }
}</span></span>

切点统一抽取:把相同的切点抽取出来,相当于是一个方法,减少了繁琐的重复书写。

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Pointcut</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"execution(* com.atguigu.spring5.aopanno.User.add(..))"</span>) <span style="color:#aa5500">// 抽取切点</span>
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#0000ff">pointdemo</span>() {
}
<span style="color:#aa5500">// 使用统一切点</span>
<span style="color:#555555">@Before</span>(<span style="color:#000000">value</span> <span style="color:#981a1a">=</span> <span style="color:#aa1111">"pointdemo()"</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#0000ff">before</span>() {
    <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"before........."</span>);
}</span></span>

3、事务

  • 声明式事务注解,SpringBoot项目中只需要使用@Transactional注解即可,不需要其它xml文件配置;

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Transactional</span>(<span style="color:#000000">propagation</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Propagation</span>.<span style="color:#000000">REQUIRED</span>,<span style="color:#000000">isolation</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Isolation</span>.<span style="color:#000000">READ_COMMITTED</span>,<span style="color:#000000">readOnly</span> <span style="color:#981a1a">=</span> <span style="color:#221199">true</span>,<span style="color:#000000">rollbackFor</span> <span style="color:#981a1a">=</span> <span style="color:#000000">Exception</span>.<span style="color:#770088">class</span>,<span style="color:#000000">timeout</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1</span>,<span style="color:#000000">noRollbackFor</span> <span style="color:#981a1a">=</span> <span style="color:#000000">UncheckedIOException</span>.<span style="color:#770088">class</span>)
<span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#0000ff">method1</span>() {
    <span style="color:#aa5500">// ...</span>
}</span></span>
  • propagation 事务传播机制:

    • REQUIRED:默认值,如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务;

    • REQUIRES_NEW:首先创建一个新的事务,如果当前存在事务,则把当前事务挂起;

    • SUPPORTS 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行;

    • NOT_SUPPORTED 以非事务方式运行,如果当前存在事务,则把当前事务挂起;

    • NEVER 以非事务方式运行,如果当前存在事务,则抛出异常;

    • MANDATORY 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常;

    • NESTED 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行; 如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

  • isolation隔离级别:

    • DEFAULT 使用后端数据库默认的隔离级别

    • READ_UNCOMMITTED 读取未提交数据(会出现脏读, 不可重复读)

    • READ_COMMITTED 读取已提交数据(会出现不可重复读和幻读)

    • REPEATABLE_READ 可重复读(会出现幻读)

    • SERIALIZABLE 串行化

  • timeout:超时时间

    • 事务需要在一定时间内进行提交,如果不提交进行回滚

    • 默认值是 -1 ,即不设置超时时间,单位是秒 s

  • readonly:是否只读

    • 值为 true 表示查询,不能修改

    • 值为 false 表示可查询可写

  • rollbackFor:回滚哪些异常

    • 设置出现哪些异常时进行事务回滚,默认出现运行时异常时都回滚

  • noRollbackFor:设置出现哪些异常时不进行事务回滚

    • 默认检查时异常都不进行回滚。

4、单元测试

  • 引入测试依赖:

    <span style="background-color:#f8f8f8"><span style="color:#981a1a"><</span><span style="color:#000000">dependency</span><span style="color:#981a1a">></span>
        <span style="color:#981a1a"><</span><span style="color:#000000">groupId</span><span style="color:#981a1a">></span><span style="color:#000000">org</span>.<span style="color:#000000">springframework</span>.<span style="color:#000000">boot</span><span style="color:#981a1a"></</span><span style="color:#000000">groupId</span><span style="color:#981a1a">></span>
        <span style="color:#981a1a"><</span><span style="color:#000000">artifactId</span><span style="color:#981a1a">></span><span style="color:#000000">spring</span><span style="color:#981a1a">-</span><span style="color:#000000">boot</span><span style="color:#981a1a">-</span><span style="color:#000000">starter</span><span style="color:#981a1a">-</span><span style="color:#000000">test</span><span style="color:#981a1a"></</span><span style="color:#000000">artifactId</span><span style="color:#981a1a">></span>
        <span style="color:#981a1a"><</span><span style="color:#000000">scope</span><span style="color:#981a1a">></span><span style="color:#000000">test</span><span style="color:#981a1a"></</span><span style="color:#000000">scope</span><span style="color:#981a1a">></span>
    <span style="color:#981a1a"></</span><span style="color:#000000">dependency</span><span style="color:#981a1a">></span></span>
  • 直接开始单元测试:

    <span style="background-color:#f8f8f8"><span style="color:#555555">@SpringBootTest</span>(<span style="color:#000000">classes</span> <span style="color:#981a1a">=</span> <span style="color:#000000">JunitApplication</span>.<span style="color:#770088">class</span>) <span style="color:#aa5500">// classes属性可选,用于指定测试单元所加载的配置类,默认就是SpringBoot的引导类</span>
    <span style="color:#770088">class</span> <span style="color:#0000ff">Springboot04JunitApplicationTests</span> {
        <span style="color:#aa5500">//注入你要测试的对象</span>
        <span style="color:#555555">@Autowired</span>
        <span style="color:#770088">private</span> <span style="color:#000000">BookDao</span> <span style="color:#000000">bookDao</span>;
        <span style="color:#555555">@Test</span> <span style="color:#aa5500">// 具体的测试方法</span>
        <span style="color:#008855">void</span> <span style="color:#000000">contextLoads</span>() {
            <span style="color:#aa5500">//执行要测试的对象对应的方法</span>
            <span style="color:#000000">bookDao</span>.<span style="color:#000000">save</span>();
            <span style="color:#000000">System</span>.<span style="color:#000000">out</span>.<span style="color:#000000">println</span>(<span style="color:#aa1111">"two..."</span>);
        }
    }</span>

2、Mabatis

1、基本使用

  • 导入依赖:

    <span style="background-color:#f8f8f8"><span style="color:#117700"><</span><span style="color:#117700">dependencies</span><span style="color:#117700">></span>
        <span style="color:#aa5500"><!--1.导入对应的starter--></span>
        <span style="color:#117700"><</span><span style="color:#117700">dependency</span><span style="color:#117700">></span>
            <span style="color:#117700"><</span><span style="color:#117700">groupId</span><span style="color:#117700">></span>org.mybatis.spring.boot<span style="color:#117700"></</span><span style="color:#117700">groupId</span><span style="color:#117700">></span>
            <span style="color:#117700"><</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span>mybatis-spring-boot-starter<span style="color:#117700"></</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span>
            <span style="color:#117700"><</span><span style="color:#117700">version</span><span style="color:#117700">></span>2.2.0<span style="color:#117700"></</span><span style="color:#117700">version</span><span style="color:#117700">></span>
        <span style="color:#117700"></</span><span style="color:#117700">dependency</span><span style="color:#117700">></span>
    ​
        <span style="color:#117700"><</span><span style="color:#117700">dependency</span><span style="color:#117700">></span>
            <span style="color:#117700"><</span><span style="color:#117700">groupId</span><span style="color:#117700">></span>mysql<span style="color:#117700"></</span><span style="color:#117700">groupId</span><span style="color:#117700">></span>
            <span style="color:#117700"><</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span>mysql-connector-java<span style="color:#117700"></</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span>
            <span style="color:#117700"><</span><span style="color:#117700">scope</span><span style="color:#117700">></span>runtime<span style="color:#117700"></</span><span style="color:#117700">scope</span><span style="color:#117700">></span>
        <span style="color:#117700"></</span><span style="color:#117700">dependency</span><span style="color:#117700">></span>
    <span style="color:#117700"></</span><span style="color:#117700">dependencies</span><span style="color:#117700">></span></span>
  • 配置数据源:

    <span style="background-color:#f8f8f8"><span style="color:#aa5500">#2.配置相关信息</span>
    <span style="color:#0000ff">spring</span>:
    <span style="color:#0000ff">  datasource</span>:
    <span style="color:#0000ff">    driver-class-name</span>:<span style="color:#009900"> com.mysql.cj.jdbc.Driver</span>
    <span style="color:#0000ff">    url</span>:<span style="color:#009900"> jdbc</span>:<span style="color:#009900">mysql</span>:<span style="color:#009900">//localhost</span>:<span style="color:#009900">3306/ssm_db</span>
    <span style="color:#0000ff">    username</span>:<span style="color:#009900"> root</span>
    <span style="color:#0000ff">    password</span>:<span style="color:#009900"> root</span>
    ​
    <span style="color:#0000ff">mybatis</span>:  
    <span style="color:#aa5500">    # mapper接口在java目录下,对应的xml文件在resources目录下,如果它俩的路径名称不一致,则需要如下配置来指明mapper接口对应的xml文件的位置。</span>
    <span style="color:#0000ff">    mapper-locations</span>:<span style="color:#009900"> classpath</span>:<span style="color:#009900">mapper/*.xml  </span>
    <span style="color:#aa5500">    # 指定实体类所在包路径来让mybatis自动扫描到自定义的实体类</span>
    <span style="color:#0000ff">    type-aliases-package</span>:<span style="color:#009900"> com.chf.pojo  </span>
    <span style="color:#aa5500">    # 输出日志</span>
    <span style="color:#0000ff">    configuration</span>:    
    <span style="color:#0000ff">        log-impl</span>:<span style="color:#009900"> org.apache.ibatis.logging.stdout.StdOutImpl    </span>
    <span style="color:#aa5500">        #开启驼峰自动映射。前提是Java属性名和数据库表的字段都遵循命名规范:Java首字母小写,后面每个单词首字母大写,驼峰;SQL命名规范:全部小写,单词之间采用下划线分割。一个单词的就不必用驼峰或者下划线了</span>
    <span style="color:#0000ff">        map-underscore-to-camel-case</span>:<span style="color:#009900"> true</span></span>
  • 实体类

    <span style="background-color:#f8f8f8">// lombok注解。。。
    public class Book { // 默认情况下字段名和属性名相同的进行匹配
        private Integer id;
        private String carNum;
        private String brand;
        private Double guidePrice;
        private String produceTime;
        private String carType;
    }</span>
  • 映射接口(mapper)

    <span style="background-color:#f8f8f8">@Mapper   // 声明这是mapper接口,同时也将其实现类对象加载到容器中
    public interface CarMapper {、
        
        /*@Select("select * from tbl_book where id = #{id}") // 简单SQL语句可以在这里直接写。@Delete、@Insert、@Update。
        public Book getById(Integer id);*/
        /**
         * 插入汽车
         * @return
         * @param car
         */
        int insert(Car car); // 传入参数是实体类
        int insert2(Map map); // 传入参数是map集合
        /**
         * 按id删除车辆信息
         * @param id
         * @return
         */
                                
        int delete(Long id);
        /**
         * 更新车辆信息
         * @param car
         * @return
         */
        int update(Car car);
    }</span>
  • xml 文件:

    <span style="background-color:#f8f8f8"><!--namespace值等于mapper接口路径-->
    <mapper namespace="com.chf.mapper.CarMapper">
        <insert id="insert"> <!--id标签值与对应的mapper接口中的方法名相同-->
            insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
            <!--#{}接收的参数是所传入对象的属性名称-->
            values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
        </insert>
        <insert id="insert2">
            <insert id="insertStudentByMap" parameterType="map"><!--指定传入参数是map集合-->
            insert into t_student
            values (null,#{姓名},#{年龄},#{身高},#{生日},#{性别})<!--#{}里的是map的key,实际插入的是map的value-->
        </insert>
        </insert>
        <!--如果占位符只有一个,其实可以随便写里面的内容但不能不写,但最好见名知意,这次只是测试-->
        <delete id="delete">
            delete from t_car where id = #{dasdad}
        </delete>
        <update id="update">
            update t_car set <!--同理,#{}所接收参数是所传入实体类的属性名称-->
                car_num=#{carNum}, 
                brand=#{brand},
                guide_price=#{guidePrice},
                produce_time=#{produceTime},
                car_type=#{carType}
            where id=#{id}
        </update>
    </mapper></span>
  • 在需要的地方注入该mapper,然后调用其中方法即可。

2、常用查询

  • 主要解释mapper接口文件和xml文件。

  • mapper接口:

    <span style="background-color:#f8f8f8">@Mapper   // 声明这是mapper接口,同时也将其实现类对象加载到容器中
    public interface CarMapper {
        // 查询全部。并按时间排序
        List<Car> selectAllByAscOrDesc(String str);
        // 模糊查询
        List<Car> selectByBrandLike(String str);
        // 查询单个对象,返回map集合。集合key是查询的字段名,value是实际值
        Map<String,Object> selectByIdRetMap(Long id);
        // 查询多个对象,返回多个map,存放到List集合中
        List<Map<String,Object>> selectAllRetListMap();
        // 指定外层map的key是查询到的哪一个字段值。
        @MapKey("id")
        Map<Long,Map<String,Object>> selectAllRetMap();
        // 多参数:@Param("xxx")里的值和select标签中参数对应即可。
        List<Student> selectByNameAndSex(@Param("nnn") String name,
                      @Param("sss") Character sex);
        // 聚合查询,返回基本数据类型
        Long selectTotal();
    }</span>
  • xml 文件:查询标签比其它标签多了resultType属性,属性值是返回值类型。

    <span style="background-color:#f8f8f8"><!--namespace值等于mapper接口路径-->
    <mapper namespace="com.chf.mapper.CarMapper">
        <!--简单查询-->
        <select id="selectAllByAscOrDesc" resultType="Car"><!--返回实体类对象,可用集合接收-->
            select
                id,
                car_num carNum,<!--实体类属性名与表字段名不对应的解决办法之二:为查询字段起别名-->
                brand,
                guide_price guidePrice,
                produce_time produceTime,
                car_type carType
            from
                t_car
            order by
                produce_time ${ascOrDesc}
        </select>
        <!--模糊查询。-->
        <select id="selectByBrandLike" resultType="Car">
            select
                id,
                car_num carNum,
                brand,
                guide_price guidePrice,
                produce_time produceTime,
                car_type carType
            from
                t_car
            where
                brand like "%"#{brand}"%"
        </select>
        <!--查询单个对象,返回map集合-->
        <select id="selectByIdRetMap" resultType="map">
            select
                id,
                car_num carNum,
                brand,
                guide_price guidePrice,
                produce_time produceTime,
                car_type carType
            from
                t_car
            where
                id = #{id}
        </select>
        <!--查询多个对象,返回多个map,存放到List集合中。注意返回值不是List!-->
        <select id="selectAllRetListMap" resultType="map">
            select
                id,
                car_num carNum,
                brand,
                guide_price guidePrice,
                produce_time produceTime,
                car_type carType
            from
                t_car
        </select>
        <!--查询多个对象,返回多个map,存放到外层map集合中。-->
        <select id="selectAllRetMap" resultType="map">
            select
                id,
                car_num carNum,
                brand,
                guide_price guidePrice,
                produce_time produceTime,
                car_type carType
            from
                t_car
        </select>
        <!--查询多个对象,多参数查询-->
        <select id="selectByNameAndSex" resultType="Car">
            select
                *
            from
                t_car
            where
            	name = #{nnn} and sex = #{sss}
        </select>
        <!--返回值是基本数据类型-->
        <select id="selectTotal" resultType="long">
            select
                count(*)
            from
                t_car
        </select>
    </mapper></span>

3、动态SQL

1、where - if 标签
<span style="background-color:#f8f8f8"><span style="color:#333333">@Mapper
public interface CarMapper {
    /**
     * 多条件查询
     */
    List<Car> selectByMultiCondition(@Param("brand") String brand,
                                     @Param("guidePrice") Double guidePrice,
                                     @Param("carType") String carType);
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333"><mapper namespace="com.chf.mapper.CarMapper">
    <!--
        1、如果f标签中test属性的值为true,则if标签中的sql语句就会拼接。反之就不会拼接
        2、test属性中可以使用的是:
            当使用了@Param注解,那么test中要出现的是@Param注解指定的参数名。
            当没有使用@Param注解,那么test中要出现的是:param1 param2 param3 ...
            当使用了POJO,那么test中出现的是POJO类的属性名
        3、在MyBatis的动态SQL中,不能使用&&,使用的是and
        4、标签内与#{}内写的都是POJO属性名,其余是SQL的字段名
		5、刚开始的1 = 1是防止后面出现空传值导致SQL语句出现错误
		
    -->
    <select id="selectByMultiCondition" resultType="Car">
        select
            id,car_num,brand,guide_price,produce_time,car_type
        from
            t_car
        where
            1 = 1
            <if test="brand != null and brand != ''">
                and brand like "%"#{brand}"%"
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                and guide_price >= #{guidePrice}
            </if>
            <if test="carType != null and carType != ''">
                and car_type like "%"#{carType}"%"
            </if>
    </select>
    
    <!--包含where标签时。if并不是只能用在where语句中!-->
    <!--
        where标签是专门负责where子句动态生成的
        这里将1 = 1去掉了并且第一个if标签语句还有"and"关键字,但where标签会自动去除多余的and或or
        所有条件都有空时,where标签保证不会生成where子句
    -->
    <select id="selectByMultiConditionWithWhere" resultType="Car">
        select
            id,car_num,brand,guide_price,produce_time,car_type
        from
            t_car
        <where>
            <if test="brand != null and brand != ''">
                and brand like "%"#{brand}"%"
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                and guide_price >= #{guidePrice}
            </if>
            <if test="carType != null and carType != ''">
                and car_type like "%"#{carType}"%"
            </if>
        </where>
    </select>
</mapper></span></span>
2、trim
  • 增删前后缀

<span style="background-color:#f8f8f8"><span style="color:#333333">@Mapper
public interface CarMapper {
    /**
     * 使用trim标签
     */
    List<Car> selectByMultiConditionWithTrim(@Param("brand") String brand,
                                             @Param("guidePrice") Double guidePrice,
                                             @Param("carType") String carType);
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333"><mapper namespace="com.chf.mapper.CarMapper">
    <!--
        prefix:加前缀
        suffix:加后缀
        prefixOverrides:删除前缀
        suffixOverrides:删除后缀
        以下表示在trim标签所有内容的前面添加where,后缀的and或者or去掉
    -->
    <select id="selectByMultiConditionWithTrim" resultType="Car">
        select
            id,car_num,brand,guide_price,produce_time,car_type
        from
            t_car
        <trim prefix="where" suffixOverrides="and|or">
            <if test="brand != null and brand != ''">
                brand like "%"#{brand}"%" and
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                guide_price >= #{guidePrice} and
            </if>
            <if test="carType != null and carType != ''">
                car_type like "%"#{carType}"%"
            </if>
        </trim>
    </select>
</mapper></span></span>
3、set 标签
  • 主要使用在update语句当中,用于生成set关键字,同时去掉最后多余的",";

  • 比如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。

<span style="background-color:#f8f8f8"><span style="color:#333333">@Mapper
public interface CarMapper {
    /**
     * 使用set标签进行更新
     */
    int updateBySet(Car car);
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333"><mapper namespace="com.chf.mapper.CarMapper">
    <update id="updateBySet">
        update
            t_car
        <set>
            <if test="carNum != null and carNum != ''">car_num = #{carNum},</if>
            <if test="brand != null and brand != ''">brand = #{brand},</if>
            <if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if>
            <if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if>
            <if test="carType != null and carType != ''">car_type = #{carType}</if>
        </set>
        where
            id = #{id}
    </update>
</mapper></span></span>
4、choose where otherwise
  • 三个标签一起使用,相当于if-else if-else

    <span style="background-color:#f8f8f8">@Mapper
    public interface CarMapper {
        /**
         * 使用choose when otherwise标签
         */
        List<Car> selectByChoose(@Param("brand") String brand,
                                 @Param("guidePrice") Double guidePrice,
                                 @Param("carType") String carType);
    }</span>
    <span style="background-color:#f8f8f8"><mapper namespace="com.chf.mapper.CarMapper">
        <select id="selectByChoose" resultType="Car">
            select
                id,car_num,brand,guide_price,produce_time,car_type
            from
                t_car
            <where>
                <choose>
                    <when test="brand != null and brand != ''">
                        brand like "%"#{brand}"%"
                    </when>
                    <when test="guidePrice != null and guidePrice != ''">
                        guide_price >= #{guidePrice}
                    </when>
                    <otherwise>
                        car_type like "%"#{carType}"%"
                    </otherwise>
                </choose>
            </where>
        </select>
    </mapper></span>
5、foreach标签
  • 常用于批量删除,in关键字查询:

    <span style="background-color:#f8f8f8">@Mapper
    public interface CarMapper {
        /**
         * 根据id批量删除 foreach
         */
        int deleteByIds(@Param("ids") Long[] ids);
    }</span>
    <span style="background-color:#f8f8f8"><mapper namespace="com.chf.mapper.CarMapper">
        <!--
            foreach标签的属性:
                collection:所传入的数组或集合参数
                item:经过处理后的数组或集合中的元素,并可赋值给#{}
                separator:各个元素之间的分隔符
                open:在所有元素之前添加的开始符号
                close:在所有元素之后添加的结束符号
        -->
        <update id="deleteByIds">
            delete from
                t_car
            where
                id in
                <foreach collection="ids" item="aaa" separator="," open="(" close=")">
                    #{aaa}
                </foreach>
        </update>
    </mapper></span>

4、分页

  • 可以直接在SQL语句中为limit 关键字传入参数。startIndex(起始下标,下标从0开始)和pageSize(每页显示的记录条数)。

  • 使用分页插件对查询到的分页结果进行包装:

    • 引入PageHelper插件依赖:

      <span style="background-color:#f8f8f8"><dependency>
          <groupId>com.github.pagehelper</groupId>
          <artifactId>pagehelper-spring-boot-starter</artifactId>
          <version>1.2.12</version>
      </dependency></span>
    • 在核心启动类的@SpringBootApplication注解后面添加:

      <span style="background-color:#f8f8f8">@SpringBootApplication(exclude = PageHelperAutoConfiguration.class)</span>
    • 在代码中使用:

      <span style="background-color:#f8f8f8">public PageInfo<Car> testPageInfo(int pageNum,int pageSize) {
          int startIndex = (pageNum - 1) * pageSize;
          List<Car> cars = carMapper.selectByPage(startIndex,pageSize);
          // 封装查询后的结果
          PageInfo<Car> carPageInfo = new PageInfo<>(car,pageSize);
          return carPageInfo;
      }</span>

3、mybatis-plus

1、基本使用

  • 调用 mapper 的基本方法,在serviceImpl类中使用LambdaQueryWrapperLambdaUpdateWrapper构造查询条件,查询或修改时把条件语句作为参数传递进去即可。

<span style="background-color:#f8f8f8"><span style="color:#333333">public interface UserMapper extends BaseMapper<User> { // BaseMapper是MyBatis-Plus提供的模板mapper,其中包含了基本的CRUD方法,泛型为操作的实体类型
}</span></span>

MyBatis-Plus中有一个接口IService和其实现类ServiceImpl,封装了常见的业务层逻辑:

<span style="background-color:#f8f8f8"><span style="color:#333333">public interface UserService extends IService<User> { 
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">/**
* ServiceImpl实现了IService,提供了IService中基础功能的实现
* 若ServiceImpl无法满足业务需求,则可以使用自定的UserService定义方法,并在实现类中实现
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    //避免使用字符串表示字段,防止运行时错误
    queryWrapper
        .like(StringUtils.isNotBlank(username), User::getName, username)
        .ge(ageBegin != null, User::getAge, ageBegin)
        .le(ageEnd != null, User::getAge, ageEnd);
    List<User> users = userMapper.selectList(queryWrapper);

}</span></span>

分页查询

  • 配置分页插件:

<span style="background-color:#f8f8f8"><span style="color:#333333">@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper") //可以将主类中的注解移到此处
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new
        PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}</span></span>
  • 使用:

<span style="background-color:#f8f8f8"><span style="color:#333333">@Test
public void testPage(){
    //设置分页参数
    Page<User> page = new Page<>(1, 5);
    userMapper.selectPage(page, null);
    //获取分页数据
    List<User> list = page.getRecords();
    list.forEach(System.out::println);
    System.out.println("当前页:"+page.getCurrent());
    System.out.println("每页显示的条数:"+page.getSize());
    System.out.println("总记录数:"+page.getTotal());
    System.out.println("总页数:"+page.getPages());
    System.out.println("是否有上一页:"+page.hasPrevious());
    System.out.println("是否有下一页:"+page.hasNext());
}</span></span>

2、常用注解

  • @TableName("t_user"):在实体类上添加该注解,用以标识该实体类所对应的表名字,默认为实体类首字母小写。开发过程中,数据库中对应的表通常都有t_tb\_前缀,我们可以在配置文件中统一配置全局前缀,@TableName("t_user")注解中就不用写t_了;mybatis-plus.global-config.db-config.table-prefix

  • @TableId(value = "xxx"):指定表主键 id,未指定的话默认将id属性作为主键。其value值指的是数据库表中的主键字段,默认是id

  • @TableField("xxx"):指定该实体类属性与表中哪个字段对应,默认和属性名同名或驼峰法转下划线法;

  • @TableLogic:作用于某个属性,把它作为逻辑删除属性;

  • 条件构造的QueryWrapperLambdaQueryWrapper

  • 分页查询:Page page = new Page<>(1, 5);

3、MyBatis中的$和#有什么区别?

  • 使用#设置参数时,MyBatis会创建预编译的SQL语句,然后在执行SQL时MyBatis会为预编译SQL中的占位符(?)赋值。预编译的SQL语句执行效率高,并且可以防止注入攻击;

  • 使用$设置参数时,MyBatis只是创建普通的SQL语句,然后在执行SQL语句时MyBatis将参数直接拼入到SQL里。这种方式在效率、安全性上均不如前者,但是可以解决一些特殊情况下的问题;

  • 在一些动态表格(根据不同的条件产生不同的动态列)中,我们要传递SQL的列名,根据某些列进行排序,或者传递列名给SQL都是比较常见的场景,这就无法使用预编译的方式了(因为这时的SQL语句都不完整,无法预编译);

@Mapper与@MapperScan

区别与联系

  • @Mapper用在接口上,在编译之后会生成相应的接口实现类,并放入 IOC 容器。@MapperScan 在SpringBootApplication启动类上面使用,如下,说明扫描“cn.cvs.mapper”此包下的所有mapper接口,生成对应的实现类;

  • @Mapper是队单个接口类的注解,单个操作。(接口少的时候适合使用),而@MapperScan是对整个包之下的所有的接口类的注解,是批量的操作。使用@MapperScan之后,接口类就不需要再使用@Mapper注解了;

  • @MapperScan可以扫描多个包,参数传一个字符串数组即可。

<span style="background-color:#f8f8f8"><span style="color:#333333">@Mapper // 用在接口上,在编译之后会生成相应的接口实现类
public interface ItripUserMapper {
    public ItripUser getItripUserById(@Param(value = "id") Long id)throws Exception;

	public List<ItripUser>	getItripUserListByMap(Map<String,Object> param)throws Exception;
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">@MapperScan("cn.cvs.mapper") // 扫描指定包下所有的接口类,然后所有接口在编译之后都会生成相应的实现类
@SpringBootApplication
public class SpringBootApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootApplication.class, args);
	}

}</span></span>

3、Spring MVC

1、请求方法注解

  • @RequestMapping(value = {"/testRequestMapping", "/test"}:配置请求映射路径,通常是作用于controller类上,用于标识和区别某一类的请求类型,value值可以有多个,请求匹配任意一个即可。支持ant风格的路径:

    • ?:表示任意的单个字符;

    • :表示任意的0个或多个字符;

    • *:表示任意的一层或多层目录,注意:在使用**时,只能使用/**/xxx的方式。

  • 注解参数详解:

    • value;

    • method;

    • params:通过请求的请求参数匹配请求映射,属性值是一个字符串类型的数组,可以通过四种表达式设置请求参数和请求映射的匹配关系:

      • "param":要求请求映射所匹配的请求必须携带param请求参数

      • "!param":要求请求映射所匹配的请求必须不能携带param请求参数

      • "param=value":要求请求映射所匹配的请求必须携带param请求参数且param=value

      • "param!=value":要求请求映射所匹配的请求必须携带param请求参数但是param!=value

<span style="background-color:#f8f8f8"><span style="color:#333333">@RequestMapping(
        value = {"/testRequestMapping", "/test"} // 指定路径
        ,method = {RequestMethod.GET, RequestMethod.POST} // 指定请求方法类型
        ,params = {"username","password!=123456"}
)
public String testRequestMapping(){
    return "success";
}</span></span>

  • @GetMapping("/get"):接收get请求,支持ant风格路径,支持路径传参,例下:id和username是接收请求路径中的参数,,且在方法参数中使用@PathVariable("id")接收参数。

    <span style="background-color:#f8f8f8">@RequestMapping("/testRest/{id}/{username}")
    public String testRest(@PathVariable("id") String id, @PathVariable("username") String username){}</span>
  • @PostMapping("/post1"):接收post请求(其余和前述一样);

  • @DeleteMapping("/delete1"):接收delete请求(其余和前述一样);

  • @UpdateMapping("/update1"):接收update请求(其余和前述一样);

2、请求方法参数注解

  • @PathVariable:获取请求路径中传递的参数;

  • @RequestParam:基本不用,因为它不是REST风格;

  • @RequestBody:获取请求体参数,是JSON格式的,当前请求的请求体就会为当前注解所标识的形参赋值,如下:注意该参数也可以是一个实体类,对象,只要传递的请求体参数与该实体类的部分属性的变量名有对应即可。

    <span style="background-color:#f8f8f8">@PostMapping("/testRequestBody")
    public String testRequestBody(@RequestBody String requestBody){
        /**/
    }</span>
  • @ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器;

  • @RestController注解是@Controller和@ResponseBody的一个复合注解;

3、统一异常处理

  • @ControllerAdvice将当前类标识为异常处理的组件。例如:

    <span style="background-color:#f8f8f8">@ControllerAdvice  // mvc统一异常处理!
    public class ExceptionController {
        //@ExceptionHandler用于设置所标识方法处理的异常
        @ExceptionHandler(ArithmeticException.class)
        //ex表示当前请求处理中出现的异常对象
        public String handleArithmeticException(Exception ex, Model model){
            model.addAttribute("ex", ex);
            return "error";
        }
    }</span>

4、过滤器/拦截器

5、文件上传与下载

文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"

SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息

上传步骤:

a>添加依赖:

<span style="background-color:#f8f8f8"><span style="color:#333333"><!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency></span></span>

b>在SpringMVC的配置文件中添加配置:

<span style="background-color:#f8f8f8"><span style="color:#333333"><!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean></span></span>

c>控制器方法:

<span style="background-color:#f8f8f8"><span style="color:#333333">@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
    //获取上传的文件的文件名
    String fileName = photo.getOriginalFilename();
    //处理文件重名问题
    String hzName = fileName.substring(fileName.lastIndexOf("."));
    fileName = UUID.randomUUID().toString() + hzName;
    //获取服务器中photo目录的路径
    ServletContext servletContext = session.getServletContext();
    String photoPath = servletContext.getRealPath("photo");
    File file = new File(photoPath);
    if(!file.exists()){
        file.mkdir();
    }
    String finalPath = photoPath + File.separator + fileName;
    //实现上传功能
    photo.transferTo(new File(finalPath));
    return "success";
}</span></span>

4、Spring Boot

1、基本认识

parent

开发Spring Boot程序都要继承一个 spring-boot-starter-parent,其中定义了上百个依赖管理。我们添加依赖的时候如果不指定版本号,默认就是继承parent 定义的版本,好处是它里边定义的一组版本之间不会产生依赖冲突,省了我们很多的麻烦;

starter

开发者要完成某一项功能时,需要引入一大堆依赖,容易出错,starter则是定义这样一组固定技术搭配,完成某项功能时,只要引入固定starter即可,而不必写若干个依赖了。要注意它与parent的区别;

starter命名规范

starter所属命名规则示例
官方提供spring-boot-starter-技术名称spring-boot-starter-web spring-boot-starter-test
第三方提供第三方技术名称-spring-boot-startermybatis-spring-boot-starter druid-spring-boot-starter

引导类

Spring Boot 使用@SpringBootApplication注解标注了一个类,该类的main方法就是程序启动的入口,成为引导类。

内嵌tomcat

内嵌Tomcat服务器是 Spring Boot 辅助功能之一。内嵌 Tomcat 工作原理是将 Tomcat 服务器作为对象运行,并将该对象交给Spring容器管理。

2、Spring Boot中的配置文件

配置文件优先级

properties(最高)> yml > yaml(最低),不同配置文件中相同配置按照加载优先级相互覆盖,不同配置则全部保留。

读取配置文件

读取单一数据

yaml中保存的单个数据,可以使用Spring中的注解@Value读取单个数据,属性名引用方式:${一级属性名.二级属性名……}

读取全部数据

读取单一数据可以解决读取数据的问题,但是如果定义的数据量过大,这么一个一个书写肯定会累死人的,SpringBoot提供了一个对象,能够把所有的数据都封装到这一个对象中,这个对象叫做Environment,使用自动装配注解可以将所有的yaml数据封装到这个对象中

数据封装到了Environment对象中,获取属性时,通过Environment的接口操作进行,具体方法是getProperties(String),参数填写属性名即可

读取对象数据:使用@ConfigurationProperties必须告诉他加载的数据前缀是什么,记得数据属性名要与对象的变量名一一对应

3、热部署

热部署,简单来说就是程序修改后,服务器会自动把更新后的程序给重新加载一遍,而不用重启项目。

使用热部署

步骤①:导入开发者工具对应的坐标

<span style="background-color:#f8f8f8"><span style="color:#333333"><dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency></span></span>

步骤②:修改项目后,使用快捷键完成热部署:Build --- Build Project;

开启自动热部署

自动热部署是和开发工具有关的,就是允许了开发工具的自动进行热部署,以下以idea为例设置idea中启动热部署。

步骤①:设置允许自动构建项目

打开【File】,选择【settings...】,在面板左侧的菜单中找到【Compile】选项,然后勾选【Build project automatically】,意思是自动构建项目

步骤②:允许在程序运行时进行自动构建

使用快捷键【Ctrl】+【Alt】+【Shit】+【/】打开维护面板,选择第1项【Registry...】

在选项中搜索comple,然后勾选compiler.automake.allow.when.app.running项即可。

idea中默认当idea工具失去焦点5秒后进行热部署。其实就是你从idea工具中切换到其他工具时进行热部署,比如改完程序需要到浏览器上去调试,这个时候idea就自动进行热部署操作。

4、SpringBoot解析yml中的数字

  • 做SpringBoot项目的时候,要连接本地数据库作为,当时把数据库密码设置成自己的生日,以0开头的四位数,但是启动项目时总是报错数据库密码错误;

  • 检查了几遍数据库密码都没有问题,也上网找了很多解决方案,有说数据库加密方式和SpringBoot连接数据库时加密方式不一致的,等等;

  • 最后,我在测试类中直接读取密码,结果看到取出来的数字不是在yml文件中配置的值,然后上网一查才知道原来是SpringBoot会默认把0开头的数字看成是八进制的,0x开头的就看成是十六进制,所以才会密码错误;

  • 最后我就把密码改了,不以0开头,解决;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值