SpringBoot学习笔记

***SpringBoot实现国际化切换***

    1. 编写国际化配置文件,抽取页面需要显示的国际化消息;
      注意文件位置,以及配置文件的命名:使用页面_语言代码_国家代码.properties

       

    2. SpringBoot自动配置好了管理国际化资源文件的组件;
      我们的配置文件可以直接放在类路径下叫messages.properties;

      但这里我们不是按照它的来弄的,使用要去全局配置文件里修改

      #国际化资源文件的配置
      spring:
        messages:
          basename: i18n.login

       

    3. 去页面获取国际化的值
      名称与配置文件里的一致即可,注意: thymeleaf获取国际化值的表达式是:#{}
      <!--引入thymeleaf模板引擎表达式-->
      <html lang="en" xmlns:th="http://www.thymeleaf.org">
      th:text="#{pleaseSignIn}"
      ....
       
    4. *点击链接实现国家化

      thymeleaf发送请求是用@{},参数用()

              第一步:

      public class MyLocalResolver implements LocaleResolver {
      
          /** * 切换语言第一步 */ @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String l = httpServletRequest.getParameter("l"); Locale locale = Locale.getDefault(); // 如果请求参数没有语言区域信息,我们就用SpringBoot默认的 if (!StringUtils.isEmpty(l)) { String[] split = l.split("_");
      locale = new Locale(split[0], split[1]);
      } return locale; } @Override public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { } }

              第二步:

      @Configuration
      public class MyMvcConfig extends WebMvcConfigurerAdapter {
          /** * 切换语言第二步 */ @Bean public LocaleResolver localeResolver() { return new MyLocalResolver(); } }

       

    5. 如果页面乱码,是idea的编码问题哦

       

SpringBoot整合日志框架

市面上的日志框架:
JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....

SpringBoot:底层是Spring框架,Spring框架默认是用JCL;‘
SpringBoot选用 SLF4j和logback;

日志门面 (日志的抽象层)日志实现
JCL(Jakarta Commons Logging)
Facade for Java)

SLF4j(Simple Logging
jboss-logging
Log4j JUL(java.util.logging)
Log4j2 Logback
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(HelloWorld.class); logger.info("Hello World");  } }
  • 配置

    #日志配置
    logging:
      level:
        com.soldier: trace
      #spring.profiles.active=dev
    application.yml
    ### set log levels ###
    log4j.rootLogger = debug ,  stdout ,  D ,  E
    
    ### 输出到控制台 ###
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target = System.out
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
    
    #### 输出到日志文件 ###
    #log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    #log4j.appender.D.File = /home/soldier/SOLDIER/idea_project/logs/LearningNotes/log.log
    #log4j.appender.D.Append = true
    #log4j.appender.D.Threshold = DEBUG ## 输出DEBUG级别以上的日志
    #log4j.appender.D.layout = org.apache.log4j.PatternLayout
    #log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    
    #### 保存异常信息到单独文件 ###
    #log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    #log4j.appender.D.File = /home/soldier/SOLDIER/idea_project/logs/LearningNotes/error.log ## 异常日志文件名
    #log4j.appender.D.Append = true
    #log4j.appender.D.Threshold = ERROR ## 只输出ERROR级别以上的日志!!!
    #log4j.appender.D.layout = org.apache.log4j.PatternLayout
    #log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    log4j.properties
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
    scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
    scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
    debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
    -->
    <configuration scan="false" scanPeriod="60 seconds" debug="false">
        <!-- 定义日志的根目录 -->
        <property name="LOG_HOME" value="/home/soldier/SOLDIER/idea_project/logs/LearningNotes" />
        <!-- 定义日志文件名称 -->
        <property name="appName" value="spring_boot"></property>
        <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
        <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
            <!--
            日志输出格式:
                %d表示日期时间,
                %thread表示线程名,
                %-5level:级别从左显示5个字符宽度
                %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
                %msg:日志消息,
                %n是换行符
            -->
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            </layout>
        </appender>
    
        <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
        <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 指定日志文件的名称 -->
            <file>${LOG_HOME}/${appName}.log</file>
            <!--
            当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
            TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
            -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!--
                滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 
                %i:当文件大小超过maxFileSize时,按照i进行文件滚动
                -->
                <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
                <!-- 
                可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
                且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
                那些为了归档而创建的目录也会被删除。
                -->
                <MaxHistory>365</MaxHistory>
                <!-- 
                当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
                -->
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <!-- 日志输出格式: -->     
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
            </layout>
        </appender>
    
        <!-- 
            logger主要用于存放日志对象,也可以定义日志类型、级别
            name:表示匹配的logger类型前缀,也就是包的前半部分
            level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
            additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,
            false:表示只用当前logger的appender-ref,true:
            表示当前logger的appender-ref和rootLogger的appender-ref都有效
        -->
        <!-- hibernate logger -->
        <logger name="com.soldier" level="debug" />
        <!-- Spring framework logger -->
        <logger name="org.springframework" level="debug" additivity="false"></logger>
    
    
    
        <!-- 
        root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
        要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。 
        -->
        <root level="info">
            <appender-ref ref="stdout" />
            <appender-ref ref="appLogAppender" />
        </root>
    </configuration> 
    logback-spring.xml
    logback.xml:直接就被日志框架识别了;
    logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能

     

***SpringBoot注册登陆拦截器***

  1. 在component包下创建HandlerInterceptor子类
    public class LoginHandlerInterceptor implements HandlerInterceptor {
    //    目标方法执行之前
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            Object user = request.getSession().getAttribute("loginUser");
            if (user == null) {
    //            未登陆,返回登陆页
                request.setAttribute("msg", "没有权限,请先登陆");
                request.getRequestDispatcher("/index").forward(request,response);
                return false;
    
            } else {
    //            已登陆
                return true;
            }
        }
    }

     

  2. 使用WebMvcConfigurerAdapter可以扩展SpringMvc的功能,注册我们写的拦截,【注意:SpringBoot 2.X之后也会拦截静态资源】
    @Configuration
    public class MyMvcConfig extends WebMvcConfigurerAdapter {
        @Bean
        public WebMvcConfigurer webMvcConfigurer() {
            WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
    
    //          登陆拦截器:第二步:注册拦截器
                @Override
                public void addInterceptors(InterceptorRegistry registry) {
    //                静态资源SpringBoot已经做好了映射,所以不用配置;但2.x以后会被拦截
                    registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
    //                                      不拦截访问登陆页面和登陆检验的请求,及静态资源
                                            .excludePathPatterns("/","/index","/userLogin","/static/**","/webjars/**");
                }
            };
            return adapter;
        }
    }

     

***SpringBoot对请求参数的绑定***

  • 使用占位符来获取请求参数
    @GetMapping("/getDept/{id}")
    public Department getDepartment(@PathVariable("id") Integer id) {
         return departmentMapper.getDeptById(id);
    }

     

  • 请求参数与入参对象属性的一一绑定

    要求:请求参数的名称和JavaBean入参的对象的属性名一样的

    //    添加员工
    //    SpringMvc自动将请求参数和入参对象的属性进行封装
        @PostMapping("/addEmp")
        public String addEmp(Employee employee) {
    
            employeeDao.save(employee);
    //        来到员工列表页面
    //        redirect:重定向
    //        forward:转发
            return "redirect:/ems";
        }

     

SpringBoot定制错误页面(类似于web.xml的)--浏览器访问时

  1. *有模板引擎的情况下,静态资源文件夹/templates/error/状态码.html;
    我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html);
    页面能获取的信息;
    timestamp:时间戳
    status:状态码
    error:错误提示
    exception:异常对象
    message:异常消息
    errors:JSR303数据校验的错误都在这里



  2. 没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找;
  3. 以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;

SpringBoot定制错误的json数据--其他客户端(如:postman)访问时

  1. 浏览器和客户端返回的都是json数据,没有自适应效果
    @ControllerAdvice
    public class MyExceptionHandler {
    //    浏览器和客户端返回的都是json数据;UserNotExisitException是自己写的RuntimeException子类
        @ResponseBody
        @ExceptionHandler(UserNotExisitException.class)
        public Map<String, Object> handlerException(Exception e) {
            Map<String, Object> map = new HashMap<>();
            map.put("code", "用户消息不存在");
            map.put("gogo", "is me");
            return map;
        }
    }

     

  2. 转发到/error进行自适应响应效果处理
    public String handlerException(Exception e, HttpServletRequest request) {
            Map<String, Object> map = new HashMap<>();
            //传入我们自己的状态码 4xx 5xx
            request.setAttribute("javax.servlet.error.status_code", 400);
            map.put("code", "用户消息不存在");
            map.put("gogo", "is me");
    //        转发到/error
            return "forward:/error";
        }

     

  3. 将我们的定制数据携带出去
    出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法)
    a、完全来编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中;  --太复杂
    b、页面上能用的数据,或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes得到的,
         而容器默认使用DefaultErrorAttributes.getErrorAttributes()进行数据处理的,
    所以我们可以继承DefaultErrorAttributes来重写getErrorAttributes方法,实现自定义数据
    @Component
    public class MyErrorAttributes extends DefaultErrorAttributes {
        
        @Override
        public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
            Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
            map.put("made", "定制错误数据");
            return map;
        }
    }

     

***SpringBoot对数据库的访问***

  1. 全局配置文件
    #配置数据库
    spring:
      datasource:
        username: root
        password: 123456
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/??

     

  2. *自动配置
    参考DataSourceConfiguration,根据配置创建数据源,默认使用Tomcat连接池;可以使用spring.datasource.type指定自定义的数据源类型
           SpringBoot默认可以支持:org.apache.tomcat.jdbc.pool.DataSource 、HikariDataSource 、BasicDataSource
    默认运行的建表语句:只需要将文件命名为【schema‐*.sql】
    默认插入数据的建表语句:只需要将文件命名为【data‐*.sql】
    还可以在yaml文件中指定,如下图:

                                        

     

     

***SpringBoot整合Druid数据源***

  1. pom.xml
           <!-- 引入自定义数据源 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.16</version>
            </dependency>
            <!-- log4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>

     

  2. application.yaml
    spring:
      #配置数据库
      datasource:
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/LearningNotes
        #spring某个版本之后需要加上这句,否则不会自动执行sql文件
        initialization-mode: always
        #设置自动运行的建表sql文件
        schema:
          - classpath:/sql/department.sql
          - classpath:/sql/employee.sql
        #设置自动运行的数据sql文件
    #    data:
    #      - xxx.sql
    
        #引入自定义数据源
        type: com.alibaba.druid.pool.DruidDataSource
        #Druid数据源配置
        initialSize: 5
        minIdle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        filters: stat,wall,log4j
        maxPoolPreparedStatementPerConnectionSize: 20
        useGlobalDataSourceStat: true
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

     

  3. DruidConfig.class
    @Configuration
    public class DruidConfig {
    
        /**
         * 把我们在配置文件的配置写入springBoot
         */
        @ConfigurationProperties(prefix = "spring.datasource")
        @Bean
        public DataSource druid() {
            return new DruidDataSource();
        }
    
        /**
         * 配置Druid的监控
         */
        //1、配置一个管理后台的Servlet
        @Bean
        public ServletRegistrationBean statViewServlet() {
            //处理/druid下的所有请求
            ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
    
            //配置一些初始化参数
            Map<String, String> initParams = new HashMap<>();
            initParams.put("loginUsername","admin");
            initParams.put("loginPassword","123456");
            initParams.put("allow","");//允许谁登录,为空或不写默认允许所有
    //        initParams.put("deny","localhost");//拒绝谁访问
            bean.setInitParameters(initParams);
    
            return bean;
        }
    
        //2、配置一个监控了的filter
        @Bean
        public FilterRegistrationBean webStatFilter() {
            FilterRegistrationBean bean = new FilterRegistrationBean();
            bean.setFilter(new WebStatFilter());
    
            //配置一些初始化参数
            Map<String, String> initParams = new HashMap<>();
            initParams.put("exclusions","*.js,*.css,/druid/*");//不拦截哪些请求
            bean.setInitParameters(initParams);
    
            //拦截哪些请求
            bean.setUrlPatterns(Arrays.asList("/*"));
            return bean;
        }
    
    }
    DruidConfig

     

***SpringBoot在Druid数据源下整合MaBatis持久层***

  1. 配置Druid数据源,上一个标题
  2. 注解版操作数据库(最简单)
    @Mapper
    public interface DepartmentMapper {
    
        //声明是否使用自动递增主键,主键名是什么
        @Options(useGeneratedKeys = true, keyProperty = "id")
        @Insert("insert into department(departmentName) values(#{departmentName})")
        public int insertDept(Department department);
    
        @Delete("delete from department where id=#{id}")
        public int deleteDeptById(Integer id);
    
        @Update("update set departmentName=#{departmentName} from department where id=#{id}")
        public int updateDept(Department department);
    
        @Select("select * from department where id=#{id}")
        public Department getDeptById(Integer id);
    }
    一、DepartmentMapper
    @RestController
    public class DepartmentController {
    
        @Autowired
        DepartmentMapper departmentMapper;
    
        @GetMapping("/getDept/{id}")
        public Department getDepartment(@PathVariable("id") Integer id) {
            return departmentMapper.getDeptById(id);
        }
    
        @GetMapping("/dept")
        public Department insertDept(Department department) {
            departmentMapper.insertDept(department);
            return department;
        }
    }
    二、DepartmentController


    【但实体类属性名与字段名必须一致,否则查询时无法绑定上指】-如驼峰命名法时,解决办法:

    @Configuration
    public class MyBatisConfig {//MyBatis的自定义规则
        
        //实现驼峰命名法
        @Bean
        public ConfigurationCustomizer configurationCustomizer() {
            return new ConfigurationCustomizer() {
                @Override
                public void customize(org.apache.ibatis.session.Configuration configuration) {
                    configuration.setMapUnderscoreToCamelCase(true);
                }
            };
        }
    }
    三、MyBatisConfig

     

  3. 配置版操作数据库
    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>
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC"/>
          <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          </dataSource>
        </environment>
      </environments>
      <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      </mappers>
    </configuration>
    mybatis全局配置文件
    <?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="org.mybatis.example.BlogMapper">
      <select id="selectBlog" resultType="Blog">
        select * from Blog where id = #{id}
      </select>
    </mapper>
    实体类映射文件示例
    public interface EmployeeMapper {
    
        public int insertEmp(Employee employee);
    
        public int deleteEmpById(Integer id);
    
        public int updateEmp(Employee employee);
    
        public Employee getEmpById(Integer id);
    }
    步骤1:EmployeeMapper
    <?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.soldier.mapper.EmployeeMapper">
    
        <!--id名对应mapper类的方法名,resultType对应实体类全路径-->
        <select id="getEmpById" resultType="com.soldier.bean.Employee">
          select * from employee where id = #{id}
        </select>
        <!--resultType:返回结果类型 parameterType:参数类型 -->
        <insert id="insertEmp" parameterType="int" useGeneratedKeys="true" keyProperty="id">
          insert into employee(lastName,email,gender,d_Id) VALUES (#{lastName},#{email},#{gender},#{dId})
        </insert>
    
        <delete id="deleteEmpById">
          delete from employee where id = #{id}
        </delete>
    
        <update id="updateEmp">
          update set lastName=#{lastName},email=#{email},gender=#{gender},d_Id=#{dId}, from employee where id=#{id}
        </update>
    
    
    </mapper>
    步骤2--实体类映射文件:EmployeeMapper.xml
    <?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>
        <!--<environments default="development">-->
            <!--<environment id="development">-->
                <!--<transactionManager type="JDBC"/>-->
                <!--<dataSource type="POOLED">-->
                    <!--<property name="driver" value="${driver}"/>-->
                    <!--<property name="url" value="${url}"/>-->
                    <!--<property name="username" value="${username}"/>-->
                    <!--<property name="password" value="${password}"/>-->
                <!--</dataSource>-->
            <!--</environment>-->
        <!--</environments>-->
        <!--配置驼峰命名法-->
        <settings>
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        </settings>
        <!--<mappers>-->
            <!--<mapper resource="org/mybatis/example/BlogMapper.xml"/>-->
        <!--</mappers>-->
    </configuration>
    步骤3--全局配置文件:mybatis-config.xml
    #配置mybatis
    mybatis:
      #全局mybatis配置文件路径
      config-location: classpath:/mybatis/mybatis-config.xml
      #所有映射文件路径
      mapper-locations: classpath:/mybatis/mapper/*.xml
    步骤4:application.yml
    //这一句是关键
    @MapperScan("com.soldier.mapper")
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
    }
    步骤5:Application.class

    springboot启动类中@MapperScan注解和全局配置yml文件中mybatis.mapper-locations 两者缺一不可

***SpringBoot整合JPA***

新建springboot项目选中web、JPA、Mysql、JDBC,底层使用hibernate

  1. 编写一个实体类(bean)和数据表进行映射,并且配置好映射关系
    //使用JPA注解配置映射关系
    @Entity  //告诉JPA这是一个实体类(和数据表的类)
    @Table(name = "tbl_user")  //@Table来指定和哪个数据表对应;如果省略默认表名就是实体类名小写
    public class User {
    
        @Id //这是一个主键
        @GeneratedValue(strategy = GenerationType.IDENTITY)  //自增主键
        private Integer id;
    
        @Column(name = "last_name", length = 50)  //这是和数据表对应的一个列
        private String lastName;
    
        @Column  //省略默认列名就是属性名,长度255
        private String email;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    User

     

  2. 编写一个Dao接口来操作实体类对应的数据表(Repository)
    //继承JpaRepository来完成对数据库的操作
    public interface UserRepository extends JpaRepository<User, Integer> {
        //父类JpaRepository泛型使用实体类加上主键类型
    }

     

  3. 基本的配置JpaProperties
    spring:
      #配置数据库
      datasource:
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/LearningNotes
    
      jpa:
        hibernate:
          #更新或创建数据表结构
          ddl-auto: update
        #显示sql语句
        show-sql: true

     

  4. 测试
    @RestController
    public class UserController {
    
        @Autowired
        UserRepository userRepository;
    
        @GetMapping("/user/{id}")
        public User getUser(@PathVariable("id") Integer id) {
            User user = userRepository.findById(id).get();
            return user;
        }
    
        @GetMapping("/addUser")
        public User insertUser(User user) {
            User save = userRepository.save(user);
            return save;
    
        }
    }
    View Code

     

     

 

 

thymeleaf公共页面元素抽取

1、抽取公共片段
 <div th:fragment="copy">
&copy; 2011 The Good Thymes Virtual Grocery
</div>

2、引入公共片段
<div th:insert="~{footer :: copy}"></div>
~{templatename::selector}:模板名::选择器
~{templatename::fragmentname}:模板名::片段名

3、默认效果:
insert的公共片段在div标签中
如果使用th:insert等属性进行引入,可以不用写~{}:
行内写法可以加上:[[~{}]];[(~{})];

    三种引入公共片段的th属性:
      th:insert:将公共片段整个插入到声明引入的元素中
      th:replace:将声明引入的元素替换为公共片段
      th:include:将被引入的片段的内容包含进这个标签中

 

SpringBoot的相关依赖

<parent>
    <groupId>org.springframework.boot</groupId> <artifactId>spring‐boot‐starter‐parent</artifactId> <version>2.1.5.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring‐boot‐starter‐web</artifactId> </dependency> </dependencies> 
  • parent:Spring Boot的版本仲裁中心;以后我们导入依赖默认是不需要写版本;(没有在dependencies里面管理的依赖自然需要声明版本号)
  • spring‐boot‐starter:spring-boot场景启动器;帮我们导入了web模块正常运行所依赖的组件;

SpringBoot的部署

  • 在pom文件中加入一个依赖,可以将应用打包成一个可执行的jar包
    <build>
        <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
  • IDEA左边的【Maven】-【项目名】-【Lifecycle】-【package】即可自动生成一个jar包
  • 运行jar包:切换到jar包所在目录下
    java -jar 项目名.jar

     

SpringBoot对静态资源的映射规则(SpringBoot 2.X后自定义拦截器时会拦截静态资源)

  1. 所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源;
    webjars:以jar包的方式引入静态资源;
    http://www.webjars.org/
    localhost:8080/webjars/jquery/3.3.1/jquery.js1
    
    <!‐‐引入jquery‐webjar‐‐>在访问的时候只需要写webjars下面资源的名称即可
    <dependency>
      <groupId>org.webjars</groupId><artifactId>jquery</artifactId><version>3.3.1</version>
    </dependency>

            

  2. "/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射
    1 "classpath:/META‐INF/resources/",
    2 "classpath:/resources/",
    3 "classpath:/static/",
    4 "classpath:/public/"
    5 "/":当前项目的根路径
    localhost:8080/abc === 去静态资源文件夹里面找abc

     

  3. 欢迎页; 静态资源文件夹下的所有index.html页面;被"/**"映射;
    localhost:8080/ 找index页面

     

  4. 所有的 **/favicon.ico 都是在静态资源文件下找;

模板引擎(SpringBoot推荐的Thymeleaf)

JSP、Velocity、Freemarker、Thymeleaf都是模板引擎,可以通过它们自己的语法解析动态数据

 

  1. 引入
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring‐boot‐starter‐thymeleaf</artifactId>
    </dependency>
    切换thymeleaf版本
    <properties>
        <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
        <!--布局功能的支持程序    thymeleaf3主程序    layout2以上版本 ‐-->
        <!--thymeleaf2    layout1-->
        <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
    </properties>

     

  2. 创建页面
    @ConfigurationProperties(prefix = "spring.thymeleaf")
    public class ThymeleafProperties {
        private static final Charset DEFAULT_ENCODING = Charset.forName("UTF‐8");
        private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");
        public static final String DEFAULT_PREFIX = "classpath:/templates/";
        public static final String DEFAULT_SUFFIX = ".html";
    ThymeleafProperties.class

    只要我们把HTML页面放在classpath:/templates/,thymeleaf就能自动渲染;

     

  3. 语法规则及使用
    一、页面导入thymeleaf的名称空间
    <html lang="en" xmlns:th="http://www.thymeleaf.org">

    二、使用thymeleaf语法:  th:任意html属性;来替换原生属性的值

    <div th:text="${hello}">这是显示欢迎信息</div>

     

  4. *支持的表达式(${}-->OGNL表达式)

     

***SpringBoot的全局配置文件:application.properties与yaml,能配置什么

<!‐‐导入配置文件处理器,配置文件进行绑定就会有提示‐‐>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring‐boot‐configuration‐processor</artifactId> <optional>true</optional> </dependency>

这里重点讲yaml文件

  • yaml文件基本语法:

        k:(空格)v:表示一对键值对(空格必须有);以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的【属性和值也是大小写敏感】
    server:
        port: 8081
        path: /hello

     

  • yaml值的写法:

    1、普通的值(数字,字符串,布尔):
    k: v:字面直接来写;
    字符串默认不用加上单引号或者双引号;
    "":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
    name: "zhangsan \n lisi":输出;zhangsan 换行 lisi
    '':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
    name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi

    2、对象、Map(属性和值)(键值对):

    写法一:
    friends:
        lastName: zhangsan
        age: 20
    写法二:(行内写法)
    friends: {lastName: zhangsan,age: 18}

    3、数组(List、Set):里面的猫狗都是对象

    写法一:
    pets:
        ‐ cat
        ‐ dog
        ‐ pig
    写法二:(行内写法)
    pets: [cat,dog,pig]
  • 例子
    1、配置文件

    person:
        lastName: hello
        age: 18
        boss: false
        birth: 2017/12/12
        maps: {k1: v1,k2: 12}
        lists:
            ‐ lisi
            ‐ zhaoliu
        dog:
            name: 小狗
            age: 12

    2、javaBean

    /**
        * 将配置文件中配置的每一个属性的值,映射到这个组件中
        * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;、
        *
        * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能;
        *
        prefix = "person":配置文件中哪个下面的所有属性进行一一映射
    */
    @Component
    @ConfigurationProperties(prefix = "person") public class Person { private String lastName; private Integer age; private Boolean boss; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Dog dog; }

     

  • 配置文件占位符

    --占位符获取之前配置的值,如果没有可以是用:指定默认值

    person.dog.name=${person.hello:hello}_dog

     

  • Profile

    --我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml;默认使用application.properties的配置 其中yaml文件还支持多文档块的方式

    server:
        port: 8081
    spring:
        profiles:
            active: prod #指定激活使用哪个环境
    ‐‐‐
    server:
        port: 8083
    spring:
        profiles: dev
    ‐‐‐
    server:
        port: 8084
    spring:
        profiles: prod #指定属于哪个环境
    1、在配置文件中指定 spring.profiles.active=dev
    2、命令行:
    java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
    可以直接在测试的时候,配置传入命令行参数
    3、虚拟机参数;
    -Dspring.profiles.active=dev
    激活指定profile

     

  • *配置文件加载位置

    --springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件;

    SpringBoot会从这四个位置全部加载主配置文件;互补配置;

    优先级从高到低:

    –file:./config/
    –file:./
    –classpath:/config/
    –classpath:/

    可以通过在配置文件中【spring.config.location】来改变默认的配置文件位置:指定配置文件和默认加载的这些配置文件共同起作用形成互补配置

  • 外部配置文件加载顺序
    SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会
    形成互补配置
    1.命令行参数
    所有的配置都可以在命令行上进行指定
    java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
    多个配置用空格分开; --配置项=值
    2.来自java:comp/env的JNDI属性
    3.Java系统属性(System.getProperties())
    4.操作系统环境变量
    5.RandomValuePropertySource配置的random.*属性值
    由jar包外向jar包内进行寻找;
    优先加载带profile
    6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
    7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
    再来加载不带profile
    8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件
    9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件
    10.@Configuration注解类上的@PropertySource
    11.通过SpringApplication.setDefaultProperties指定的默认属性
    所有支持的配置加载来源;
    外部配置加载顺序

     

SpringBoot中的注解

  • @EnableAutoConfiguration:SpringBoot启动的时候加载主配置类,开启了自动配置功能
  • @PostMapping:处理post请求(以此类推:get、put...)
  • @RequestParam:获取请求参数
  • @RestController:不返回页面,返回json数据
  • 【@Value】获取值和【@ConfigurationProperties】获取值比较:

 @ConfigurationProperties@Value
功能批量注入配置文件中的属性一个个指定
松散绑定(松散语法)支持不支持
SpEL不支持支持
JSR303数据校验支持不支持
复杂类型封装支持不支持

 

  • @PropertySourceL:加载指定的配置文件;
    @PropertySource(value = {"classpath:person.properties"})
  • @ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
    @ImportResource(locations = {"classpath:beans.xml"})
  • 配置类@Configuration
  • @Bean用于某类中的方法,将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名

报错:Failed to bind properties under 'spring.datasource' to javax.sql.DataSource

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'spring.datasource' to javax.sql.DataSource:

    Property: spring.datasource.filters
    Value: stat,wall,log4j
    Origin: class path resource [application.yaml]:39:14
    Reason: org.apache.log4j.Logger

Action:
Update your application's configuration

解决办法:

<!-- log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

报错:log4j:WARN No appenders could be found for logger (druid.sql.Connection).

log4j:WARN No appenders could be found for logger (druid.sql.Connection).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

  • application.yml
    #日志配置
    logging:
      level:
        com.soldier: trace
      #spring.profiles.active=dev

     

  • 需要配置log4j.properties及logback-spring.xml
    ### set log levels ###
    log4j.rootLogger = debug ,  stdout ,  D ,  E
    
    ### 输出到控制台 ###
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target = System.out
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
    
    #### 输出到日志文件 ###
    #log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    #log4j.appender.D.File = /home/soldier/SOLDIER/idea_project/logs/LearningNotes/log.log
    #log4j.appender.D.Append = true
    #log4j.appender.D.Threshold = DEBUG ## 输出DEBUG级别以上的日志
    #log4j.appender.D.layout = org.apache.log4j.PatternLayout
    #log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    
    #### 保存异常信息到单独文件 ###
    #log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    #log4j.appender.D.File = /home/soldier/SOLDIER/idea_project/logs/LearningNotes/error.log ## 异常日志文件名
    #log4j.appender.D.Append = true
    #log4j.appender.D.Threshold = ERROR ## 只输出ERROR级别以上的日志!!!
    #log4j.appender.D.layout = org.apache.log4j.PatternLayout
    #log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    log4j.properties
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
    scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
    scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
    debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
    -->
    <configuration scan="false" scanPeriod="60 seconds" debug="false">
        <!-- 定义日志的根目录 -->
        <property name="LOG_HOME" value="/home/soldier/SOLDIER/idea_project/logs/LearningNotes" />
        <!-- 定义日志文件名称 -->
        <property name="appName" value="spring_boot"></property>
        <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
        <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
            <!--
            日志输出格式:
                %d表示日期时间,
                %thread表示线程名,
                %-5level:级别从左显示5个字符宽度
                %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 
                %msg:日志消息,
                %n是换行符
            -->
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            </layout>
        </appender>
    
        <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
        <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 指定日志文件的名称 -->
            <file>${LOG_HOME}/${appName}.log</file>
            <!--
            当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
            TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
            -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!--
                滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 
                %i:当文件大小超过maxFileSize时,按照i进行文件滚动
                -->
                <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
                <!-- 
                可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
                且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
                那些为了归档而创建的目录也会被删除。
                -->
                <MaxHistory>365</MaxHistory>
                <!-- 
                当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
                -->
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <!-- 日志输出格式: -->     
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
            </layout>
        </appender>
    
        <!-- 
            logger主要用于存放日志对象,也可以定义日志类型、级别
            name:表示匹配的logger类型前缀,也就是包的前半部分
            level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
            additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,
            false:表示只用当前logger的appender-ref,true:
            表示当前logger的appender-ref和rootLogger的appender-ref都有效
        -->
        <!-- hibernate logger -->
        <logger name="com.soldier" level="debug" />
        <!-- Spring framework logger -->
        <logger name="org.springframework" level="debug" additivity="false"></logger>
    
    
    
        <!-- 
        root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
        要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。 
        -->
        <root level="info">
            <appender-ref ref="stdout" />
            <appender-ref ref="appLogAppender" />
        </root>
    </configuration> 
    logback-spring.xml

     

  • 如图:

 

报错:log4j:ERROR Category option " 1 " not a decimal integer.

  • 解决办法--log4j.properties 的配置文件中:把{1}中的空格去掉。

 

转载于:https://www.cnblogs.com/HuangJie-sol/p/10892648.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值