第一阶段

一、认识SpringBoot

1.1 HelloWorld

  1. 版本要求:java8maven3.3以上版本
  2. 导入相关依赖
  1. <!-- 导入父工程 -->
  2. <parent>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <groupId>org.springframework.boot</groupId>
  5. <version>2.6.0</version>
  6. </parent>
  7. <!--web场景的场景启动器 会自动导入web项目所有的依赖jar包-->
  8. <dependencies>
  9. <dependency>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-web</artifactId>
  12. <version>2.6.0</version>
  13. </dependency>
  14. </dependencies>
  1. 编写一个主程序,在类上使用注解 @SpringBootlication 这个注解的作用就是表示这是一个 SpringBoot应用,这个类就称为主程序类
  1. @SpringBootApplication
  2. public class MainApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(MainApplication.class,args);
  5. }
  6. }
  1. 编写控制层Controller 知识点@ResponseBody放在控制层类上表示此类所有的方法全都视为向浏览器输出内容,而@RestController相当于
    **_@Controller_**+**_@ResponseBody_** 表示此类的所有控制器方法都是输出内容
  1. //@ResponseBody
  2. //@Controller
  3. @RestController
  4. public class ControllerJson {
  5. @RequestMapping("/hello")
  6. public String handler(){
  7. return "Hello SpringBoot2!";
  8. }
  9. }
  1. 运行主程序的main方法直接输入地址 如图
    img.png

    2、简化的配置文件

  • 创建一个名字为application.properties的配置文件【注意:必须要叫这个名,不然无效】
  • 其中可以编写一些配置
  1. #编写Tomcat的端口号
  2. server.port=8888

3、创建Jar包

第一步、导入相关依赖

  1. <!--加上打包方式不是web的war-->
  2. <packaging>jar</packaging>
  3. <!--扩展包-->
  4. <build>
  5. <plugins>
  6. <plugin>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-maven-plugin</artifactId>
  9. <version>2.6.0</version>
  10. </plugin>
  11. </plugins>
  12. </build>

然后选中maven工程的打包
img_1.png
进入到此文件的目录打开cmd命令行输入java -jar [jar包名].jar 注意关闭cmd窗口的快速编辑模式

4、重写依赖jar包

如果此时SpringBoot自动仲裁的包不是我们想要的,此时就需要重写

  1. <properties>
  2. <!-- 以MySQL为例子 -->
  3. <mysql.version>5.1.43</mysql.version>
  4. <properties/>

5、SpringMVC的常用组件 SpringBoot已经配置好

主程序所在的包及其子包都会默认扫描进IOC容器

6、@Configuration 以及 @Bean

@Configuration 当一个类上放置了这个注解之后 就会变为配置类,被SpringBoot主方法扫描进IOC容器之后作为组件的一部分
这个类中@Bean 所标注的方法中返回的对象都会作为组件的一部分

  1. @Configuration(proxyBeanMethods = true)
  2. public class UserController {
  3. @Bean
  4. public User getUser(){
  5. return new User("张三",getPet());
  6. }
  7. @Bean
  8. public Pet getPet(){
  9. return new Pet("tom");
  10. }
  11. }

@Configuration(proxyBeanMethods = true)默认为TRUE时就是单例模式 Full模式
为FALSE 时就是 Lite模式 ,这个模式启动比较快
当组件依赖时最好为TRUE
注意这个是SpringBoot的内容

引用的解释

官方文档描述: 用@Configuration注释类表明其主要目的是作为bean定义的源 @Configuration类允许通过调用同一类中的其他@Bean方法来定义bean之间的依赖关系

ta人总结: 1.表明当前类是一个配置类,是方法bean的源
2.将@Configuration配置的AppConfig的beanDefinitioin属性赋值为full类型的,保证AppConfig类型 可以转变为cglib类型 3.将@Configuration配置的AppConfig由普通类型转变为cglib代理类型,后会生成cglib代理对象,通 过代理对象的方法拦截器,
可以解决AppConfig内部方法bean之间发生依赖调用的时候从容器中去获取,避免了多例的出现

二、正式学习SpringBoot2

1、相关注解

@Import 注解

作用:可以调用给容器中创建导入的组件(无参构造)

  1. @Import({User.class,Pet.class})
  2. @Configuration(proxyBeanMethods=true)
  3. public class ConfigurationBean {

结果: 是默认组件的全类名

  1. String[] names = run.getBeanNamesForType(User.class);
  2. for(String name:names) {
  3. System.out.println("========");
  4. System.out.println(name);//demo.bean.User
  5. }

@Conditional 以及派生注解

  1. @ConditionalOnBean 在容器中有某个组件
  • 当放在方法上时,当条件成立 方法中的组件才会在容器中注册
  • 放在类上时,当条件成立时 类中的组件才会生效
    1. @ConditionalOnBean(name = "tom")
    2. //判断容器中是否有tom这个组件
  1. @ConditionalOnMissingBean 当容器中没有才进行注册

    @ImportResource

    当有配置文件或者其他配置类时可以使用此注解导入到当前要使用的IOC容器
    1. @ImportResource("classpath:bean1.xml")
    2. //放在类上

    2、配置绑定

    @ConfigurationProperties

    image.png
    image.png
    image.png
    image.png
    注意:被装配的类一定要开启 set方法

    @EnableConfigurationProperties(Car.class)

    ```java @EnableConfigurationProperties(Car.class) //这种方式依然需要@ConfigurationProperties在需要配置的类上 //不过不需要把该类放在IOC容器当中 //这个注解是放在类上 括号里面加装配过的类 //这个注解会把类自动注入到容器当中
  1. <a name="Jd23g"></a>
  2. ### 3、@SpringBootApplication 源码分析
  3. ```java
  4. @Target(ElementType.TYPE)
  5. @Retention(RetentionPolicy.RUNTIME)
  6. @Documented
  7. @Inherited
  8. @SpringBootConfiguration
  9. @EnableAutoConfiguration
  10. @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  11. @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
  12. public @interface SpringBootApplication {

@SpringBootConfiguration

  1. //该注解的底层
  2. @Target(ElementType.TYPE)
  3. @Retention(RetentionPolicy.RUNTIME)
  4. @Documented
  5. //代表着是一个配置类而已
  6. @Configuration
  7. public @interface SpringBootConfiguration {

@ComponentScan

  1. (excludeFilte@ComponentScan(excludeFilters =
  2. { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
  3. @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

就是扫描包

@EnableAutoConfiguration

  1. @AutoConfigurationPackage
  2. @Import(AutoConfigurationImportSelector.class)
  3. public @interface EnableAutoConfiguration {

1、@AutoConfigurationPackage

自动配置包(规则)
就是将@SpringBootApplication 所标注的类的所在包下的所有组件都加载进来

  1. @Import(AutoConfigurationPackages.Registrar.class)//给容器中导入一个(系列)组件
  2. public @interface AutoConfigurationPackage {
  1. static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
  2. @Override
  3. public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
  4. register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
  5. }
  6. @Override
  7. public Set<Object> determineImports(AnnotationMetadata metadata) {
  8. return Collections.singleton(new PackageImports(metadata));
  9. }
  10. }

@Import(AutoConfigurationImportSelector.class)
  1. //1、利用该方法给容器中导入一批组件
  2. protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
  3. if (!isEnabled(annotationMetadata)) {
  4. return EMPTY_ENTRY;
  5. }
  6. AnnotationAttributes attributes = getAttributes(annotationMetadata);
  7. //2、利用List<String> configurations 获取到所有需要导入的包
  8. List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
  9. configurations = removeDuplicates(configurations);
  10. Set<String> exclusions = getExclusions(annotationMetadata, attributes);
  11. checkExcludedClasses(configurations, exclusions);
  12. configurations.removeAll(exclusions);
  13. configurations = getConfigurationClassFilter().filter(configurations);
  14. fireAutoConfigurationImportEvents(configurations, exclusions);
  15. return new AutoConfigurationEntry(configurations, exclusions);
  16. }
  1. protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
  2. //利用工厂加载一些东西
  3. List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
  4. getBeanClassLoader());
  5. Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
  6. + "are using a custom packaging, make sure that file is correct.");
  7. return configurations;
  8. }

4、总结

加载127个配置类
SpringBoot 会按照条件自动装配规则(@Conditionnal)最终会按需配置

流程:XXXXAutoConfiguration—->组件—->XXXXProperties——->application.properties
也就是说更改配置文件就可以更改编码等等

5、 查看引入的场景配置

在application.properties 文件中
debug=true
控制台打印 Positive 生效
控制台打印 Negative 不生效

6、热更新

  1. <!-- 热部署 资源占大 -->
  2. <!-- <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-devtools</artifactId>
  5. <version>2.5.6</version>
  6. </dependency>
  7. -->

第一阶段总结

  1. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  2. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.context.annotation.Import;
  6. import org.springframework.context.annotation.ImportResource;
  7. import demo.bean.Car;
  8. import demo.bean.Pet;
  9. import demo.bean.User;
  10. @Import({User.class,Pet.class})
  11. @Configuration(proxyBeanMethods=true)
  12. @ConditionalOnMissingBean(name = "!demo.bean.User")
  13. //@ImportResource("classpath:bean1.xml")
  14. @EnableConfigurationProperties(Car.class)
  15. public class ConfigurationBean {
  16. //@ConditionalOnBean(name = "tom")
  17. @Bean("user")
  18. public User getUser() {
  19. return new User("张三",getPet());
  20. }
  21. @Bean("tom")
  22. public Pet getPet() {
  23. return new Pet("tom");
  24. }
  25. }

第二阶段

一、配置、Web

1、yaml

是标记语言?不是标记语言?
image.png

基本使用方式

image.png
双引号不会转义,而单引号会转义

编写提示依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-configuration</artifactId>
  4. <optional>true</optional>
  5. </dependency>

2、Web开发

WebMvcConfigurer

功能等同于原来的springMVC.xml。可以注册视图解析器,多部件解析器

静态资源目录

静态资源访问

  • public
    • 可以直接访问
  • META-INF/resources
    • 可以直接访问
  • resources
    • 可以直接访问
  • static
    • 可以直接访问

配置静态资源访问目录

  1. # 不配置的话默认访问静态资源目录为/**
  2. spring:
  3. mvc:
  4. static-path-pattern: /wjl/**
  5. # 此时要想找到静态资源 静态资源的目录必须是所设置的文件夹
  6. # 注意:已经被弃用
  7. resources:
  8. static-locations: classpath: /wjl1/

欢迎界面

  • 默认为index名字的HTML文件
  • 设置了静态资源的目录可以访问
  • 加了前缀不行 static-path-pattern: /wjl/**

favicon.ico 文件会默认为网站图标 和代码无太多关联、浏览器处理
网站缓存原因 Shift+f5/刷新

配置文件和相关属性进行了绑定

image.png

一些相关配置以及源码

1、禁用所有静态资源
  1. spring:
  2. resources:
  3. # add-mappings 类的实例属性
  4. add-mappings: false

对应的WebMvcAutoconfiguration.java(也就是webMVC的配置类)中的源码部分

  1. @Override
  2. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  3. if (!this.resourceProperties.isAddMappings()) {
  4. logger.debug("Default resource handling disabled");
  5. return;
  6. }
  7. Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
  8. CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
  9. if (!registry.hasMappingForPattern("/webjars/**")) {
  10. customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
  11. .addResourceLocations("classpath:/META-INF/resources/webjars/")
  12. .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
  13. }
  14. String staticPathPattern = this.mvcProperties.getStaticPathPattern();
  15. if (!registry.hasMappingForPattern(staticPathPattern)) {
  16. customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
  17. .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
  18. .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
  19. }
  20. }

WelcomePageHandlerMapping.java中的处理欢迎页代码

  1. final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping {
  2. private static final Log logger = LogFactory.getLog(WelcomePageHandlerMapping.class);
  3. private static final List<MediaType> MEDIA_TYPES_ALL = Collections.singletonList(MediaType.ALL);
  4. WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
  5. ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) {
  6. if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
  7. logger.info("Adding welcome page: " + welcomePage.get());
  8. setRootViewName("forward:index.html");
  9. }
  10. else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
  11. logger.info("Adding welcome page template: index");
  12. setRootViewName("index");
  13. }
  14. }
  15. private boolean welcomeTemplateExists(TemplateAvailabilityProviders templateAvailabilityProviders,
  16. ApplicationContext applicationContext) {
  17. return templateAvailabilityProviders.getProvider("index", applicationContext) != null;
  18. }
  19. private void setRootViewName(String viewName) {
  20. ParameterizableViewController controller = new ParameterizableViewController();
  21. controller.setViewName(viewName);
  22. setRootHandler(controller);
  23. setOrder(2);
  24. }
  25. @Override
  26. public Object getHandlerInternal(HttpServletRequest request) throws Exception {
  27. for (MediaType mediaType : getAcceptedMediaTypes(request)) {
  28. if (mediaType.includes(MediaType.TEXT_HTML)) {
  29. return super.getHandlerInternal(request);
  30. }
  31. }
  32. return null;
  33. }
  34. private List<MediaType> getAcceptedMediaTypes(HttpServletRequest request) {
  35. String acceptHeader = request.getHeader(HttpHeaders.ACCEPT);
  36. if (StringUtils.hasText(acceptHeader)) {
  37. return MediaType.parseMediaTypes(acceptHeader);
  38. }
  39. return MEDIA_TYPES_ALL;
  40. }
  41. }

开启REST 请求风格的请求

此时不得不夸赞 Rest风格真的协调 同一段请求连接 不同的请求方式
不同的效果

  • get 查
  • post 增
  • put 改
  • delete 删
  • patch

控制器部分

  1. //@RestColltroller
  2. @ResponseBody
  3. @Controller
  4. public class ControllerWeb {
  5. // @ResponseBody
  6. // @RequestMapping("/")
  7. // public String hello() {
  8. // return "Hello SpringBoot2!";
  9. // }
  10. @RequestMapping(value="/user",method=RequestMethod.GET)
  11. public String getUser() {
  12. return "get-张三";
  13. }
  14. @RequestMapping(value = "/user",method = RequestMethod.POST)
  15. public String saveUser() {
  16. return "post-张三";
  17. }
  18. @RequestMapping(value = "/user",method = RequestMethod.PUT)
  19. public String updateUser() {
  20. return "put-张三";
  21. }
  22. @RequestMapping(value = "/user",method = RequestMethod.DELETE)
  23. public String deletsUser() {
  24. return "delete-张三";
  25. }
  26. }

表单部分

  1. <form action="/user" method="post">
  2. <!--这里大小写都行-->
  3. <input type="hidden" name="_method" value="put"/>
  4. <input type="submit" value="put">
  5. </form><br>

该配置源码

  1. //SpringMVC的HiddenHttpMethodFilter
  2. @Override
  3. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
  4. throws ServletException, IOException {
  5. HttpServletRequest requestToUse = request;
  6. if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
  7. String paramValue = request.getParameter(this.methodParam);
  8. if (StringUtils.hasLength(paramValue)) {
  9. String method = paramValue.toUpperCase(Locale.ENGLISH);
  10. if (ALLOWED_METHODS.contains(method)) {
  11. requestToUse = new HttpMethodRequestWrapper(request, method);
  12. }
  13. }
  14. }
  15. //WebMVC类
  16. @Bean
  17. @ConditionalOnMissingBean(FormContentFilter.class)
  18. @ConditionalOnProperty(prefix = "spring.mvc.formcontent.filter", name = "enabled", matchIfMissing = true)
  19. public OrderedFormContentFilter formContentFilter() {
  20. return new OrderedFormContentFilter();
  21. }

所以实际开启:

  1. # 真的比MVC方便许多
  2. # 选择性开启 如果用能直接发送delete和put等的方式可以不开启
  3. spring:
  4. mvc:
  5. hiddenmethod:
  6. filter:
  7. enabled: true

MVC 注解

@PathVariable @RequestHeader
  1. @RestController
  2. public class ControllerRest {
  3. @GetMapping("/user/{id}/{username}")
  4. public Map<String,Object> rest1(
  5. @PathVariable("id") Integer id,
  6. @PathVariable("username") String username,
  7. @PathVariable Map<String,Object> map,
  8. @RequestHeader("User-Agent") String Ua,
  9. //map不带User-Agent 就是所有
  10. @RequestHeader("User-Agent") Map<String,Object> uamap
  11. ){
  12. System.out.println(id);
  13. System.out.println(username);
  14. System.out.println(map);
  15. System.out.println(Ua);
  16. System.out.println(uamap);
  17. /*
  18. 1
  19. 王玉柱
  20. {id=1, username=王玉柱}
  21. Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0
  22. {host=localhost:8080, user-agent=Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0, accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,;q=0.8, accept-language=zh,en;q=0.5, accept-encoding=gzip, deflate, connection=keep-alive, upgrade-insecure-requests=1, sec-fetch-dest=document, sec-fetch-mode=navigate, sec-fetch-site=none, sec-fetch-user=?1}
  23. */
  24. return map;
  25. }
  26. }

@RequestParam

注意数组或者集合 多选模式下不要用map

  1. @GetMapping("/par")
  2. //http://localhost:8080/par?id=1&username=王玉柱&username=王
  3. public Map<String,Object> par
  4. (@RequestParam("id") Integer id,
  5. @RequestParam Map<String,Object> map,
  6. @RequestParam("username") List<Object> list,
  7. @RequestParam("username") String[] str
  8. ){
  9. System.out.println(id);
  10. System.out.println(map);
  11. System.out.println(list);
  12. for(int i=0;i<str.length;i++) {System.out.print(str[i]+" ");}
  13. return map;
  14. /*1
  15. {id=1, username=玉柱}
  16. [玉柱, 王]
  17. 玉柱 王
  18. */
  19. }

@CookieValue @RequestBody
  • @CookieValue(“key”) cookie是以键值对形式存储的
  • @CookieValue Cookie cookie 获取所有cookie
  • @RequestBody 获取所有的请求头信息

    URL重写@MatrixVariable(“k”)

    页面开发禁用了Cookie
    此时需要这样 矩阵变量
    /path;jssionssid=xxxx把Cookie的值通过矩阵变量的方式进行传递
    路径/路径; k=v;k=v;k=v 注意分号
    此时想要获得参数的值需要这个注解 @MatrixVariable("k")修饰方法形参变量以获得v的值

  • 不过很少用

不过SpringBoot默认禁用了矩阵变量
第一种方式 实现WebMvcConfigurer接口,重写默认方法

功能等同于原来的springMVC.xml。可以注册视图解析器,多部件解析器

configurePathMatch(PathMatchConfigurer configurer),更改对其的禁用

  1. @Configuration//组件
  2. public class ConfiguartionZDY /*implements WebMvcConfigurer*/{
  3. /*
  4. @Override //路径帮助器
  5. public void configurePathMatch(PathMatchConfigurer configurer) {
  6. // TODO Auto-generated method stub
  7. UrlPathHelper urlpath = new UrlPathHelper();
  8. //这个方法默认为true 意思就是默认移除掉分号在请求路径
  9. urlpath.setRemoveSemicolonContent(false);
  10. //set进去
  11. configurer.setUrlPathHelper(urlpath);
  12. }
  13. */
  14. @Bean//匿名内部类的形式
  15. public WebMvcConfigurer webMvcConfigurer() {
  16. return new WebMvcConfigurer(){
  17. public void configurePathMatch(PathMatchConfigurer configurer) {
  18. UrlPathHelper urlpath = new UrlPathHelper();
  19. //这个方法默认为true 意思就是默认移除掉分号在请求路径
  20. urlpath.setRemoveSemicolonContent(false);
  21. //set进去
  22. configurer.setUrlPathHelper(urlpath);
  23. }
  24. };
  25. }
  26. @Bean
  27. public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
  28. HiddenHttpMethodFilter filter = new HiddenHttpMethodFilter();
  29. //自定义rest请求的隐藏域name的值 过这里
  30. filter.setMethodParam("_method");
  31. return filter;
  32. }
  33. }

控制层
image.png

  1. //http://localhost:8080/jz/wjl;user=123;pass=123445
  2. @GetMapping("/jz/{path}")
  3. public String path(@PathVariable("path") String path,
  4. @MatrixVariable("user") String user,
  5. @MatrixVariable("pass") String pass
  6. ){
  7. System.out.println(path+"====>");//wjl
  8. return "path===>"+path+"\nuser==>"+user+"\npassword==>"+pass;
  9. }


/路径/path; user=xxxx/path2;user=xxxx
这种形式的需要注解的 pathVar属性

  1. //http://localhost:8080/jz/jz1;user=123/jz2;user=456
  2. @GetMapping("/jz/{path}/{path2}")
  3. public String path(@PathVariable("path") String path,
  4. @PathVariable("path2") String path2,
  5. @MatrixVariable(value="user",pathVar="path") String user,
  6. @MatrixVariable(value ="user",pathVar="path2") String user2
  7. ){
  8. System.out.println("path===>"+path+"path2====>"+path2+"\nuser==>"+user+"\npassword==>"+user2);
  9. //path===>jz1path2====>jz2 user==>123 password==>456
  10. return "path===>"+path+"path2====>"+path2+"\nuser==>"+user+"\npassword==>"+user2;
  11. }

内部类

动态:
  • 外部类的属性和方法内部类可以访问,但是外访问内的属性与方法必须new
  • 如果成员内部类的属性或者方法与外部类的同名,将导致外部类的这些属性与方法在内部类被隐藏,也可按照该格式调用,外部类.this.属性/方法。
  • 通过外部类创建内部类的两种方式
    1. //方式1
    2. C c = new C();
    3. C.D d = c.new D();
    4. /*方式2创建成员内部类对象*/
    5. C.D d1 = c.getClassD();

静态
  1. 完善了Java多继承机制,由于每一个内部类都可以独立的继承接口或类,所以无论外部类是否继承或实现了某个类或接口,对于内部类没有影响。
  2. 方便写事件驱动程序。
  3. 静态内部类对象的创建一般是外部类.内部类 类名 = new 外部类.内部类();
    成员内部类对象的创建一般是外部类.内部类 类名 = 外部类对象名.new 内部类();
    相应的链接
    内部类的详解)

域中的参数传递

  1. @RequestMapping("/mm")
  2. public String mm(Map<String,Object> map,
  3. Model model,
  4. HttpServletRequest requst,
  5. HttpServletResponse response)
  6. {
  7. map.put("map","map");
  8. model.addAttribute("model","model");
  9. requst.setAttribute("res","res");
  10. Cookie cookie = new Cookie("user","user");
  11. //放在域中
  12. response.addCookie(cookie);
  13. //转发的意思不要写错
  14. return "forward:/cook";
  15. }
  16. @ResponseBody
  17. @RequestMapping("/cook")
  18. public String cookie(
  19. @CookieValue(value ="user") String mapcookie,
  20. @RequestAttribute("map") String map,
  21. @RequestAttribute("model") String model,
  22. HttpServletRequest res
  23. ) {
  24. System.out.println("map====>"+map);
  25. System.out.println("model===>"+model);
  26. System.out.println("res====>"+res.getAttribute("res"));
  27. //System.out.println(cookie.getValue());
  28. System.out.println(mapcookie+"[cookie]");
  29. /*map====>map
  30. model===>model
  31. res====>res
  32. user[cookie]
  33. */

自定义对象的传递
  1. 当前页面表单的的name属性如果和实体类的属性名一致 可以直接用对象来接

    1. @ResponseBody
    2. @PostMapping("/save1")
    3. public BeanOne bean1(BeanOne one) {
    4. return one;
    5. }
    6. @ResponseBody
    7. @PostMapping("/save2")
    8. public BeanOne bean2(String username,String password,String sex) {
    9. BeanOne one = new BeanOne();
    10. one.setPassword(password);
    11. one.setUsername(username);
    12. one.setSex(sex);
    13. return one;
    14. }

    级联赋值

    1. 宠物名:<input type="text" name="pet.name"><br>

    更改级联赋值规则

    1. @Bean//匿名内部类的形式
    2. public WebMvcConfigurer webMvcConfigurer() {
    3. return new WebMvcConfigurer(){
    4. public void configurePathMatch(PathMatchConfigurer configurer) {
    5. UrlPathHelper urlpath = new UrlPathHelper();
    6. //这个方法默认为true 意思就是默认移除掉分号在请求路径
    7. urlpath.setRemoveSemicolonContent(false);
    8. //set进去
    9. configurer.setUrlPathHelper(urlpath);
    10. }
    11. //重写WebMvcConfigurer类中的类型转换器不在用传统的级联Per.per 而是这种逗号分割的
    12. @Override
    13. public void addFormatters(FormatterRegistry registry) {
    14. //将字符串转化为Pet对象
    15. registry.addConverter(new Converter<String,Pet>() {
    16. @Override
    17. public Pet convert(String str) {
    18. if(!StringUtils.isEmpty(str)) {
    19. Pet pet = new Pet();
    20. String[] strs = str.split(",");
    21. pet.setName(strs[0]);
    22. return pet;
    23. }
    24. return null;
    25. }
    26. });
    27. }
    28. };
    29. }

    SpringMVC 所支持的返回值

  • View
  • Model
  • ModelAndView
  • ResponseEntity
  • ReactiveHandler(响应式)
  • 自定义对象
  • StreamResponseBody(函数式)
  • HttpEntity
  • HttpHeaders
  • Callable(异步)
  • DeferredResult
  • ListenablFuture
  • CompletionStage
  • WebAsyncTask
  • @ModelAttribute
  • @ResponseBody

3、内容协商

1、首先引入依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-jdbc</artifactId>
  4. </dependency>

源码讲解链接

2、自定义MessageConverter
  1. #spring:
  2. # resources:
  3. # add-mappings: false
  4. spring:
  5. mvc:
  6. hiddenmethod:
  7. filter:
  8. enabled: true
  9. # 开启参数的内容协商
  10. contentnegotiation:
  11. favor-parameter: true

开启器内容协商之后可以在访问连接后面加一段可以指定请求要的是什么内容、
请求连接+?format=json 或者其他类型的

自定义内容协商解析
扩展接口留出来的扩展方法

  1. return new WebMvcConfigurer(){
  2. public void configurePathMatch(PathMatchConfigurer configurer) {
  3. UrlPathHelper urlpath = new UrlPathHelper();
  4. //这个方法默认为true 意思就是默认移除掉分号在请求路径
  5. urlpath.setRemoveSemicolonContent(false);
  6. //set进去
  7. configurer.setUrlPathHelper(urlpath);
  8. }
  9. //自定义内容协商把控制器所返回的对象写为自定义格式就是写出JSON就是JSON写出Xml就是Xml
  10. @Override
  11. public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
  12. //添加上自定义的MessageConverter
  13. converters.add(new WjlMessageConverters());
  14. }

加入自己的解析器

  1. //实现HttpMessageConverter总接口与其方法
  2. public class WjlMessageConverters implements HttpMessageConverter<BeanOne>{
  3. @Override//支持读取某种格式的功能
  4. public boolean canRead(Class<?> clazz, MediaType mediaType) {
  5. // TODO Auto-generated method stub
  6. return false;
  7. }
  8. @Override//支持写出某种数据的功能
  9. public boolean canWrite(Class<?> clazz, MediaType mediaType) {
  10. // TODO Auto-generated method stub
  11. //返回值是否支持这种类型
  12. return clazz.isAssignableFrom(BeanOne.class);
  13. }
  14. /**
  15. * 获取所有能支持的媒体类型
  16. * 服务器要统计所有MessageConverter都能写出哪些内容类型
  17. */
  18. @Override//在这个方法的 返回值里写出自己所需要的返回值类型
  19. public List<MediaType> getSupportedMediaTypes() {
  20. // TODO Auto-generated method stub
  21. return MediaType.parseMediaTypes("application/x-wjl");
  22. }
  23. @Override
  24. public BeanOne read(Class<? extends BeanOne> clazz, HttpInputMessage inputMessage)
  25. throws IOException, HttpMessageNotReadableException {
  26. // TODO Auto-generated method stub
  27. return null;
  28. }
  29. @Override
  30. public void write(BeanOne t, MediaType contentType, HttpOutputMessage outputMessage)
  31. throws IOException, HttpMessageNotWritableException {
  32. // TODO Auto-generated method stub
  33. //自定义协议数据的内容的写出 自定义写出到浏览器的数据
  34. String data = t.getUsername()+";"+t.getPassword()+";"+t.getSex()+";"+t.getPet();
  35. //获取输出流
  36. OutputStream body = outputMessage.getBody();
  37. //写出去
  38. body.write(data.getBytes());
  39. }
  40. }

4、视图解析与模板引擎‘

SpringBoot默认不支持jsp

项目访问路径请求连接设置

  1. server:
  2. servlet:
  3. context-path: /wjl

以后所有的请求都必须以wjl开头

依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  4. </dependency>

eclipse需要的配置

  1. spring.thymeleaf.cache=true
  2. spring.thymeleaf.check-template=true
  3. spring.thymeleaf.check-template-location=true
  4. spring.thymeleaf.content-type=text/html
  5. spring.thymeleaf.enabled=true
  6. spring.thymeleaf.encoding=UTF-8
  7. spring.thymeleaf.excluded-view-names=
  8. spring.thymeleaf.mode=HTML5
  9. spring.thymeleaf.prefix=classpath:/templates/
  10. spring.thymeleaf.suffix=.html

The 抽取公共内容的两种方式
image.png
image.png

  • forward
  • redirect

    5、拦截器

    ```java package Springbootdemo.handel;

import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; //自定义拦截器 //第一步 继承HandlerInterceptor接口 重写其方法 //把这个配置放在容器中 public class LoginHandleInterceptor implements HandlerInterceptor{

  1. @Override//目标方法执行之前
  2. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
  3. throws Exception {
  4. HttpSession session = request.getSession();
  5. if(session.getAttribute("login") != null) {
  6. //跳转到登录后的界面
  7. return true;
  8. }
  9. //跳转到登录界面
  10. session.setAttribute("mgs","请登录");
  11. //跳转到最开初的界面
  12. response.sendRedirect("/login");
  13. return false;
  14. }
  15. @Override//执行之后呢
  16. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
  17. ModelAndView modelAndView) throws Exception {
  18. HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
  19. }
  20. @Override//渲染之后
  21. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
  22. throws Exception {
  23. HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
  24. }

}

@Bean//匿名内部类的形式 public WebMvcConfigurer webMvcConfigurer() { return new WebMvcConfigurer(){ //放入容器中就是通过WebMvcConfigurer接口,要么实现接口,要么以匿名内部类的方式以@Bean //标注的方法WebMvcConfigurer抛出到容器中 @Override public void addInterceptors(InterceptorRegistry registry) { //添加进自定义的拦截器 registry.addInterceptor(new LoginHandleInterceptor()) //拦截所有 .addPathPatterns(“/**”) //放行不需要拦截的路径以及静态页面 .excludePathPatterns(“/“,”/login”); }

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/23215202/1639535262073-0446a9e8-5681-46ef-9ccb-3da842fc0c21.png#clientId=u2ba679e9-8d74-4&from=paste&height=276&id=u67821b39&margin=%5Bobject%20Object%5D&name=image.png&originHeight=552&originWidth=1225&originalType=binary&ratio=1&size=180235&status=done&style=none&taskId=ufb5233c7-d129-4151-8001-d2315d26367&width=612.5)
  2. <a name="Uq82s"></a>
  3. ### 6、文件上传与下载
  4. <a name="jKQ0f"></a>
  5. #### 上传
  6. html页面
  7. ```html
  8. 上传文件必须要的属性
  9. <form th:action="@{/file}" method="post" enctype="multipart/form-data">
  10. 用户名:<input type="text" name="username"><br>
  11. 密码: <input type="password" name="password"><br>
  12. 单文件上传:<input type="file" name="photo" ><br>
  13. 多文件上传:<input type="file" name="photos" multiple><br>
  14. <input type="submit" value="提交">
  15. </form>
  1. # 配置单个文件上传大小
  2. spring.servlet.multipart.max-file-size=10MB
  3. # 配置整个文件上传域的大小
  4. spring.servlet.multipart.max-request-size=100MB

控制器层面

  1. @ResponseBody
  2. //MultipartFile 封装的一个文件接口
  3. // 用来接受文件处理对象 多文件上传使用数组形式
  4. //@RequestPart("photo") 对应上传的文件的名字(name)
  5. @PostMapping("/file")
  6. public String file2(@RequestPart("photo") MultipartFile file,
  7. @RequestPart("photos") MultipartFile[] files,
  8. @RequestParam("username") String username,
  9. @RequestParam("password") String password) throws IOException {
  10. log.info("上传的文件信息:username={},password={},file={},files={}",
  11. username,password,file.getSize(),files.length);
  12. if (!file.isEmpty()){//判断文件是否为空
  13. String name = file.getOriginalFilename();//获取文件名然后存放文件
  14. file.transferTo(new File("D:\\.temp\\ceshiwenjianjia\\"+name));
  15. }
  16. if(files.length>0){
  17. for (MultipartFile f:files){
  18. if (!f.isEmpty()){//判断文件是否为空
  19. String fname = f.getOriginalFilename();//获取文件名
  20. f.transferTo(new File("D:\\.temp\\ceshiwenjianjia\\pi\\"+fname));
  21. }
  22. }
  23. }
  24. return "谢谢";
  25. }

下载

SpringMVC

1、文件下载

使用ResponseEntity实现下载文件的功能

  1. @RequestMapping("/testDown")
  2. public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
  3. //获取ServletContext对象
  4. ServletContext servletContext = session.getServletContext();
  5. //获取服务器中文件的真实路径
  6. String realPath = servletContext.getRealPath("/static/img/1.jpg");
  7. //创建输入流
  8. InputStream is = new FileInputStream(realPath);
  9. //创建字节数组
  10. byte[] bytes = new byte[is.available()];
  11. //将流读到字节数组中
  12. is.read(bytes);
  13. //创建HttpHeaders对象设置响应头信息
  14. MultiValueMap<String, String> headers = new HttpHeaders();
  15. //设置要下载方式以及下载文件的名字
  16. headers.add("Content-Disposition", "attachment;filename=1.jpg");
  17. //设置响应状态码
  18. HttpStatus statusCode = HttpStatus.OK;
  19. //创建ResponseEntity对象
  20. ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
  21. //关闭输入流
  22. is.close();
  23. return responseEntity;
  24. }

2、文件上传

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

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

上传步骤:

a>添加依赖:

  1. <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
  2. <dependency>
  3. <groupId>commons-fileupload</groupId>
  4. <artifactId>commons-fileupload</artifactId>
  5. <version>1.3.1</version>
  6. </dependency>

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

  1. <!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
  2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

c>控制器方法:

  1. @RequestMapping("/testUp")
  2. public String testUp(MultipartFile photo, HttpSession session) throws IOException {
  3. //获取上传的文件的文件名
  4. String fileName = photo.getOriginalFilename();
  5. //处理文件重名问题
  6. String hzName = fileName.substring(fileName.lastIndexOf("."));
  7. fileName = UUID.randomUUID().toString() + hzName;
  8. //获取服务器中photo目录的路径
  9. ServletContext servletContext = session.getServletContext();
  10. String photoPath = servletContext.getRealPath("photo");
  11. File file = new File(photoPath);
  12. if(!file.exists()){
  13. file.mkdir();
  14. }
  15. String finalPath = photoPath + File.separator + fileName;
  16. //实现上传功能
  17. photo.transferTo(new File(finalPath));
  18. return "success";
  19. }

7、错误处理机制

自定义异常显示页面
创建一个静态文件夹 error这里面专门存放一处理错误的页面

如果是自带的视图解析就是静态文件夹 如果是模板引擎就是模板引擎所规定的的文件夹下

image.png
此时网站出现异常会自动解析并跳转该文件夹下面的4xx,5xx页面
并且会把错误信息以JSON的形式显示
image.png
可以通过视图的功能取出来
image.png

自定义异常
image.png

8、Web原生组件注入

  • Servlet Filter Listener

    第一种方式

    image.png
  1. 在主配置类中上添加该注解 @ServletComponentScan("servlet类的包")
  2. 在Servlet类上面添加 @WebServlet(访问路径)
  3. Servlet类继承HttpServlet 并且重写doGet、doPost方法
  4. 直接响应 会 忽视SpringBoot的拦截器
  5. @WebFilter(拦截路径)WebListener也是同样如此 ```java //拦截器备忘 @WebFilter(“/serv”) public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    1. //放行
    2. chain.doFilter(request,response);
    }
  1. ```java
  2. @WebListener//监听器 继承ServletContextListener接口
  3. public class MyListener implements ServletContextListener {
  4. @Override
  5. public void contextInitialized(ServletContextEvent sce) {
  6. System.out.println("监听开始");
  7. }
  8. @Override
  9. public void contextDestroyed(ServletContextEvent sce) {
  10. System.out.println("监听结束");
  11. }
  12. }

第二种方式

RegistrationBean

image.png

  • 注册一个配置类
  • 要保证单例模式,不要造成代码冗余 ```java @Configuration(proxyBeanMethods = true)//配置类 public class MyRegistration { //把要映射的Servlet类注册到ServletRegistrationBean中 @Bean//并且配置访问路径 public ServletRegistrationBean myServlet(){

    1. MyServlet myServlet = new MyServlet();//要映射的Servlet类
    2. //此时/se 或者 /s 就是请求路径
    3. return new ServletRegistrationBean(myServlet,"/se","/s");

    }

    @Bean//注册拦截器 public FilterRegistrationBean myFilter(){

    1. MyFilter myFilter = new MyFilter();
    2. //第一种写法 拦截上面方法中注册Servlet类的路径
    3. //return new FilterRegistrationBean(myFilter,myServlet());
    4. //第二种 自己写路径
    5. MyFilter filter = new MyFilter();
    6. FilterRegistrationBean filterR = new FilterRegistrationBean<>(filter);
    7. ArrayList<String> list = new ArrayList<>(); list.add("/**"); list.add("/serv");
    8. filterR.setUrlPatterns(list);
    9. return filterR;

    }

    @Bean//注册监听器‘ public ServletListenerRegistrationBean myListener(){

    1. return new ServletListenerRegistrationBean(new MyListener());

    }

}

  1. <a name="CCs2s"></a>
  2. #### 更换Tomcat服务器
  3. ```xml
  4. <dependency>
  5. <groupId>org.springframework.boot</groupId>
  6. <artifactId>spring-boot-starter-web</artifactId>
  7. <exclusions>
  8. <exclusion>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-tomcat</artifactId>
  11. </exclusion>
  12. </exclusions>
  13. </dependency>
  14. <dependency>
  15. <groupId>org.springframework.boot</groupId>
  16. <artifactId>spring-boot-starter-undertow</artifactId>
  17. </dependency>

9、定制化SpringBootWeb的三种方式

一、创建配置类实现WebMvcConfigurer接口(推荐)

  1. @Configuration//组件
  2. public class ConfiguartionZDY /*implements WebMvcConfigurer*/{
  3. /*
  4. @Override //路径帮助器
  5. public void configurePathMatch(PathMatchConfigurer configurer) {
  6. // TODO Auto-generated method stub
  7. UrlPathHelper urlpath = new UrlPathHelper();
  8. //这个方法默认为true 意思就是默认移除掉分号在请求路径
  9. urlpath.setRemoveSemicolonContent(false);
  10. //set进去
  11. configurer.setUrlPathHelper(urlpath);
  12. }
  13. */
  14. @Bean//匿名内部类的形式
  15. public WebMvcConfigurer webMvcConfigurer() {
  16. return new WebMvcConfigurer(){
  17. //放入容器中就是通过WebMvcConfigurer接口,要么实现接口,要么以匿名内部类的方式以@Bean
  18. //标注的方法WebMvcConfigurer抛出到容器中
  19. //@Override
  20. // public void addInterceptors(InterceptorRegistry registry) {
  21. // //添加进自定义的拦截器
  22. // registry.addInterceptor(new LoginHandleInterceptor())
  23. // //拦截所有
  24. // .addPathPatterns("/**")
  25. // //放行不需要拦截的路径以及静态页面
  26. // .excludePathPatterns("/","/login");
  27. // }
  28. //自己设置内容协商策略
  29. @Override
  30. public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
  31. Map<String,MediaType> mediaTypes = new HashMap<>();
  32. ParameterContentNegotiationStrategy strategy =
  33. new ParameterContentNegotiationStrategy(mediaTypes);
  34. configurer.strategies(Arrays.asList(strategy));
  35. }
  36. public void configurePathMatch(PathMatchConfigurer configurer) {
  37. UrlPathHelper urlpath = new UrlPathHelper();
  38. //这个方法默认为true 意思就是默认移除掉分号在请求路径
  39. urlpath.setRemoveSemicolonContent(false);
  40. //set进去
  41. configurer.setUrlPathHelper(urlpath);
  42. }
  43. //自定义内容协商把控制器所返回的对象写为自定义格式就是写出JSON就是JSON写出Xml就是Xml
  44. @Override
  45. public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
  46. //添加上自定义的MessageConverter
  47. converters.add(new WjlMessageConverters());
  48. }
  49. //重写WebMvcConfigurer类中的类型转换器不在用传统的级联Per.per 而是这种逗号分割的
  50. /*
  51. @Override
  52. public void addFormatters(FormatterRegistry registry) {
  53. //将字符串转化为Pet对象
  54. registry.addConverter(new Converter<String,Pet>() {
  55. @Override
  56. public Pet convert(String str) {
  57. if(!StringUtils.isEmpty(str)) {
  58. Pet pet = new Pet();
  59. String[] strs = str.split(",");
  60. pet.setName(strs[0]);
  61. return pet;
  62. }
  63. return null;
  64. }
  65. });
  66. }
  67. */
  68. };
  69. }
  70. @Bean
  71. public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
  72. HiddenHttpMethodFilter filter = new HiddenHttpMethodFilter();
  73. //自定义rest请求的隐藏域name的值 过这里
  74. filter.setMethodParam("_method");
  75. return filter;
  76. }
  77. }

二、通过返回WebMvcRegistrations组件的形式

  1. //这里很底层 没做修改 只是知道有这么一种方式
  2. @Bean
  3. public WebMvcRegistrations webMvcRegistrations(){
  4. return new WebMvcRegistrations() {
  5. @Override
  6. public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
  7. return WebMvcRegistrations.super.getRequestMappingHandlerMapping();
  8. }
  9. @Override
  10. public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
  11. return WebMvcRegistrations.super.getRequestMappingHandlerAdapter();
  12. }
  13. @Override
  14. public ExceptionHandlerExceptionResolver getExceptionHandlerExceptionResolver() {
  15. return WebMvcRegistrations.super.getExceptionHandlerExceptionResolver();
  16. }
  17. };
  18. }

三 、失效的注解

  1. /**
  2. *WebMvcConfigurer 重写其方法
  3. *@EnableWebMvc: 全面接管SpringMVC
  4. * 意思就是都由自己定制 视图解析器 欢迎页
  5. * 静态资源等等SpringMVC全部失效
  6. * 由自己重写方法处理
  7. */
  8. @EnableWebMvc
  9. @Configuration
  10. public class ZiDingYiSpringMVC implements WebMvcConfigurer {

二、数据访问

1、SQL数据源

数据准备
SpringBoot不会自动导入驱动,因为ta不知道 需要什么数据库
所以需要自己导入 [做了版本仲裁]

  1. //默认版本
  2. <dependency>
  3. <groupId>mysql</groupId>
  4. <artifactId>mysql-connector-java</artifactId>
  5. </dependency>
  6. //自定义版本(就近原则)
  7. <properties>
  8. <java.version>1.8</java.version>
  9. <mysql.version>版本号</mysql.version>
  10. </properties>

数据源的自动配置

导入JDBC场景

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-jdbc</artifactId>
  4. </dependency>

SpringBoot的jdbc

  • DataSourceAutoConfiguration : 数据源的自动配置

    • 修改数据源相关的配置:spring.datasource
    • 数据库连接池的配置,是自己容器中没有DataSource才自动配置的
    • 底层配置好的连接池是:HikariDataSource
      1. @Configuration(proxyBeanMethods = false)
      2. @Conditional(PooledDataSourceCondition.class)
      3. @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
      4. @Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
      5. DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
      6. DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
      7. protected static class PooledDataSourceConfiguration

  • DataSourceTransactionManagerAutoConfiguration: 事务管理器的自动配置

  • JdbcTemplateAutoConfiguration: JdbcTemplate的自动配置,可以来对数据库进行crud
    • 可以修改这个配置项@ConfigurationProperties(prefix = “spring.jdbc”) 来修改JdbcTemplate
    • @Bean@Primary JdbcTemplate;容器中有这个组件
  • JndiDataSourceAutoConfiguration: jndi的自动配置
  • XADataSourceAutoConfiguration: 分布式事务相关的

配置数据库链接

  1. //默认的配置HikariDataSource
  2. spring:
  3. datasource:
  4. # /// 和 localhost:3306/
  5. url: jdbc:mysql:///wjl
  6. username: root
  7. password: 123456
  8. driver-class-name: com.mysql.cj.jdbc.Driver

测试代码

  1. @Slf4j
  2. @SpringBootTest
  3. class SpringBootDemo2ApplicationTests {
  4. @Autowired
  5. JdbcTemplate jdbcTemplate;
  6. @Test
  7. void contextLoads() {
  8. String sql = "select * from user where id = ?";
  9. User2 user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<User2>(User2.class), 1);
  10. log.info("此用户信息:{}",user);
  11. }
  12. }

获取德鲁伊连接

  1. @Configuration
  2. public class MyDataSources {
  3. /**
  4. * 当向容器中添加自己配置的数据源组件时
  5. * SpringBoot所自带的HikariDataSource就会失效
  6. * @return DruidDataSource实现了DataSource接口
  7. */
  8. //这个注解可以把配置文件中的数据源装配到所返回的组件中
  9. //绑定对应的配置文件中的数据库所需内容
  10. @Bean
  11. @ConfigurationProperties("spring.datasource")
  12. public DataSource getDataSource(){
  13. DruidDataSource dataSource = new DruidDataSource();
  14. //开启数据监控 可以不开启 有异常
  15. dataSource.setFilters("stat");
  16. //下面是再加上开启防火墙
  17. //dataSource.setFilters("stat,wall");
  18. return dataSource;
  19. }
  20. }

注意返回组件的bean(方法)与配置类不要有一样的默认空间名称,否则就会报错
配置德鲁伊的监控页

  1. @Configuration
  2. public class MyDataSources {
  3. /**
  4. * 当向容器中添加自己配置的数据源组件时
  5. * SpringBoot所自带的HikariDataSource就会失效
  6. * @return DruidDataSource实现了DataSource接口
  7. */
  8. //这个注解可以把配置文件中的数据源装配到所返回的组件中
  9. @Bean
  10. @ConfigurationProperties("spring.datasource")
  11. public DataSource getDataSource() throws SQLException {
  12. DruidDataSource dataSource = new DruidDataSource();
  13. //开启数据监控 可以不开启 有异常
  14. //这两个配置可以直接在配置文件中写出
  15. dataSource.setFilters("stat,wall");
  16. return dataSource;
  17. }
  18. /**
  19. * 配置德鲁伊的监控页
  20. * 地址栏输入http://localhost:8080/druid
  21. * 就可以看到监控页
  22. * @return
  23. */
  24. @Bean
  25. public ServletRegistrationBean statViewServlet(){
  26. StatViewServlet servlet = new StatViewServlet();
  27. //构造器需要一个StatViewServlet
  28. ServletRegistrationBean<StatViewServlet> registrationBean =
  29. new ServletRegistrationBean<>(servlet, "/druid/*");
  30. //初始化参数loginUsername用户名 admin 是自定义的
  31. registrationBean.addInitParameter("loginUsername","admin");
  32. registrationBean.addInitParameter("loginPassword","123456");
  33. return registrationBean;
  34. }
  35. /**
  36. * 用于采集web-jdbc关联监控的数据
  37. * @return
  38. */
  39. @Bean
  40. public FilterRegistrationBean filterRegistrationBean(){
  41. WebStatFilter filter = new WebStatFilter();
  42. FilterRegistrationBean<WebStatFilter> registrationBean =
  43. new FilterRegistrationBean<>(filter);
  44. List<String> list = new ArrayList<>(); list.add("/*");
  45. //要监控的内容
  46. registrationBean.setUrlPatterns(list);
  47. //排除监控的内容
  48. registrationBean.addInitParameter("exclusions","*.js,*.gif");
  49. return registrationBean;
  50. }
  51. }

总结:当我们看到某某个Bean的文档或者教程时,就可以把它加入到容器中

德鲁伊简略办法

以上是原理,导入这个依赖之后,以上不需要配置德鲁伊的版本等等

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>druid-spring-boot-starter</artifactId>
  4. <version>1.2.8</version>
  5. </dependency>
  1. @Slf4j
  2. @SpringBootTest
  3. class SpringDriudApplicationTests {
  4. @Autowired
  5. JdbcTemplate jdbcTemplate;
  6. @Autowired
  7. DataSource dataSource;
  8. @Test
  9. void contextLoads() {
  10. String sql = "select count(*) from user";
  11. Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);
  12. log.info("一共有{}条数据",integer);
  13. //手动配置的德鲁伊
  14. //com.alibaba.druid.pool.DruidDataSource
  15. //引入德鲁伊stat
  16. //com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceWrapper
  17. System.out.println("DataSource"+dataSource.getClass());
  18. }
  19. }

扩展配置项

之后的配置
image.png
image.png

  1. spring:
  2. datasource:
  3. url: jdbc:mysql://localhost:3306/db_account
  4. username: root
  5. password: 123456
  6. driver-class-name: com.mysql.jdbc.Driver
  7. druid:
  8. aop-patterns: com.atguigu.admin.* #监控SpringBean
  9. filters: stat,wall # 底层开启功能,stat(sql监控),wall(防火墙)
  10. stat-view-servlet: # 配置监控页功能
  11. enabled: true
  12. login-username: admin
  13. login-password: admin
  14. resetEnable: false
  15. web-stat-filter: # 监控web
  16. enabled: true
  17. urlPattern: /*
  18. exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
  19. filter:
  20. stat: # 对上面filters里面的stat的详细配置
  21. slow-sql-millis: 1000
  22. logSlowSql: true
  23. enabled: true
  24. wall:
  25. enabled: true
  26. config:
  27. drop-table-allow: false

这些都是写死的

2、整合Mybatis

入门

  1. <dependency>
  2. <groupId>org.mybatis.spring.boot</groupId>
  3. <artifactId>mybatis-spring-boot-starter</artifactId>
  4. <version>2.2.0</version>
  5. </dependency>

同理,可以在配置文件中修改相应的配置

  • SqlSessionFactory自动配置好了
  • SqlSession:自动配置了SqlSession组合了SqlSession
  • Mapper
    1. # 整合mybatis
    2. # 指定配置文件路径
    3. mybatis:
    4. config-location: classpath:mybatis-config.xml
    5. mapper-locations: classpath:springdriud/mapper/*.xml
    映射文件
    1. <mapper namespace="springdriud.mapper.UserMapper">
    2. <select id="selectById" resultType="springdriud.bean.User">
    3. select * from user where id = #{id}
    4. </select>
    5. </mapper>
    映射接口 ```java @Mapper//Springboot映射接口需要此注解 public interface UserMapper { User selectById(Long id); }

//service层 @Service public class UserService { @Autowired UserMapper userMapper; public User selectById(Long id){ return userMapper.selectById(id); } }

//Controller层 @Controller public class SqlController { // @Autowired // JdbcTemplate jdbcTemplate; @Autowired UserService userService;

  1. @ResponseBody
  2. @GetMapping("/user")
  3. public User selectById(@RequestParam("id") Long id){
  4. User user = userService.selectById(id);
  5. System.out.println(user);
  6. return user;
  7. }

}

  1. 默认开启驼峰命名规则<br />主配置文件中
  2. ```xml
  3. <settings>
  4. <setting name="mapUnderscoreToCamelCase" value="true"/>
  5. </settings>

SpringBoot配置文件中、

  1. mybatis:
  2. # 使用了yaml配置文件中的的对应配置之后
  3. # 对应的主配置文件就会冲突 不需要了
  4. #config-location: classpath:mybatis-config.xml
  5. mapper-locations: classpath:springdriud/mapper/*.xml
  6. configuration: # 指定mybatis主配置文件中的相关配置项
  7. map-underscore-to-camel-case: true

@Mapper 和 @MapperScan

@Mapper 标注Mapper接口
@MapperScan 标注与SpringBoot主程序上 ,扫描Mapper接口所在的包
两个注解只需要用一个注解形式就行

3、整合mybatis-plus(知识点比较多)

导入依赖

  1. <dependency>
  2. <groupId>org.mybatis.spring.boot</groupId>
  3. <artifactId>mybatis-spring-boot-starter</artifactId>
  4. <version>2.2.0</version>
  5. </dependency>

配置

  1. mybatis:
  2. #config-location: classpath:mybatis-config.xml
  3. mapper-locations: classpath:springdriud/mapper/*.xml
  4. configuration: # 指定mybatis主配置文件中的相关配置项
  5. # 开启了相关的配置之后可能不需要执行主配置文件只需要Mapper映射文件
  6. map-underscore-to-camel-case: true

image.png
image.png

Service层

  1. //这个IService<User> 是MP的最高Service类
  2. public interface UserService extends IService<User> {
  3. }
  4. @Service //第一个泛型值得是要操作哪个Mapper类 第二个泛型是指要返回的数据类型 有许多方法 自己看着重写
  5. public class UserServiceimpl extends ServiceImpl<UserMapper, User> implements UserService {
  6. }

此时Service的实现类就有众多方法可用

image.png
image.png
image.png
image.png

  1. //获取页
  2. Page<User> objectPage = new Page<>(3,3);
  3. Page<User> userPage = userMapper.selectPage(objectPage, null);
  4. //总记录数
  5. long total = userPage.getTotal();
  6. //当前页号
  7. long current = userPage.getCurrent();
  8. //当前页的记录条数
  9. long pages = userPage.getPages();
  10. //获取Page对象的里面包含的实体类对象
  11. List<User> records = userPage.getRecords();

地址与参数
image.png
rest风格的携带参数
image.png
image.png
重定向参数类 RedirectAttributes
image.png

4、NOSQL

1、整合Redis

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>

自动配置:
●RedisAutoConfiguration 自动配置类。RedisProperties 属性类 —> spring.redis.xxx是对redis的配置
●连接工厂是准备好的。LettuceConnectionConfiguration、JedisConnectionConfiguration
自动注入了RedisTemplate<Object, Object> : xxxTemplate;
●自动注入了StringRedisTemplate;k:v都是String
●key:value
●底层只要我们使用 StringRedisTemplate、RedisTemplate就可以操作redis

安装配置Redis https://www.cnblogs.com/guo126/p/12446304.html
一般使用 阿里云
配置本地无密码连接

  1. redis:
  2. url: redis://localhost:6379

redis://default:XXXX@X.X.X.X:6379,前提是学过redis,配置过
阿里云的
image.png

RedisTemplate与Lettuce

  1. @Autowired
  2. RedisTemplate redisTemplate;
  3. @Test
  4. void reids(){
  5. ValueOperations valueOperations = redisTemplate.opsForValue();
  6. valueOperations.set("hello","work");
  7. System.out.println(valueOperations.get("hello"));
  8. }

切换Jedis

  1. <dependency>
  2. <groupId>redis.clients</groupId>
  3. <artifactId>jedis</artifactId>
  4. </dependency>
  1. redis:
  2. url: redis://localhost:6379
  3. client-type: jedis
  4. # Lettuce也可以配置
  5. jedis:
  6. pool:
  7. max-active: 10
  1. @Autowired
  2. RedisConnectionFactory factory;
  3. @Test
  4. void cll(){
  5. //查看工厂
  6. System.out.println(factory.getClass());
  7. //class org.springframework.data.redis.connection.jedis.JedisConnectionFactory
  8. }

image.png

5、 单元测试

@Transactional 标注的测试注解方法会自动回滚
@DisplayName("方法名/类名")标注的测试方法起名
@BeforeEach @AfterEach被这两个注解修饰的测试(@Test可用可不用)方法在其他测试方法执行前/后必定执行一下 两个测试方法就执行两下
@BeforeAll@AfterAll测试单个方法时前后执行一下 测试整个测试类里面的所有测试方法时执行一次 注意修饰 **静态方法**
@Disabled全部方法运行时,被标注的此方法不运行
@Tag("2")加标签
@Timeout(value = 1,unit = TimeUnit._NANOSECONDS_)此方法运行时间超过便算作超时
@RepeatedTest(5)重复测试

简单断言

用来对单个值进行简单的验证。如:

| 方法

| 说明

| | —- | —- | | assertEquals

| 判断两个对象或两个原始类型是否相等

| | assertNotEquals

| 判断两个对象或两个原始类型是否不相等

| | assertSame

| 判断两个对象引用是否指向同一个对象

| | assertNotSame

| 判断两个对象引用是否指向不同的对象

| | assertTrue

| 判断给定的布尔值是否为 true

| | assertFalse | 判断给定的布尔值是否为 false

| | assertNull

| 判断给定的对象引用是否为 null

| | assertNotNull

| 判断给定的对象引用是否不为 null |

参数型测试

  1. //参数式测试
  2. @ParameterizedTest
  3. //赋值
  4. @ValueSource(ints={1,2,3})
  5. void test(int i){
  6. System.out.println(i);
  7. }
  8. @ParameterizedTest
  9. @DisplayName("把方法作为参数")
  10. @MethodSource("str")
  11. void mehtod(String str){
  12. System.out.println(str);
  13. // I
  14. // Love
  15. // You!!!
  16. }
  17. static Stream<String> str(){
  18. return Stream.of("I ","Love"," You!!!");
  19. }

6、指标监控

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-actuator</artifactId>
  4. </dependency>

http://localhost:8080/actuator/

image.png

后期自己再钻研先放在这里

7、原理解析

Profile功能

简单来说就是多环境切换,生产环境、测试环境

例子:
创建两个配置文件application-test.yaml代表测试环境
application-prop.yaml代表生产环境
application.properties中指定当前所使用的配置

  • application-test.yaml

    1. per.name: 测试环境张三
  • application-prop.yaml

    1. per.name: 生产环境张三
  • controller

    1. @Controller
    2. public class IndexController {
    3. @Value("${per.name:张三}")
    4. private String name;
    5. @ResponseBody
    6. @GetMapping("/")
    7. public String index(){
    8. return "Hello "+name;
    9. }
    10. }
  • application.properties

    1. spring.profiles.active=test

    输出:测试环境张三
    后者覆盖前者
    同名配置以指定精确的环境配置优先
    在打包之后指定
    image.png
    命令行的方式可以修改配置文件的任意值

Profile条件装配功能

@Profile注解
@Profile("test/prop") 标注与类或者方法上 如果这是test环境 标注了@Profile("test")的方法/类就生效

Profile分组

  1. #prod组
  2. spring.profiles.group.myprod[0]=prod1
  3. spring.profiles.group.myprod[1]=prod2
  4. # test组
  5. spring.profiles.group.mytest[0]=test1
  6. spring.profiles.group.mytest[1]=test2
  7. # 值定加载哪个配置文件组
  8. spring.profiles.active=mytest

外部化配置

  1. @Controller
  2. public class IndexController {
  3. //@Value("${per.name:张三}")
  4. @Value("${JAVA_HOME}")
  5. private String name;
  6. @ResponseBody
  7. @GetMapping("/")
  8. public String index(){
  9. //返回你好 D:\develop\jdk-13
  10. return "Hello "+name;
  11. }
  12. }
  1. @SpringBootApplication
  2. public class ProfileApplication {
  3. public static void main(String[] args) {
  4. ConfigurableApplicationContext run = SpringApplication.run(ProfileApplication.class, args);
  5. ConfigurableEnvironment environment = run.getEnvironment();
  6. //获取环境变量
  7. Map<String, Object> systemEnvironment = environment.getSystemEnvironment();
  8. System.out.println(systemEnvironment);
  9. System.out.println("======================");
  10. //获取系统当前属性
  11. MutablePropertySources sources = environment.getPropertySources();
  12. System.out.println(sources);
  13. }
  1. /*seconds (JVM running for 1.887)
  2. {USERDOMAIN_ROAMINGPROFILE=LAPTOP-4H9RKFJI,
  3. LOCALAPPDATA=C:\Users\还是人物经历\AppData\Local,
  4. PROCESSOR_LEVEL=25, USERDOMAIN=LAPTOP-4H9RKFJI,
  5. LOGONSERVER=\\LAPTOP-4H9RKFJI,
  6. JAVA_HOME=D:\develop\jdk-13,
  7. SESSIONNAME=Console,
  8. ALLUSERSPROFILE=C:\ProgramData,
  9. PROCESSOR_ARCHITECTURE=AMD64,
  10. PSModulePath=C:\Program Files\WindowsPowerShell\Modules;
  11. C:\Windows\system32\WindowsPowerShell\v1.0\Modules,
  12. SystemDrive=C:,
  13. OneDrive=C:\Users\还是人物经历\OneDrive,
  14. APPDATA=C:\Users\还是人物经历\AppData\Roaming,
  15. USERNAME=还是人物经历,
  16. ProgramFiles(x86)=C:\Program Files (x86),
  17. CommonProgramFiles=C:\Program Files\Common Files,
  18. Path=D:\Python\Scripts\;D:\Python\;C:\Program Files\Common Files\Oracle\Java\javapath;D:\develop\jdk-13\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;D:\1 下载默认位置\platform-tools;D:\Gohuanjing\bin;C:\Program Files\MySQL\MySQL Server 8.0\bin;".;D:\mysqlcc\mysql-connector-java-8.0.26\mysql-connector-java-8.0.26.jar";D:\JavaWeb\Maven\apache-maven-3.8.3\bin;D:\pandoc\;D:\JavaWeb\Redis-x64-5.0.14;C:\Users\还是人物经历\AppData\Local\Microsoft\WindowsApps;D:\band\;D:\html\Microsoft VS Code\bin;C:\Users\还是人物经历\go\bin, PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW, DriverData=C:\Windows\System32\Drivers\DriverData, OS=Windows_NT, classpath=.;D:\mysqlcc\mysql-connector-java-8.0.26\mysql-connector-java-8.0.26.jar, OneDriveConsumer=C:\Users\还是人物经历\OneDrive, COMPUTERNAME=LAPTOP-4H9RKFJI, GOPATH=C:\Users\还是人物经历\go, PROCESSOR_REVISION=5000, CommonProgramW6432=C:\Program Files\Common Files, GOROOT=D:\Gohuanjing, ComSpec=C:\Windows\system32\cmd.exe, ProgramData=C:\ProgramData, ProgramW6432=C:\Program Files, HOMEPATH=\Users\还是人物经历, SystemRoot=C:\Windows, TEMP=C:\Users\还是人~1\AppData\Local\Temp, HOMEDRIVE=C:, PROCESSOR_IDENTIFIER=AMD64 Family 25 Model 80 Stepping 0, AuthenticAMD, USERPROFILE=C:\Users\还是人物经历, TMP=C:\Users\还是人~1\AppData\Local\Temp, M2_HOME=D:\JavaWeb\Maven\apache-maven-3.8.3, CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files, ProgramFiles=C:\Program Files, PUBLIC=C:\Users\Public, NUMBER_OF_PROCESSORS=12, windir=C:\Windows, =::=::\, IDEA_INITIAL_DIRECTORY=D:\ijideaje\IntelliJ IDEA 2021.2.3\bin}
  19. ======================
  20. [MapPropertySource {name='server.ports'}, ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, StubPropertySource {name='servletConfigInitParams'}, ServletContextPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='Config resource 'class path resource [application-test.yaml]' via location 'optional:classpath:/''}, OriginTrackedMapPropertySource {name='Config resource 'class path resource [application.properties]' via location 'optional:classpath:/''}]
  21. */

配置文件的路径

  • 配置文件的根路径(resources)
  • 配置文件的根路径下config目录下
  • jar包当前目录
  • jar包目录下的config目录

优先级低的会覆盖优先级高的

自定义starter

第一步 创建一个空工程创建一个模块选择MAVEN
image.png
第二步 创建一个新模块,以SpringBoot初始化向导配置,不选择任何场景
image.png
image.png
第三步将没用的东西删除
image.png
image.png

主类

  1. /**
  2. * 默认不要放在容器中
  3. */
  4. public class HelloSrvice {
  5. //也可以有一个构造
  6. @Autowired
  7. HelloServiceProperties properties;
  8. public String hello(String name){
  9. return properties.getPrefix()+name+properties.getSuffix();
  10. }
  11. public void setProperties(HelloServiceProperties properties) {
  12. this.properties = properties;
  13. }
  14. }

主类的属性配置类

  1. //该配置类进行绑定
  2. @ConfigurationProperties("wjl.hello")
  3. public class HelloServiceProperties {
  4. private String prefix;
  5. private String suffix;
  6. //生成GET SET
  7. public String getPrefix() {return prefix;}
  8. public void setPrefix(String prefix) {this.prefix = prefix;}
  9. public String getSuffix() {return suffix;}
  10. public void setSuffix(String suffix) {this.suffix = suffix;}
  11. }

主类的自动配置类

  1. @Configuration
  2. //IOC容器中没有该类时配置这个配置类才起效
  3. @ConditionalOnMissingBean(HelloSrvice.class)
  4. //HelloSrvice的配置类进行属性绑定放在容器中
  5. @EnableConfigurationProperties(HelloServiceProperties.class)
  6. public class HelloServiceAutoConfiguration {
  7. //放组件
  8. @Bean
  9. public HelloSrvice helloSrvice(){
  10. HelloSrvice helloSrvice = new HelloSrvice();
  11. return helloSrvice;
  12. }
  13. }

第四步创建一个META-INF文件夹及下面的spring.factories文件

  1. #项目一旦启动要加载哪个自动配置类?
  2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  3. com.wjl.HelloServiceAutoConfiguration

第五步 先打包安装有主程序的
image.png

第六步 创建一个测试项目
image.png