Java_五个月学习_第三阶段

13 篇文章 0 订阅
8 篇文章 0 订阅

第三阶段

day51、GIT

1.1操作步骤

  • 下载git软件
  • idea端
    • 配置idea
      • plugins配置下:安装好gir软件
      • git设置:路径配置
      • open->project form version control
  • 注册git账号
    • 创建组织
    • 创建仓库
  • 克隆复制项目
  • filter
    本地

1、git的具体详细

  • 1.1 文件名是颜色识别
    • 红色:不上传的文案
    • 绿色:文件
    • 蓝色:未上传的的文件
  • 1.2 pull备注
    • 1.1.1 第一个1大版本 第二数:功能的添加 第3个数:当前版本修改了多少个漏洞

day52、Maven

1.打包方式

 - 1.1 pom:父项目
      
 - 1.2 war:发布的子项目
 - 1.3 jar:不发布的工具项目

2.依赖关系

 war 包依赖 jar 包,war 包不依赖 war 包
    在 war 包的 pom.xml 的 dependencies 中
            <!--依赖 shop-pojo -->
            <dependency>
                <groupId>com.qf.nice</groupId>
                <artifactId>shop-pojo</artifactId>//jar包项目名
                <version>1.0.0-SNAPSHOT</version>
            </dependency>

3.封装坐标版本号

3.1 在 properties 标签中添加自定义标签:
        <junit-version>4.11</junit-version>
        <serlvet-version>4.0.1</serlvet-version>
        <mysql-version>5.1.6</mysql-version>
    3.2 在对应的坐标中引用版本号
        <version>${junit-version}</version>

4.创建 jar 包

4.1 File -- Project Structure
    4.2 Artifacts -- "+" -- JAR -- From modules with ....
    4.3 勾选 Include in project build
    4.4 回到主页面 Build -- Build Artifacts

5.上传 jar 包本地仓库

mvn install:install-file -Dfile=jar包位置 -DgroupId=组织名 -DartifactId=项目名 -Dversion=版本号 -Dpackaging=jar

    mvn install:install-file -Dfile=D:\Software\java-jar\DBManger.jar -DgroupId=com.qf.hao.utils -DartifactId=DBManager -Dversion=1.0.0 -Dpackaging=jar

day53、day53 Spring-Ioc

关于Ioc介绍

1.配置文件方式

- 1.1 导入 Spring 容器的坐标
 - 1.2 创建 spring-context.xml IOC的配置文件
           <bean class="com.qf.com.qf.ran.dao.impl.ClassDaoImpl" id="classDao"/>
 - 1.3 加载配置文件创建 Spring 容器
           ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");
 - 1.4 从容器中获取指定的对象
           ClassDao classDao = (ClassDao) ctx.getBean("classDao");

2.注解方式

3、部分代码

//1、关于配置文件
 <!-- 开启扫描,扫描有注解的包,让注解生效 -->
    <context:component-scan base-package="com.qf.ran.controller"/>
    <context:component-scan base-package="com.qf.ran.service.impl"/>
    <context:component-scan base-package="com.qf.ran.dao.impl"/>

//2、关于部分注解
/**
 * @author Ran
 * @since JDK 1.8
 */
/*依赖*/
//@Component
@Controller
public class StudentController {
    /*对象注入*/
    @Autowired
    StudentService studentService;

    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }

    public void method(){
        System.out.println("Controller:"+studentService.method1());
    }
}
1.添加 xml 配置文件开启扫描支持注解,base-package 值为注解所在的包
      <context:component-scan base-package="com.qf.ran.controller"/>
    2.添加依赖注解
        @Component      --  把对象创建的控制权交给 Spring 容器(支持所有的类)
        @Controller     --  支持控制成的注解
        @Service        --  支持业务逻辑层的注解
        @Repository     --  支持持久层的注解
    3.添加注入注解
        @Autowired      --  默认使用类型查找对象
                            默认选项为 true ,设置为 false 代表注入的对象可以为 null
                            在多线程中是不安全的
                            如果出现菱形依赖问题
                            可以通过 Autowired 修饰有参构造方法来解决依赖问题
                            先创建对象再注入属性对象

        @Resources      --  默认根据 name 在容器中查找对象,没有 name 则根据类型查找对象
                            不允许对象为 null,线程安全

day54、spring-aop

关于AOP介绍

1、代理

1.业务划分:
    主业务:
        转账、充值
    系统级业务:
        事务控制、日志控制

2.静态代理:
    优势:把主业务和系统级业务划分开
    劣势:每个业务对象都需要一个代理类,会造成类的冗余

3.动态代理:
    优势:每一个业务对象都可以使用同一个代理,减少类的冗余
    劣势:产生对象的冗余,占用内存空间,修改了源代码

2、SpringAOP

4.SpringAOP:面向切面编程  --  基于XML配置
    4.1 引入jar包
    				//注意这里没有显示版本号,是要导入有版本号才行
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aop</artifactId>
                </dependency>

                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aspects</artifactId>
                </dependency>

                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-test</artifactId>
                </dependency>
    4.2 添加增强类 TransactionAdvice ,增强类中定义增强方法
    4.3 添加XML配置文件 Spring-AOP.xml
        前置增强
        后置增强
        环绕增强
        异常处理增强
        方法返回增强

5.SpringAOP:面向切面编程  --  基于注解
    5.1 引入 jar 包
    5.2 创建切面类,并使用注解 @Component @Aspect
    5.3 定义切点的方法,并添加注解
        @Pointcut("execution(* com.qf.ran.service.impl.*ServiceImpl.pay(..))")
    5.4 编写增强方法并添加对应的注解
    5.5 在Spring配置文件中添加支持 AOP 注解的配置
        <aop:aspectj-autoproxy/>

2、遇到3个bug

1、plign文件找不到解决办法
2、导包包已经下载好但是还是报错:idea的seting中勾选dubug …Maven
3、初始化异常:将juit测试包升级

3、部分代码

//1、配置文件配置
 <!-- 开启扫描,支持IOC注解 -->
    <context:component-scan base-package="com.qf.ran"/>

    <!--开启AOP注解支持(支持JDK动态代理)-->
    <aop:aspectj-autoproxy/>

    <!--开启AOP注解支持(proxy-target-class 设置为 true 代表使用cglib代理)-->
    <!--<aop:aspectj-autoproxy proxy-target-class="true"/>-->
//2、关于代理类
*/
@Component
/*代表切面类*/
@Aspect
public class TransactionAdvice {
    //定义切点
    @Pointcut("execution(* com.qf.ran.service.impl.*ServiceImpl.pay(..))")//那些类需要增强写入
    public void transactionPC(){

    }

    //前置增强
    @Before("TransactionAdvice.transactionPC()")
    public void before(){
        System.out.println("前置增强(注解)");
    }

    //后置增强
    @After("TransactionAdvice.transactionPC()")
    public void after(){
        System.out.println("后置增强(注解)");
    }

    //后置增强(异常出现后增强)
    @AfterThrowing("TransactionAdvice.transactionPC()")
    public void afterThrowing(){
        System.out.println("异常增强(注解)");
    }

    //后置增强(方法返回结果后增强)
    @AfterReturning("TransactionAdvice.transactionPC()")
    public void afterReturning(){
        System.out.println("返回结果后");
    }

    //环绕增强
    @Around("TransactionAdvice.transactionPC()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕前(注解)");
        Object proceed = point.proceed();
        System.out.println("环绕后(注解)");
        return proceed;
    }


}
//3、关于测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:Spring-context.xml"})//加载配置文件
public class UserControllerTest {
    @Autowired
    private UserController userController;
    @Test
    public void testTransferAccounts(){
        userController.transferAccounts();
    }
}

Day55、SpringMvc

spring的介绍

1、SpringMvc的配置

1.1 导入 SpringMVC 的jar包
            <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring-webmvc</artifactId>
                 <version>${springmvc-version}</version>
            </dependency>
    1.2 添加 Spring 的配置文件
        1.2.1 开启 Spring 扫描
        1.2.2 开启 SpringMVC 的注解支持    --  注意约束
    1.3 配置 web.xml 文件
        1.3.1 配置编码过滤器,初始化参数指定编码格式为UTF-8
        1.3.2 配置 DispatcherServlet 分发器,初始化参数加载 Spring 配置文件
        1.3.3 配置 html 请求的默认访问
    1.4 创建 Controller 层的类,添加注解@Controller @RequestMapping("/请求路径")
    1.5 添加对应的方法并使用注解@RequestMapping("/请求路径")

2、SpringMVC的请求和响应

2.1 添加 jar (fastjson、jackson)
    2.2 Spring 配置文件添加消息转换器
    2.3 前端发送ajax请求
    2.4 添加 RespBean 类
    2.5 Controller 层类方法添加注解 @ResponseBody (告诉Spring容器,返回的对象需要经过消息转换器转换成json 格式数据)

3、关于代码

//xml文件
<!--开启 Spring 的扫描-->
    <context:component-scan base-package="com.qf.ran"/>

    <!--开启 SpringMVC 的注解支持-->
    <mvc:annotation-driven/>
    
    <!--消息转换器配置 FastJson-->
    <!--把响应对象转换成json格式对象-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="false">
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=utf-8</value>
                        <value>application/json;charset=utf-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>


//2、前端控制器
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!--1.配置编码过滤器-->
  <filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--初始化-->
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!--2.配置 SpringMVC 分发器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 初始化 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <!--加载配置文件-->
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--3.默认访问-->
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
  </servlet-mapping>

</web-app>

//3、导jar包
 <dependencies>
        <!-- SpringMVC -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springmvc-version}</version>
        </dependency>
        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>
    </dependencies>
//部分注释
/**
 * @author Ran
 * @since JDK 1.8
 */
@Controller
/*请求的映射路径*/
@RequestMapping("/User")
public class UserController {
    @Autowired
    private UserService userService;

/*    @RequestMapping("/login")
    *//*响应对象为json格式数据*//*
    @ResponseBody
    public RespBean login(String username,String password){
        System.out.println("username:"+username);
        System.out.println("password:"+password);
        RespBean respBean = userService.login(username, password);
        return respBean;
    }*/

    @RequestMapping("/login")
    /*响应对象为json格式数据*/
    @ResponseBody
    public RespBean login(User user){
        System.out.println("user的username:"+user.getUsername());
        System.out.println("user的password:"+user.getPassword());
        RespBean respBean = userService.login(user.getUsername(), user.getPassword());
        return respBean;
    }


    @RequestMapping("/register")
    public void register(){
        System.out.println("注册方法");
    }
}

day56、Swagger、SpringMVC 异常处理、SpringMVC 拦截器

注解解释

DTO等详解

:@RestController注解相当于@ResponseBody + @Controller合在一起的作用
 @ResponseBody的作用其实是将java对象转为json格式的数据。
 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置


*      PO:Persistent Object        持久对象            --  与数据库的字段一致对象
 *      BO:Business Object          业务对象            --  把业务逻辑需要的属性封装成一个对象
 *      VO:Value/View Object        值对象/视图对象     --  抽象出的业务对象,主要对应页面显示的对象
 *      DTO:Data Transfer Object    数据传输对象        --  在进行跨域或者远程传输时使用的对象

Responsebody

1.SpringMVC 注解

SpringMvc生命周期

/*
.1 RequestMapping
            1.1.1 value     --  请求映射路径
            1.1.2 method    --  指定提交方式
            1.1.3 params    --  约束请求提交的参数
    1.2 指定提交方式的映射注解
        GetMapping、PostMapping...
    1.3 RestController = Controller + ResponseBody
        把控制层交由 Spring 创建对象并把当前对象中所有方法返回值指定转换为 json 格式数据
*/
    //在类中添加注解,所有的方法都以json格式的对象方法
   @GetMapping("/login")
    public RespBean login(User user){
        System.out.println("user的username:"+user.getUsername());
        System.out.println("user的password:"+user.getPassword());
        RespBean respBean = userService.login(user.getUsername(), user.getPassword());
        return respBean;
    }


    //提交方式只能是get请求
    @GetMapping("/login")
    @ResponseBody
    public RespBean login(User user){
        System.out.println("user的username:"+user.getUsername());
        System.out.println("user的password:"+user.getPassword());
        RespBean respBean = userService.login(user.getUsername(), user.getPassword());
        return respBean;
    }*/
    把控制层交由 Spring 创建对象并把当前对象中所有方法返回值指定转换为 json 格式数据
    // 提交方式: GET:获取信息        POST:更新操作        PUT:新增操作         DELETE:删除操作
    //代表提交方式只能是GET或者POST请求
   @RequestMapping(value = "/login",method= {RequestMethod.GET,RequestMethod.POST})
    @ResponseBody
    public RespBean login(User user){
        System.out.println("user的username:"+user.getUsername());
        System.out.println("user的password:"+user.getPassword());
        RespBean respBean = userService.login(user.getUsername(), user.getPassword());
        return respBean;
    }
 
 <!--定义对象json装换器-->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <ref bean="stringHttpMessageConverter"/>
            <ref bean="mappingJackson2HttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <bean id="stringHttpMessageConverter"
          class="org.springframework.http.converter.StringHttpMessageConverter"/>

    <!--解决IE浏览器json文件下载和json数据中文乱码的问题-->
    <bean id="mappingJackson2HttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <property name="supportedMediaTypes">
            <list>
                <value>text/html;charset=UTF-8</value>
                <value>application/json;charset=UTF-8</value>
            </list>
        </property>
    </bean>

2.Swagger – 接口文档

  • 2.1 添加 jar 包
 <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger-version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>
  • 2.2 添加配置文件类 SwaggerConfiguration
/**
 * @author Ran
 * @since JDK 1.8
 */
/*代表当前类为配置文件类*/
@Configuration
@EnableSwagger2
/*扫描包 支持Swagger注解*/
@ComponentScan("com.qf.ran")
public class SwaggerConfiguration {
    /*需要创建的对象*/
    @Bean
    public Docket createAPI() {
        return new Docket(DocumentationType.SWAGGER_2)
                .forCodeGeneration(true)
                .select()
                .apis(RequestHandlerSelectors.any())
                //过滤生成链接
                .paths(PathSelectors.any())
                .build()
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        Contact contact = new Contact("Ran", "http://baidu.com"
                , "j_daran@qq.com");
        ApiInfo apiInfo = new ApiInfoBuilder()
                .license("Apache License Version 2.0")
                .title("Swagger 集成测试")
                .description("Swagger API Teste")
                .contact(contact)
                .version("1.0")
                .build();
        return apiInfo;
    }
}

2.3 web.xml 添加默认访问 *.css *.js *.html

<!--3.默认访问-->
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
  </servlet-mapping>
  • 2.4 Spring 的配置文件添加 swagger-ui 的配置
 <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources"/>
            <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars"/>
  • 2.5 对应的类和方法添加 swagger 注解
 @Api(tags="用户模块")                   --  模块注解
        @ApiOperation("登录功能")               --  方法注解
        @ApiModel                               --  实体类注解
        @ApiModelProperty(value = "状态值")     --  实体类属性注解
@Api(tags="用户模块")
@RestController
@RequestMapping("/User")
public class UserController {
    @Autowired
    private UserService userService;

    @ApiOperation("登录功能")
    @GetMapping(value = "/login")
    public RespBean login(User user){
        System.out.println("user的username:"+user.getUsername());
        System.out.println("user的password:"+user.getPassword());
        RespBean respBean = userService.login(user.getUsername(), user.getPassword());
        return respBean;
    }

    @ApiOperation("注册功能")
    @RequestMapping("/register")
    public void register(){
        System.out.println("注册方法");
    }
}

3.SpringMVC 异常处理

  • 3.1 创建全局异常处理对象 HandlerException 添加注解@ControllerAdvice
  • 3.2 添加异常处理方法,参数为异常类型
    添加注解@ExceptionHandler 标记为异常处理方法
    value 代表只针对某个异常进行处理
@ControllerAdvice
@ResponseBody
public class HandlerException {
    //异常处理,value = AccountException.class 代表只处理 AccountException 异常
    @ExceptionHandler(value = AccountException.class)
    public RespBean handlerException(AccountException e){
        //e.getMessage() 获取异常信息
        return RespBean.respError(e.getMessage());
    }


/*处理所有的异常
    @ExceptionHandler
    public RespBean handlerException(Exception e){

    }*/
}

4.SpringMVC 拦截器

  • 4.1 创建拦截器类 LoginInterceptor 实现 HandlerInterceptor
  • 4.2 重写 preHandle() true 代表放行 false 代表拦截
/**
 * @author Ran
 * @since JDK 1.8
 *
 *      登录拦截器
 */
public class LoginInterceptor implements HandlerInterceptor {
    //拦截方法      --  true为放行,false为拦截
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        Integer id = (Integer)request.getSession().getAttribute("id");
        if(id == null){
            throw new LoginException("用户未登录");
        }
        return true;
    }
}
  • 4.3 在 Spring 配置文件添加拦截器栈,添加登录拦截器,指定需要拦截的请求和不需要拦截的请求以及对应的拦截器类
<!--拦截器栈配置-->
    <mvc:interceptors>
        <!--配置登录拦截器-->
        <mvc:interceptor>
            <!--需要拦截的请求-->
            <!--
                /*  代表只能拦截 /SpringMVC-interceptor/User
                /** 代表能拦截   /SpringMVC-interceptor/User/login
            -->
            <mvc:mapping path="/**"/>

            <!--不需要拦截的请求-->
            <!--swagger资源排除-->
            <mvc:exclude-mapping path="/swagger-ui.html"/>
            <mvc:exclude-mapping path="/webjars/**"/>
            <mvc:exclude-mapping path="/swagger-resources/**"/>
            <mvc:exclude-mapping path="/v2/api-docs/**"/>

            <!--排除登录和注册请求-->
            <mvc:exclude-mapping path="/User/login"/>
            <mvc:exclude-mapping path="/User/register"/>

            <!--文件上传-->
            <mvc:exclude-mapping path="/file/upload"/>

            <!--指定拦截器类-->
            <bean class="com.qf.ran.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

5.SpringMVC 文件上传

  • 5.1 加载 jar 包
 <!--文件上传 start-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
        <!--文件上传 end-->
  • 5.2 在 Spring 配置文件添加文件上传,指定文件上传的大小和编码格式
 <!--文件上传配置-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--文件上传大小限制-->
        <property name="maxUploadSize" value="104857600"/>
        <!--文件上传的编码-->
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>
  • 5.3 添加对应的业务接口方法,方法参数添加 MultipartFile flie
    file.getOriginalFilename() – 获取文件名
    file.transferTo() – 存储文件
**
 * @author Ran
 * @since JDK 1.8
 *
 *      文件上传模块
 */
@Api(tags = "文件上传模块")
@RestController
@RequestMapping("/file")
public class FileUploadController {

    @ApiOperation("文件上传")
    @PostMapping(value = "/upload",consumes = "multipart/*",
            headers = "content-type=multipart/form-data")
    public RespBean upload(@ApiParam(value = "文件") MultipartFile file, HttpServletRequest request, HttpServletResponse response){
        //1\获取 img 路径并创建目录
        String realPath = request.getServletContext().getRealPath("/asserts/img");

        //解决重名
        //获取文件名
        String fileName = file.getOriginalFilename();
        fileName = UUID.randomUUID().toString() +"_"+fileName;

        //存储文件到服务器
        try {
            file.transferTo(new File(realPath,fileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return RespBean.respSuccess("文件上传成功");
    }
}

day57、MyBaits

报错

lamba表达式错误

打包遇到错误

1 Spring整合MyBatis

  • 1.1 加入 jar 包 – 6个jar包
<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <!--Spring start-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--Spring end-->
    <!--druid start -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.23</version>
    </dependency>
    <!--druid end -->

    <!-- mysql start-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql-version}</version>
    </dependency>
    <!-- mysql end-->

    <!--mybatis start-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.5</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.5</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!--mybatis end-->

    <!--lombok start-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lombok-version}</version>
    </dependency>
    <!--lombok end-->

    <!--测试类加载配置文件 start-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
      <scope>test</scope>
    </dependency>
    <!--测试类加载配置文件 end-->
  • 2.添加配置文件
    • jdbc.properties 数据库连接驱动文件
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
# JDBC Pool
jdbc.pool.init=1
jdbc.pool.minIdle=3
jdbc.pool.maxActive=20
# JDBC Test
jdbc.testSql=SELECT 'x' FROM DUAL
  • MyBatis-config.xml MyBatis的配置文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 全局参数 -->
    <settings>
        <!-- 打印 SQL 语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
        <!-- 使全局的映射器启用或禁用缓存。 -->
        <setting name="cacheEnabled" value="false"/>
        <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。 -->
        <setting name="aggressiveLazyLoading" value="true"/>
        <!-- 是否允许单条 SQL 返回多个数据集 (取决于驱动的兼容性) default:true -->
        <setting name="multipleResultSetsEnabled" value="true"/>
        <!-- 是否可以使用列的别名 (取决于驱动的兼容性) default:true -->
        <setting name="useColumnLabel" value="true"/>
        <!-- 允许 JDBC 生成主键。需要驱动器支持。如果设为了 true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。 default:false  -->
        <setting name="useGeneratedKeys" value="false"/>
        <!-- 指定 MyBatis 如何自动映射 数据基表的列 NONE:不映射 PARTIAL:部分 FULL:全部  -->
        <setting name="autoMappingBehavior" value="PARTIAL"/>
        <!-- 这是默认的执行类型 (SIMPLE: 简单; REUSE: 执行器可能重复使用prepared statements语句;BATCH: 执行器可以重复执行语句和批量更新) -->
        <setting name="defaultExecutorType" value="SIMPLE"/>
        <!-- 使用驼峰命名法转换字段。 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 设置本地缓存范围 session:就会有数据的共享 statement:语句范围 (这样就不会有数据的共享 ) defalut:session -->
        <setting name="localCacheScope" value="SESSION"/>
        <!-- 设置 JDBC 类型为空时,某些驱动程序 要指定值, default:OTHER,插入空值时不需要指定类型 -->
        <setting name="jdbcTypeForNull" value="NULL"/>
    </settings>
</configuration>
  • Spring-context.xml      Spring配置文件
    
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启 Spring 扫描-->
    <context:component-scan base-package="com.qf.ran"/>
</beans>
  • Spring-Mybatis.xml Spring整合Mybatis的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!--加载jdbc连接-->
    <context:property-placeholder ignore-unresolvable="true" location="classpath:jdbc.properties"/>

    <!-- 扫描 Mapper -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.qf.ran.dao"/>
    </bean>


    <!-- 配置 SqlSession -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--连接数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!-- 用于配置对应实体类所在的包,多个 package 之间可以用 ',' 号分割 -->
        <!--<property name="typeAliasesPackage" value="cn.qf.spring.mybatis.entity"/>-->
        <!-- 用于配置对象关系映射配置文件所在目录 -->
        <property name="mapperLocations" value="classpath:/mapper/**/*.xml"/>
        <property name="configLocation" value="classpath:/MyBatis-config.xml"></property>
    </bean>


    <!--数据源配置,使用 druid 数据库连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <!-- 基本属性 url、user、password -->
        <property name="url" value="${jdbc.connectionURL}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="${jdbc.pool.init}"/>
        <property name="minIdle" value="${jdbc.pool.minIdle}"/>
        <property name="maxActive" value="${jdbc.pool.maxActive}"/>

        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="60000"/>

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>

        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000"/>

        <property name="validationQuery" value="${jdbc.testSql}"/>
        <property name="testWhileIdle" value="true"/>
        <property name="testOnBorrow" value="false"/>
        <property name="testOnReturn" value="false"/>

        <!-- 配置监控统计拦截的filters -->
        <property name="filters" value="stat"/>
    </bean>
</beans>      
  • 3.druid监控中心 web.xml 进行配置监控 SQL 语句的执行效率以及执行次数
 <servlet>
    <servlet-name>DruidStatView</servlet-name>
    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>DruidStatView</servlet-name>
    <url-pattern>/druid/*</url-pattern>
  </servlet-mapping>

2. 动态SQL

<sql id="">   字段名的抽取,使用<include refid="">
    <if>          判断赋值给字段的参数是否为 null ,不为 null 则进行填充
    <where>       代替 where 关键词,自动省略 where 后面的 or 或者 and
    <foreach>     遍历
    <set>         代替 set 关键词,自动省略","
    <trim>        自定义标签
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 指向需要实现的接口路径-->
<mapper namespace="com.qf.ran.dao.UserMapper">
    <!--id 属性对应方法名-->
    <!--<insert id="addUser">
        insert into user(username,password) values(#{username},#{password});
    </insert>-->
    <!--
        主键返回
        sql 语句执行完后返回生成主键,对象的 id 属性接收 id 值
    -->
    <insert id="addUser" useGeneratedKeys="true" keyProperty="id">
        insert into user(username,password) values(#{username},#{password});
    </insert>

    <!--测试 @Param 修饰对象-->
    <insert id="method">
        insert into user(username,password) values(#{user.username},#{user.password});
    </insert>

    <delete id="deleteUserById">
        delete from user where id = #{id};
    </delete>

    <update id="updateUserById">
        update
          user
        <set>
            <if test="username != null and username != ''">
                username = #{username},
            </if>
            <if test="password != null and password != ''">
                password = #{password},
            </if>
            <if test="sex != null and sex != ''">
                sex = #{sex}
            </if>
        </set>
        where
          id= #{id};
    </update>

    <!--字段抽取封装-->
    <sql id="user_column">
        id,username,password,sex
    </sql>


    <!--
        trim            自定义标签
        prefix          属性值为添加的前缀
        prefixOverrides 每个 if 语句允许添加指定的关键字,根据需求删除关键字
    -->
    <select id="selectUser" resultType="User">
        select
        <include refid="user_column"/>
        from
        user
        <trim prefix="where" prefixOverrides="and|or">
            <if test="id != null and id != ''">
                and id = #{id}
            </if>
            <if test="username != null and username != ''">
                and username = #{username}
            </if>
            <if test="sex != null and sex != ''">
                or sex = #{sex}
            </if>
        </trim>
    </select>

    <!--根据对象的属性进行查询-->
    <!-- <include refid="user_column"/> 导入对应的字段数据  -->
    <!--使用 where 标签会自动删除不需要的 and 或者 or-->
    <!--<select id="selectUser" resultType="User">
        select
          <include refid="user_column"/>
        from
          user
        <where>
          <if test="id != null and id != ''">
              and id = #{id}
          </if>
          <if test="username != null and username != ''">
              and username = #{username}
          </if>
          <if test="sex != null and sex != ''">
               and sex = #{sex}
           </if>
        </where>
    </select>-->

    <!-- resultType 返回值类型 -->
   <!-- <select id="selectUserById" resultType="com.qf.ran.entity.User">
        select id,username,password from user where id = #{id};
    </select>-->

    <select id="getList" resultType="User">
        select
          <include refid="user_column"/>
        from
          user;
    </select>


    <!-- 根据 id 集合查询多个对象信息-->
    <!-- collection 对应方法中的集合参数 -->
    <select id="selectUserListByIds" resultType="User">
        select
        <include refid="user_column"/>
        from
          user
        where
          id
        in
          <foreach collection="list" open="(" separator="," close=")" item="id">
              #{id}
          </foreach>
    </select>
</mapper>

3、其他

  • 更改配置文件需要重新启动项目
  • 下载lombok包需要在File>setting》plugins>搜索lombok插件下载才能正常使用
  • spring --作用于三层 springmvc作用于controller层
  • 与数据库打交道一般用包装类,不用基本数据类型

4、关于学习今日总结

  • 注解
在这里插入代码片

Day58、MyBatis-关联映射

1、级联查询

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 指向需要实现的接口路径-->
<mapper namespace="com.qf.ran.dao.UserMapper">
    <!--id 属性对应方法名-->
    <!--<insert id="addUser">
        insert into user(username,password) values(#{username},#{password});
    </insert>-->
    <!--
        主键返回
        sql 语句执行完后返回生成主键,对象的 id 属性接收 id 值
    -->
    <insert id="addUser" useGeneratedKeys="true" keyProperty="id">
        insert into user(username,password) values(#{username},#{password});
    </insert>

    <!--测试 @Param 修饰对象-->
    <insert id="method">
        insert into user(username,password) values(#{user.username},#{user.password});
    </insert>

    <delete id="deleteUserById">
        delete from user where id = #{id};
    </delete>

    <update id="updateUserById">
        update
          user
        <set>
            <if test="username != null and username != ''">
                username = #{username},
            </if>
            <if test="password != null and password != ''">
                password = #{password},
            </if>
            <if test="sex != null and sex != ''">
                sex = #{sex}
            </if>
        </set>
        where
          id= #{id};
    </update>

    <!--字段抽取封装-->
    <sql id="user_column">
        id,username,password,sex
    </sql>


    <!--
        trim            自定义标签
        prefix          属性值为添加的前缀
        prefixOverrides 每个 if 语句允许添加指定的关键字,根据需求删除关键字
    -->
    <select id="selectUser" resultType="User">
        select
        <include refid="user_column"/>
        from
        user
        <trim prefix="where" prefixOverrides="and|or">
            <if test="id != null and id != ''">
                and id = #{id}
            </if>
            <if test="username != null and username != ''">
                and username = #{username}
            </if>
            <if test="sex != null and sex != ''">
                or sex = #{sex}
            </if>
        </trim>
    </select>

    <!--根据对象的属性进行查询-->
    <!-- <include refid="user_column"/> 导入对应的字段数据  -->
    <!--使用 where 标签会自动删除不需要的 and 或者 or-->
    <!--<select id="selectUser" resultType="User">
        select
          <include refid="user_column"/>
        from
          user
        <where>
          <if test="id != null and id != ''">
              and id = #{id}
          </if>
          <if test="username != null and username != ''">
              and username = #{username}
          </if>
          <if test="sex != null and sex != ''">
               and sex = #{sex}
           </if>
        </where>
    </select>-->

    <!-- resultType 返回值类型 -->
   <!-- <select id="selectUserById" resultType="com.qf.ran.entity.User">
        select id,username,password from user where id = #{id};
    </select>-->

    <select id="getList" resultType="User">
        select
          <include refid="user_column"/>
        from
          user;
    </select>


    <!-- 根据 id 集合查询多个对象信息-->
    <!-- collection 对应方法中的集合参数 -->
    <select id="selectUserListByIds" resultType="User">
        select
        <include refid="user_column"/>
        from
          user
        where
          id
        in
          <foreach collection="list" open="(" separator="," close=")" item="id">
              #{id}
          </foreach>
    </select>
</mapper>

2、缓存:

  • 一级缓存(SqlSession)
    • Spring-Mybatis.xml 添加配置
<!--事务处理器容器-->
            <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                <constructor-arg ref="dataSource"/>
            </bean>

            <!--开启事务注解支持-->
            <tx:annotation-driven transaction-manager="transactionManager"/>
  • 指定方法添加注解@Transactional(readOnly = true)
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    /*开启一级缓存*/
//    /*@Transactional(readOnly = true)*/
    public User selectUser(User user){
        userMapper.selectUser(user);
        userMapper.selectUser(user);
        userMapper.selectUser(user);
        userMapper.selectUser(user);
        userMapper.selectUser(user);
        return null;
    }
}
  • 2、二级缓存(mapper)
    • Mybatis-config.xml 配置中cacheEnabled 设置为true
<!-- 使全局的映射器启用或禁用二级缓存。 -->
        <setting name="cacheEnabled" value="true"/>
      
  • 在指定 XXXMapper.xml 的 mapper 标签里添加
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qf.ran.dao.UserMapper">

    <!-- 开启当前namespace 的二级缓存-->
    <cache/>
  • 实体类进行序想·列化、
    • public class User implements Serializable

3、今日总结

  • 关于注解
@Transactional(readOnly = true)   开启以及缓存
  • 关于maven依赖包

Day59、quartz、Log框架

报错解决

1、idea控制台中文乱码

1.Logback – 日志框架 记录程序运行状态以及错误信息

  • 依赖的包
 <spring.version>5.2.9.RELEASE</spring.version>
<!-- Logback依赖,还会传递 slf4j 和 logback-core -->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>
  </dependencies>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
  
  • 方法:debug(),info(),warn(),error()
 //日志对象
    private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    public User selectUserByUserId(Long id) {
        //开发阶段
        logger.debug("debug:"+id);
        //追踪正常状态信息
        logger.info("info:"+id);
        try{
            if(id == 11L){
                //当系统出现不合理的情况但是不影响程序的运行
                logger.warn("warn:用户id不存在,查询失败");
            }
            if(id == 100L){
                throw new RuntimeException("异常说明:连接数据库失败");
            }
        }catch (RuntimeException e){
            //系统级错误,导致程序无法正常运行
            logger.error("error:"+e.getMessage());
        }
        return null;
    }
  • 配置文件:logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。
	 默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false-->
<configuration scan="true" scanPeriod="60 seconds" debug="true">

    <!-- 定义变量,可通过 ${log.path}和${CONSOLE_LOG_PATTERN} 得到变量值 -->
    <!-- 指定日记保存目录 -->
    <property name="log.path" value="D:/log"/>
    <!-- 日志输出格式规定 -->
    <property name="CONSOLE_LOG_PATTERN"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} |-[%-5p] in %logger.%M[line-%L] -%m%n"/>

    <!-- 输出到控制台 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!-- Threshold=即最低日志级别,此appender输出大于等于对应级别的日志
             (当然还要满足root中定义的最低级别)
        -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <!-- 日志格式(引用变量) -->
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 输出到磁盘的日志文件中 -->
    <appender name="file" class="ch.qos.logback.core.FileAppender">
        <file>${log.path}/logback1.log</file>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>


    <!-- 滚动追加到文件中 -->
    <appender name="file2" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/logback2.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录
             文件超过最大尺寸后,会新建文件,然后新的日志文件中继续写入
             如果日期变更,也会新建文件,然后在新的日志文件中写入当天日志
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 新建文件后,原日志改名为如下  %i=文件序号,从0开始 -->
            <fileNamePattern>${log.path}/logback-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 每个日志文件的最大体量 -->
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>5KB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <append>true</append>
            <!-- 日志文件保留天数,1=则只保留昨天的归档日志文件 ,不设置则保留所有日志-->
            <maxHistory>2</maxHistory>
        </rollingPolicy>
    </appender>

    <!--
        level为日志输出级别:
            trace   -  debug  -   info  -  warn  -  error
    -->
    <root level="debug">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="file2"/>
    </root>
    <!--输出到日志文件-->
    <root level="info">
        <appender-ref ref="file"/>
    </root>

</configuration>
  • 级别:trace debug info warn error

2.Quartz – 定时任务框架

  • 1、Java代码版本

//1.创建调度器
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //2.设定任务规则
        JobDetail jobDetail = JobBuilder.newJob(ClockInJob.class)
                //指定任务的唯一标识
                .withIdentity("clockIn", "clockIn").build();
        //3.设定时间规则
        CronTrigger trigger = TriggerBuilder.newTrigger().withSchedule(
                //秒 分 时 日 月 星期数
                //3 * * * * ?       每分钟的第3秒
                //0/3 * * * * ?     一开始执行任务,每隔3秒再一次执行
                //"3/3 * * * * ?"   3秒后每隔3秒执行一次
                //"0-30 * * * * ?"  0-30秒每一秒执行一次
                //0 0 20 ? * 6      每周周五晚上8点发周报
                //0 0 1 1 * ?       每月第一天凌晨1点
                CronScheduleBuilder.cronSchedule("3/3 * * * * ?"))
                .build();
        //4.通过调度器绑定任务和时间
        scheduler.scheduleJob(jobDetail,trigger);
        //5.开启调度器
        scheduler.start();
        Thread.sleep(10000);


        //删除定时任务
        scheduler.deleteJob(new JobKey("clockIn", "clockIn"));
  • 2、配置文件版本
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.qf.ran"/>

    <!--
        1.定义任务的 bean  ,指定任务规则
    -->
    <bean name="job1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <!-- 指定 job 的名称-->
        <property name="name" value="clockIn"/>
        <!-- 指定 job 的组织 -->
        <property name="group" value="clockIn"/>
        <!--指定具体的 job 类-->
        <property name="jobClass" value="com.qf.ran.job.ClockInJob"/>
    </bean>

    <!--
        2.定义触发器的bean,制定时间规则
    -->
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="name"  value="trigger1"/>
        <property name="group"  value="trigger1"/>
        <!-- 绑定调度任务 -->
        <property name="jobDetail" ref="job1"/>
        <!--指定时间规则,每隔3秒执行一次-->
        <property name="cronExpression" value="*/3 * * * * ?"/>
    </bean>

    <!--
        3.创建调度器,将触发器注册到调度器里
    -->
    <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!--触发器栈-->
        <property name="triggers">
            <list>
                <ref bean="cronTrigger"/>
            </list>
        </property>

        <!-- 添加 quartz 配置,如下两种方式均可 -->
        <!--<property name="configLocation" value="classpath:quartz.properties"></property>-->
        <property name="quartzProperties">
            <value>
                # 指定调度器名称,实际类型为:QuartzScheduler
                org.quartz.scheduler.instanceName = MyScheduler
                # 指定连接池
                org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
                # 连接池线程数量
                org.quartz.threadPool.threadCount = 11
                # 优先级
                org.quartz.threadPool.threadPriority = 5
                # 不持久化job
                org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
            </value>
        </property>
    </bean>

</beans>

Day60、项目周

1、报错总结

  • 1\ java.lang.IllegalStateException: Failed to load ApplicationContext
//集成 swagger2 需要添加注解
@WebAppConfiguration

day61、spring-boot

1、spring-boot概要


1. Spring Boot
2. Shiro
3. 运维篇(了解)  Linux  Docker

## 微服务

#### 微服务组件

Spring Cloud

Spring Cloud Alibaba

Spring Cloud Netflix

#### 第三方常用框架

1. 分布式事务
2. 分布式锁
3. ES
4. Sharding-JDBC
5. Redis
6. 消息中间件
7. Spring Security(选学)
8. Vue(前端)

2、创建Spring Boot项目

## Spring  Boot笔记

### 基础

1. yml

### 数据层

1. Mybatis

2. Mybatis  Plus  ORM 框架的能力

3. JPA (Hibernate)

4. Redis(操作map)

### web

1. Restful

2. 参数校验

3. 全局异常处理

4. 文件上传

## 为什么要学习Spirng  Boot

1. 导包 
2. 内置web容器(tomcat)
3. 整合配置文件
4. 内置监控

## 什么是Spring Boot

> spring boot 简化了 spring 的开发难度,配置信息,提供了各种启动器(starter),是新一代的web开发标准, 并且spring cloud的基础

## 创建Spring Boot项目

### 概要

1. Spring Boot 初始化器

2. 手动创建(重点掌握)


### Maven多继承与多模块

如果想pom.xml文件被继承(父pom文件)

继承

1. `<packaging>pom</packaging>`

```xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.10</version>
        <relativePath/>
    </parent>
    
    <packaging>pom</packaging>
    
    <groupId>com.smart</groupId>
    <artifactId>spring-boot-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-example</name>
    
</project>

子pom文件

  • parent标签
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.smart</groupId>
        <artifactId>spring-boot-example</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        指向pom包,一定要改过来,不然影响后续的打包
        <relativePath>../pom.xml</relativePath>
    </parent>
</project>

补充知识点

<!--   传统的 jar  只能打包java文件 不能打包资源文件 --><!--    ssm  项目   war--><!--    spring boot 项目 jar --><!--    如果想被继承   pom 注意 如果是可运行的项目 不能使用pom -->


常见的继承标签(可以继承的都可以删除)

  1. groupId

  2. version

  3. properties(包括子标签)

  4. 依赖继承

    1. 可选依赖 dependencyManagement
    2. 直接依赖 dependencies

    build标签是不能够被继承的

    <description>spring-boot-project</description>项目说明标签,可要可不要
    

多模块

  1. 在父pom文件中

    <project>
        <modules>
            <module>spring-boot-base</module>
        </modules>
    </project>
    

    备注:

    1. 不要跨级添加模块

    多模块的好处

    1. ​ 只需要打包一个工程既可打包所有
    2. 后期可配合开发环境,统一版本号

    配置文件配置流程

    1. 把相同配置删除了,是否是继承项目

3、自定义属性

  1. @Value()
  2. @ConfigurationProperties

单值读取

语法
  1. ${属性名}
  2. #{属性名或者EL表达式}
@Data
public class User {
    @Value("${user.username}")
    private String username;
    @Value("${user.password}")
    private String password;
}

配置文件
user:
  username: admin
  password: password
Java config注册
@Configuration
public class UserConfig {

    @Bean
    public User user() {
        User user = new User();
        return user;
    }
}
测试代码
@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    User user;

    @GetMapping("/test")
    public String test() {
        return user.getUsername();
    }
    
}    

批量读取

语法格式
@ConfigurationProperties(prefix = "" ,value="")
说明
属性说明
prefix等价于value配置文件属性前缀
依赖
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-configuration-processor</artifactId>
  <optional>true</optional>
</dependency>
@Data
@Component
@ConfigurationProperties(prefix = "user.properties")
public class UserProperties {
    private String username;
    private String password;
}
配置文件
user:
  properties:
    username: admin
    password: password
测试代码
@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    UserProperties userProperties;

    @GetMapping("/test2")
    public String test2() {
        return userProperties.getUsername();
    }
}

总结

说明批量读取 @ConfigurationProperties单值读取 @Value
松散语法在yml格式的配置文件中能使用 properties不支持不支持
JSR303数据校验支持不支持
复杂数据类型支持不支持
SpEL不支持支持

补充

配置文件的加载顺序

  1. classpath
  2. config
  3. file

file > classpath config > classpath

在同级目录下

yml或者yaml优先加载 如果出现相同的属性则会被Properties中的配置所覆盖

4、 概要与ymal语法

spring boot 支持两种配置文件格式

  • properties
  • yml 或者 yaml

约定优于配置

配置文件的名称必须是application开头

5、多环境配置

  1. 生产环境
  2. 开发环境
  3. 测试环境

如果各种环境配置信息没有区别的,配置在主配置文件中

application.yml

server:
  # 修改应用程序端口
  port: 8888
  servlet:
    # 修改应用程序的前缀
    context-path: "/api/v1"
# 引入多环境配置文件
spring:
  profiles:
    active: "dev,db"

application-dev.yml

server:
  port: 8881

logging:
  level: debug

application-db.yml


通过外面命令指定(了解)

java -jar app.jar --spring.profiles.active=dev

外部执行jar工程包

java -jar app.jar

day62、文件上传和日期型文件

前期准备工作

使用

导入依赖

<dependency>
  <groupId>com.aliyun.oss</groupId>
  <artifactId>aliyun-sdk-oss</artifactId>
  <version>3.10.2</version>
</dependency>

配制

配置文件

aliyun:
  oss:
    endpoint: " https://oss-cn-guangzhou.aliyuncs.com"
    access-key-id: "LTAI5tLzBaVSAe65vuho4o3n"
    access-key-secret: "K4jFCGp8evfF7gJb3gkjkUhNrScNHc"
    bucket-name: "smart-2109"

配置属性类

@ConfigurationProperties("aliyun.oss")
@Component
public class OSSConfigProperties {
  //  https://oss-cn-guangzhou.aliyuncs.com
  private String endpoint;
  private String accessKeyId;
  private String accessKeySecret;
  // smart-2109
  private String bucketName;
}

配置类

@Configuration
public class AliyunOSSConfig {
  @Resource
  private OSSConfigProperties properties;
  /**
     * OSS对象注入到容器
     *
     * @return
     */
  @Bean
  public OSS oss() {
    return new OSSClientBuilder()
      .build(properties.getEndpoint(), properties.getAccessKeyId(), properties.getAccessKeySecret());
  }
}

业务层

  1. MultipartFile

    1. 文件的后缀名

    2. 上传文件的流

  2. oss.putObject方法

    1. bucketName
    2. key 文件上传的相对路径+文件名
    3. input 客服端上传文件的流
  3. 获取图片的显示路径

    @Resource
    OSS oss;
    @Resource
    OSSConfigProperties properties;
    // 图片的重名前缀
    public static final String IMG_PREFIX_FILE = "IMG_";
    
    	// 云服务器存储的图片的根目录
     public static final String BUCKET_NAME_IMAGE = "images";
      
    @Override
    public String uploadImage(MultipartFile multipartFile) {
        /**
         *  2 images/21111/xxx.png
         *   获取文件的原始名称
         */
        String originalFilename = multipartFile.getOriginalFilename();
        // 对图片进行重命名
        String newFileName = getNewFileName(originalFilename);
        // 
        String key = BUCKET_NAME_IMAGE + File.separator + DateUtil.format(new Date(), "yyyy-MM-dd") + File.separator + newFileName;
        try {
           //  1  上传到阿里云OSS服务器
            PutObjectResult putObjectResult = oss.putObject(properties.getBucketName(), key, multipartFile.getInputStream());
        } catch (IOException e) {
            throw new ServiceException(ResultCode.FILE_UPLOAD_ERROR);
        }
        return null;
    }
       /**
     * 对图片进行重命名
     *
     * @param originalFilename
     * @return
     */
    private static String getNewFileName(String originalFilename) {
        /**
         * 自定义命名规则 + 文件的后缀名
         * IMG_2022031415331234.png
         * xxxx.png
         */
        // 获取文件的后缀名
        String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
        return String.format("%s%s%s%s", IMG_PREFIX_FILE, DateUtil.format(new DateTime(), DATE_FORMAT), RandomUtil.randomNumbers(4), suffixName);
    }

获取图片的访问地址

private String getUrl(String bucketName, String key) {
  Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
  String url = oss.generatePresignedUrl(bucketName, key, expiration).toString();
  return url;
}

完整代码

@Service
public class UploadServiceImpl implements UploadService {
    public static final String IMG_PREFIX_FILE = "IMG_";
    public static final String DATE_FORMAT = "yyyyMMddHHmmss";
    public static final String BUCKET_NAME_IMAGE = "images";
    @Resource
    private OSS oss;
    @Resource
    private OSSConfigProperties properties;

    /**
     * 图片覆盖
     * /1/20210314/xxx.png
     * 36655/按着日期对文件归类 // 可以防止图片覆盖
     * // 对图片重命名
     *
     * @return
     */
    @Override
    public String uploadImage(MultipartFile multipartFile) {
        /**
         * 获取文件的原始名称
         */
        // 判断文件的格式
        String originalFilename = multipartFile.getOriginalFilename();
        // 判断文件是否是上传格式
        String newFileName = getNewFileName(originalFilename);
        String key = BUCKET_NAME_IMAGE + File.separator + DateUtil.format(new Date(), "yyyy-MM-dd") + File.separator + newFileName;
        try {
            PutObjectResult putObjectResult = oss.putObject(properties.getBucketName(), key, multipartFile.getInputStream());
            if (!ObjectUtil.isEmpty(putObjectResult.getETag())) {
                // 表示上传成功
                return getUrl(properties.getBucketName(), key);
            } else {
                throw new ServiceException(ResultCode.FILE_UPLOAD_ERROR);
            }
        } catch (IOException e) {
            throw new ServiceException(ResultCode.FILE_UPLOAD_ERROR);
        }
    }

    /**
     * 对图片进行重命名
     *
     * @param originalFilename
     * @return
     */
    private static String getNewFileName(String originalFilename) {
        /**
         * 自定义命名规则 + 文件的后缀名
         * IMG_2022031415331234.png
         * xxxx.png
         */

        // 获取文件的后缀名
        String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
        return String.format("%s%s%s%s", IMG_PREFIX_FILE, DateUtil.format(new DateTime(), DATE_FORMAT), RandomUtil.randomNumbers(4), suffixName);
    }

    private String getUrl(String bucketName, String key) {
        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
        String url = oss.generatePresignedUrl(bucketName, key, expiration).toString();
        return url;
    }

}

配置信息

spring:
  servlet:
    multipart:
      enabled: true
      #      location: "upload/static/image"
      # 单个上传的文件最大值
      max-file-size: 10MB
      #  一起请求上传文件的最大值
      max-request-size: 100MB

控制层

    /**
     * 文件上传
     * 1. 上传的本地的服务器
     * 2. 上传到云对象存储  OSS
     * 3  FastDFS  (技术要求高)
     * @return
     */
    @PostMapping("/upload/img")
    public ResponseResult<String> uploadImage(@RequestBody MultipartFile multipartFile) {
        String url = uploadService.uploadImage(multipartFile);
        return ResponseResult.success(url);
    }

测试接口

课外延展:

​ @Configuration注解的更具体用法

@Configuration

SQL

CREATE TABLE banner
(
    banner_id   int AUTO_INCREMENT COMMENT '主键' PRIMARY KEY,
    name        varchar(10)                           NOT NULL COMMENT '名称',
    description varchar(64) DEFAULT ''                NOT NULL COMMENT '描述',
    img         varchar(255)                          NOT NULL COMMENT '轮播图的路径',
    link_status int         DEFAULT 1                 NOT NULL COMMENT '1 表示启用  0 表示禁用',
    link        int         DEFAULT 1                 NOT NULL COMMENT '1 表示全部店铺,  2 表示指定店铺',
    link_jump   int         DEFAULT 0                 NOT NULL COMMENT '0 表示不跳转商品信息 1  表示跳转商品链接',
    product_id  bigint      DEFAULT -1                NOT NULL COMMENT '跳转的商品ID',
    type        int                                   NULL COMMENT '1 表示pc端  2 表示 移动端',
    create_date datetime    DEFAULT CURRENT_TIMESTAMP NULL COMMENT '表示创建时间',
    is_del      int         DEFAULT 0                 NOT NULL COMMENT '0 不删除  1 表示删除',
    CONSTRAINT name UNIQUE (name)   
);

控制层

@PostMapping("/add")
public ResponseResult<Integer> add(@Validated(BannerRequestParams.Add.class) @RequestBody BannerRequestParams banner) {
  int count = bannerService.add(banner);
  return ResponseResult.success(count);
}

请求参数

  1. @DateTimeFormat(pattern = “yyyy-MM-dd HH:mm:ss”)
  2. 接受客服端日期格式格式, 客服端传递过来的是字符串
/**
 * @author zhangwei
 */
@Data
@Validated
public class BannerRequestParams {


    public interface Add {

    }

    public interface Update {

    }

    /**
     * 主键
     */
    @NotNull(groups = Update.class)
    private Integer bannerId;

    /**
     * 名称
     */
    @Length(min = 1, max = 10, message = "最多10个字")
    private String name;

    /**
     * 描述
     */

    private String description;

    /**
     * 轮播图的路径
     */
    @NotNull
    private String img;

    /**
     * 1 表示启用  0 表示禁用
     */
    private Integer linkStatus;

    /**
     * 1 表示全部店铺,  2 表示指定店铺
     */
    private Integer link;

    /**
     * 0 表示不跳转商品信息 1  表示跳转商品链接
     */
    private Integer linkJump;

    /**
     * 跳转的商品ID
     */
    private Long productId;

    /**
     * 1 表示pc端  2 表示 移动端
     */
    private Integer type;
    //上传时使用
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createDate;


}

业务层

  1. 请求参数对象(QO)转化持久化对象(PO)
/**
 * @author zhangwei
 */
@Service
public class BannerServiceImpl implements BannerService {
    @Resource
    private BannerMapper bannerMapper;

    @Override
    public int add(BannerRequestParams banner) {
        Banner bannerEntity = new Banner();
        /**
         * 第一个参数有值  第二个没值
         */
        BeanUtils.copyProperties(banner, bannerEntity);
        int count = bannerMapper.insert(bannerEntity);
        if (count > 0) {
            return count;
        } else {
            throw new ServiceException(ResultCode.ERROR);
        }
    }
}

数据层

public interface BannerMapper extends BaseMapper<Banner> {
}
@Data
@TableName(value = "banner")
public class Banner {
    /**
     * 主键
     */
    @TableId(value = "banner_id", type = IdType.INPUT)
    private Integer bannerId;

    /**
     * 名称
     */
    @TableField(value = "`name`")
    private String name;

    /**
     * 描述
     */
    @TableField(value = "description")
    private String description;

    /**
     * 轮播图的路径
     */
    @TableField(value = "img")
    private String img;

    /**
     * 1 表示启用  0 表示禁用
     */
    @TableField(value = "link_status")
    private Integer linkStatus;

    /**
     * 1 表示全部店铺,  2 表示指定店铺
     */
    @TableField(value = "link")
    private Integer link;

    /**
     * 0 表示不跳转商品信息 1  表示跳转商品链接
     */
    @TableField(value = "link_jump")
    private Integer linkJump;

    /**
     * 跳转的商品ID
     */
    @TableField(value = "product_id")
    private Long productId;

    /**
     * 1 表示pc端  2 表示 移动端
     */
    @TableField(value = "`type`")
    private Integer type;

    /**
     * 表示创建时间
     */
    @TableField(value = "create_date")
    private Date createDate;

    /**
     * 0 不删除  1 表示删除
     */
    @TableField(value = "is_del")
    private Integer isDel;

    public static final String COL_BANNER_ID = "banner_id";

    public static final String COL_NAME = "name";

    public static final String COL_DESCRIPTION = "description";

    public static final String COL_IMG = "img";

    public static final String COL_LINK_STATUS = "link_status";

    public static final String COL_LINK = "link";

    public static final String COL_LINK_JUMP = "link_jump";

    public static final String COL_PRODUCT_ID = "product_id";

    public static final String COL_TYPE = "type";

    public static final String COL_CREATE_DATE = "create_date";

    public static final String COL_IS_DEL = "is_del";
}

VO对象

  • @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”)
@Data
public class BannerVo {

    /**
     * 主键
     */
    private Integer bannerId;
    /**
     * 名称
     */
    private String name;
    /**
     * 描述
     */
    private String description;
    /**
     * 轮播图的路径
     */
    private String img;
    /**
     * 1 表示启用  0 表示禁用
     */
    private Integer linkStatus;
    /**
     * 1 表示全部店铺,  2 表示指定店铺
     */
    private Integer link;
    /**
     * 0 表示不跳转商品信息 1  表示跳转商品链接
     */
    private Integer linkJump;
    /**
     * 跳转的商品ID
     */
    private Long productId;
    /**
     * 1 表示pc端  2 表示 移动端
     */
    private Integer type;
    //json数据序列化指定日期格式
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createDate;
}

配置文件中

spring:
  # 配置json数据统一的日志解析格式
  jackson:
    date-format: "yyyy-MM-dd HH:mm:ss"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值