springboot学习笔记

    科技2022-07-10  126

    1.修改springboot启动banner

    到网上搜一个ascii艺术字并复制,然后新建banner.txt把艺术字粘贴到文件中

    重启后即生效

    2.springboot自动配置原理

    继承:

    <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>

    在pom.xml中定义了继承结构,当前应用继承自spring-boot-starter-parent,spring-boot-starter-parent继承自spring-boot-dependencies,在spring-boot-dependencies中管理着核心依赖和版本,这也是我们在pom.xml无需写版本号的原因,不写会继承自父artifact定义的版本号。

    启动器:

    springboot帮助我们将某个场景下需要使用到的依赖和配置打包成一个启动器,我们需要使用某个场景的功能直接导入这个启动器依赖就可以了。加入我们需要使用到web,那么导入下面的依赖就完成了相关依赖的导入,

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>

    应用入口:

    3.yaml语法

    # 字符串 name: 左西俊 # 对象 student1: name: 王芳 age : 23 student2: {name: 王芳,age: 23} #数组 students1: - s1 - s2 - s3 students2: [s1,s2,s3]

    4.配置文件属性绑定

    首先导入依赖

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>

    编写配置文件:

    person: name: zuoxijun age: 23 happy: false birth: 1996/6/19 maps: k1: 2 k2: 3 lists: - 1 - 2 - 3 dog: name: wangzai age: 3

    编写实体类,使用@Component注解将类交给spring管理,使用@ConfigurationProperties注解将配置文件属性和实体类属性进行按名映射:

    @Component @ConfigurationProperties(prefix = "person") public class Person { private String name; private Integer age; private Boolean happy; private Date birth; private Map<String, Integer> maps; private List<Integer> lists; private Dog dog; ........ }

    @Component注解加在类上,标明该类由spring进行管理

    属性注入还可以通过@Value注解进行单独注入,@Value由两种语法#{}和${},@Value和@ConfigurationProperties的区别如下:

    松散绑定也即配置文件中的last-name可以对应到java bean中的lastName

    EL表达式:

    //整形 @Value("#{11}") //字符串 @Value("#{'haha'}") //其它bean的属性 @Value("#{bean.name}")

    取出properties文件中的属性:

    通过@PropertySource绑定properties文件,通过@Component将类将给spring管理,通过${}取出properties文件属性

    @Component @PropertySource("classpath:my.properties") public class Dog { @Value("${test.name}") private String name; @Value("${test.age}") private Integer age; ......... }

    5.@Bean注解

    一般和@Configuration注解一起使用

    @Configuration public class MyConfiguration { @Bean(name = {"ddd", "ccc"}) public Dog dog1(){ return new Dog("发财", 23); } }

    不指定name属性时,spring会使用方法名+首字母小写作为该bean的名字,指定name后使用name属性的值作为该bean的名字,name可以指定多个名字。

    bean的默认作用域为singleton,如果想修改可以结合@Scope注解

    6.@Autowired和@Resource

    可以加载属性或者set方法上,@Autowired默认是按照类型进行装配的,如果存在多个相同类型的bean就会报错,它会尝试使用属性名作为bean的名称去搜索,如果不能唯一找到一个bean则抛出异常。可以和@Qualifier组合使用,定位一个指定名称的bean。@Autowired是spring为我们定义的注解。

    @Resource是javax包下的不属于spring,它可以加在属性或者set方法上,默认按照byName进行装配,如果byName装配失败则按照byType进行装配。注意如果指定了它的type属性则一定按照byType进行装配,如果指定了它的name属性则一定按照byName进行装配。

    7.JSR303校验

    导入依赖:

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>

    @Validated在bean上开启检验:

    @Component @PropertySource("classpath:my.properties") @Validated public class Dog { .............. }

    在需要校验的属性上添加校验注解(如校验是否是email):

    @Component @PropertySource("classpath:my.properties") @Validated public class Dog { @Email @Value("${test.name}") private String name; ................ }

    所有的校验注解类型如下图:

    8.springboot多环境配置

    spring: profiles: active: test --- server: port: 8081 spring: profiles: dev --- server: port: 8083 spring: profiles: test

    WEB开发

    静态资源

    1.webjars

    通过maven导入jar包来使用静态资源,以导入jquery为例

    <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.5.1</version> </dependency>

    在WebMvcAutoConfiguration中:

    if (!registry.hasMappingForPattern("/webjars/**")) { this.customizeResourceHandlerRegistration( registry.addResourceHandler(new String[]{"/webjars/**"}) .addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}) .setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl)); }

    将/webjars/**请求映射到/META/resources/webjars/目录下,而我们通过maven导入的jar包符合这个结构:

    所以我们通过访问http://ip:8080/webjars/jquery/3.5.1/jquery.js能访问到静态资源

    2.静态资源目录

    String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { this.customizeResourceHandlerRegistration(registry .addResourceHandler(new String[]{staticPathPattern}) .addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())) .setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl)); }

    staticPathPattern资源访问路径模式,是从WeMvcProperties中获得的:

    public WebMvcProperties() { this.localeResolver = WebMvcProperties.LocaleResolver.ACCEPT_HEADER; this.format = new WebMvcProperties.Format(); this.dispatchTraceRequest = false; this.dispatchOptionsRequest = true; this.ignoreDefaultModelOnRedirect = true; this.publishRequestHandledEvents = true; this.throwExceptionIfNoHandlerFound = false; this.logResolvedException = false; this.staticPathPattern = "/**"; this.async = new WebMvcProperties.Async(); this.servlet = new WebMvcProperties.Servlet(); this.view = new WebMvcProperties.View(); this.contentnegotiation = new WebMvcProperties.Contentnegotiation(); this.pathmatch = new WebMvcProperties.Pathmatch(); }

    而在WebMvcProperties中它的值为/**,可以通过在yaml文件中配置修改这个路径

    this.resourceProperties.getStaticLocations(),resourceProperties是ResourceProperties的实例,staticLocations的值如下:

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{ "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" };

    即访问/**会映射到上面四个类路径下的文件夹下,优先级依次是META-INF/resources > resources > static > public

    因此可以通过http://ip/文件名,访问这四个文件夹下的静态资源。

    修改staticPathPattern和staticLocations的yaml配置对应为:

    spring: mvc: static-path-pattern: yourPattern resources: static-locations: yourLocaltions(数组类型)

    从上面可以看出,springboot的核心就是***Autoconfiguration,***Properties类,AutoConfiguration持有Properties的引用,Properties类绑定了yaml配置文件的某个前缀,三者共同协调实现springboot的自动配置。

    首页

    直接访问ip地址,如httlp://localhost:8080/会默认展示一个页面,即index首页页面,在WebMvcAutoConfiguration类中可以发现下面的代码:

    private Optional<Resource> getWelcomePage() { String[] locations = WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations()); return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst(); } private Resource getIndexHtml(String location) { return this.resourceLoader.getResource(location + "index.html"); }

    springboot的首页默认是从静态资源目录,即{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"}下面找index.html文件,这个html即为首页。

    另外我们也可以通过定义Controller来映射index.html文件,首先在templates文件夹下新建index.html文件,然后新建IndexController来映射:

    @Controller public class IndexController { @RequestMapping("/") public String index(){ return "index"; } }

    注意这种方式要添加thymeleaf引擎来解析视图:

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>

     

    SpringMVC扩展

    编写一个配置类实现WebMvcConfigurer接口,类上添加@Configugration注解,之后实现不同的方法来扩展springmvc的功能,如扩展一个视图控制器,如下所示:

    @Configuration public class MyMvcConfiguration implements WebMvcConfigurer { //springmvc扩展 添加视图控制器 @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/zuoxijun").setViewName("test1"); } }

    国际化

    1.将idea的文件编码全部修改为utf-8

    2.创建properties语言包文件

    3.再application.yaml中配置语言包的basename

    4.自定义locale处理器,接收不同的url参数对应到不同的locale

    public class MyLocaleResolver implements LocaleResolver { private static Set<String> supportLanguages = new HashSet<>(); static { supportLanguages.add("en_US"); supportLanguages.add("zh_CN"); } @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String lang = httpServletRequest.getParameter("l"); System.out.println(lang); if(supportLanguages.contains(lang)){ String[] s = lang.split("_"); return new Locale(s[0], s[1]); } return Locale.getDefault(); } }

    5.将locale处理器交给spring管理

    注意这里的LocaleResolver的bean的id必须是localeResolver,所以方法名必须是localeResolver,否则是不生效的,springboot不会用我们自定义的LocaleResolver.这是因为在WebMvcAutoConfiguration中:

    @ConditionalOnMissingBean判断id为localResolver的bean不存在就会使用自动配置的LocaleResolver.

    6.前端添加链接

    拦截器

    1.创建拦截器,实现HandlerInterceptor接口

    public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断是否登录 if(Boolean.TRUE.equals(request.getSession().getAttribute("login"))){ return true; } request.setAttribute("notLogin", "notLogin"); request.getRequestDispatcher("/index").forward(request, response); return false; } }

    2.注册拦截器

    错误页面

    在templates下创建error目录,下面放上响应错误的html页面,发生错误即可自动跳转到这个页面。

    整合druid数据源

    导包

    <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>

    切换druid数据源,默认是Hikari数据源

    datasource: url: jdbc:mysql://106.14.205.174/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC username: root password: 190539 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #Spring Boot 默认是不注入这些属性值的,需要自己绑定 #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,stat:监控统计、log4j:日志记录、wall:防御sql注入 #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

    type属性即是指定数据源的

    druid自定义配置:

    @Configuration public class DruidConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource(){ return new DruidDataSource(); } //注册 @Bean //注册servlet来跳转到后台监控页面 public ServletRegistrationBean bb(){ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*"); Map<String, String> initParams = new HashMap<>(); initParams.put("allow", ""); initParams.put("loginUsername", "admin"); initParams.put("loginPassword", "190539"); servletRegistrationBean.setInitParameters(initParams); return servletRegistrationBean; } //过滤一下不需要druid进行监控的页面 @Bean public FilterRegistrationBean aa(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter()); Map<String, String> map = new HashMap<>(); map.put("exclusions","/druid/*,/jdbc/*, /druid"); filterRegistrationBean.setInitParameters(map); return filterRegistrationBean; } }

    druid内置了一个servlet提供浏览器监控展示服务即StatViewServlet。,用ServletRegistrationBean来注册这个Servlet,

    对于不想进行统计的页面,可以通过FilterRegistrationBean注册WebStatFilter过滤器来过滤掉不需要监控的路径。

     

    Processed: 0.011, SQL: 8