在yaml配置文件中能配置的东西,都存在一个固有的规律:
大量的自动配置类xxxAutoConfiguration里面自动装配了一些默认的属性,然后这些属性是从对应的xxxProperties类中获取的,xxxProperties文件又通过@ConfigurationProperties注解与yaml文件绑定,所有在配置文件(yaml)中能配置的属性都在xxxProperties文件中封装着,所以如果想要自定义属性,只需要按照规则在yaml文件中配置即可。
xxxxAutoConfigurartion:自动配置类;给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
PS:可以通过debug=true来查看哪些配置生效

ConditionalOn:spring底层注解,根据不同条件,来判断当前配置或类是否生效

springboot Web开发

要解决的问题:

  • 导入静态资源…
  • 首页
  • jsp,模板引擎Thymeleaf
  • 装配扩展SpringMVC
  • 增删改查
  • 拦截器
  • 国际化!

静态资源

打开WebMvcAutoConfiguration.class

  1. //添加资源处理器
  2. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  3. //如果有自定义配置,则默认值失效
  4. if (!this.resourceProperties.isAddMappings()) {
  5. logger.debug("Default resource handling disabled");
  6. } else {
  7. Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
  8. CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
  9. //webjars下的资源都可以被识别
  10. if (!registry.hasMappingForPattern("/webjars/**")) {
  11. this.customizeResourceHandlerRegistration(registry.addResourceHandler(
  12. new String[]{"/webjars/** 可以等价于"}).addResourceLocations(
  13. ///webjars/** 可以等价于classpath:/META-INF/resources/webjars/
  14. new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(
  15. this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
  16. }
  17. String staticPathPattern = this.mvcProperties.getStaticPathPattern();
  18. if (!registry.hasMappingForPattern(staticPathPattern)) {
  19. this.customizeResourceHandlerRegistration(registry.addResourceHandler(
  20. new String[]{staticPathPattern}).addResourceLocations(
  21. WebMvcAutoConfiguration.getResourceLocations(
  22. //getStaticLocations方法获取静态资源路径
  23. this.resourceProperties.getStaticLocations())).setCachePeriod(
  24. this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
  25. }
  26. }
  27. }

点进getStaticLocations
image.png
里面有四个可以存放静态资源的路径

总结:
1.springboot可以用以下方式处理静态资源:

  • webjarslocalhost:8080/webjars/
  • 根目录下:public,static,resource,/** 这四个路径映射到localhost:8080/
  • image.png

2.优先级 resource>static(默认)>public

首页如何定制

image.png
静态资源默认路径下的index.html即首页

模板引擎

PS:在templates目录下的所有页面,只能通过controller来跳转
,这个需要模板引擎的支持 thymeleaf
需要使用thymeleaf时,只需要导入依赖,把html放入templates目录下即可image.png

  1. <dependency>
  2. <groupId>org.thymeleaf</groupId>
  3. <artifactId>thymeleaf-spring5</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.thymeleaf.extras</groupId>
  7. <artifactId>thymeleaf-extras-java8time</artifactId>
  8. </dependency>

thymeleaf基本语法

https://fanlychie.github.io/post/thymeleaf.html#5-%E9%81%8D%E5%8E%86

MVC配置原理

image.png
SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的;如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
如果我们要扩展springmvc,我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,还不能标注@EnableWebMvc注解;
image.png

那么为什么不能标注@EnableWebMvc注解?

这个注解就是导入了一个类: DelegatingwebMvcConfiguration:从容器中获取所有的webmvcconfig;
DelegatingwebMvcConfiguratio继承了WebMvcConfigurationSupport
image.png
而在WebMvc的自动装配类中:
image.png
没有WebMvcConfigurationSupport此类时条件成立,自动装配生效,即如果加上@EnableWebMvc注解等于加入了此类,会让自动装配失效。

开始web开发

准备工作:

  • 引入lombok,lombok会自动帮我们生成getter、setterequals方法

    1. /**
    2. * 部门表
    3. */
    4. @Data
    5. @AllArgsConstructor
    6. @NoArgsConstructor
    7. public class Department {
    8. private Integer id;
    9. private String departmentName;
    10. }

    ```java /**

    • 员工表 / @Data @NoArgsConstructor public class Employee { private Integer id; private String lastName; private String email; /*

      • 0:女 1:男 */ private Integer gender; private Department department; private Date birthday;

      public Employee(Integer id, String lastName, String email, Integer gender, Department department) {

      1. this.id = id;
      2. this.lastName = lastName;
      3. this.email = email;
      4. this.gender = gender;
      5. this.department = department;
      6. //默认的创建日期
      7. this.birthday = new Date();

      } }

  1. - 模拟数据库中的数据,并给出curd方法
  2. ```java
  3. /**
  4. * 员工dao
  5. */
  6. @Repository
  7. public class EmployeeDao {
  8. //模拟数据库中的数据
  9. private static Map<Integer, Employee> employeeMap = null;
  10. //员工有所属的部门
  11. @Autowired
  12. private DepartmentDao departmentDao;
  13. static {
  14. //创建一个部门表
  15. employeeMap = new HashMap<Integer, Employee>();
  16. employeeMap.put(1001,new Employee(1001,"AA","A123456@qq.com",0,new Department(101,"教学部")));
  17. employeeMap.put(1002,new Employee(1002,"BB","B123456@qq.com",1,new Department(102,"市场部")));
  18. employeeMap.put(1003,new Employee(1003,"CC","C123456@qq.com",0,new Department(103,"教研部")));
  19. employeeMap.put(1004,new Employee(1004,"DD","D123456@qq.com",1,new Department(104,"运营部")));
  20. employeeMap.put(1005,new Employee(1005,"EE","E123456@qq.com",0,new Department(105,"后勤部")));
  21. }
  22. //主键自增
  23. private static Integer initId = 1006;
  24. //增加一个员工
  25. public void save(Employee employee){
  26. if(employee.getId()==null){
  27. employee.setId(initId);
  28. }
  29. employee.setDepartment(departmentDao.getDepartmentByID(employee.getDepartment().getId()));
  30. employeeMap.put(employee.getId(),employee);
  31. }
  32. //查询全部员工
  33. public Collection<Employee> getAll(){
  34. return employeeMap.values();
  35. }
  36. //通过id查询员工
  37. public Employee getEmployeeByID(Integer id){
  38. return employeeMap.get(id);
  39. }
  40. //删除员工根据id
  41. public void delete(Integer id){
  42. employeeMap.remove(id);
  43. }
  44. }
  1. /**
  2. * 部门
  3. */
  4. @Repository
  5. public class DepartmentDao {
  6. //模拟数据库中的数据
  7. private static Map<Integer, Department> departmentMap = null;
  8. static {
  9. //创建一个部门表
  10. departmentMap = new HashMap<Integer, Department>();
  11. departmentMap.put(101,new Department(101,"教学部"));
  12. departmentMap.put(102,new Department(102,"市场部"));
  13. departmentMap.put(103,new Department(103,"教研部"));
  14. departmentMap.put(104,new Department(104,"运营部"));
  15. departmentMap.put(105,new Department(105,"后勤部"));
  16. }
  17. //获得所有部门信息
  18. public Collection<Department> getDepartments(){
  19. return departmentMap.values();
  20. }
  21. //通过id得到部门
  22. public Department getDepartmentByID(Integer id){
  23. return departmentMap.get(id);
  24. }
  25. }

控制层:

  1. @Controller
  2. public class IndexController {
  3. @RequestMapping({"/","/index.html"})
  4. public String index(){
  5. return "index";
  6. }
  7. }

这种方式是可以的,但首页在根目录下,不建议使用这种方式访问根目录下的html文件,更建议使用mvc的扩展

  1. @Configuration
  2. public class MyConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addViewControllers(ViewControllerRegistry registry) {
  5. registry.addViewController("/").setViewName("index");
  6. registry.addViewController("/index.html").setViewName("index");
  7. }
  8. }

首页配置:注意点:所有静态资源都使用thymeleaf接管

image.png
image.png

页面国际化

什么是页面国际化?
即页面的中英文切换

首先,确保file encoding的编码方式都是utf-8

image.png

然后创建名为i18n的文件夹

在里面创建login.properties 和login_zh_CN.properties文件,此时idea会自动生成Resource Bundle ‘login’ 文件夹
image.png
点击idea下方的Resource Bundle,可以进行可视化配置
image.png
例如:
image.png
给首页配置完毕(其中的key,比如login.tip之类的名称可以任意)
image.png

然后配置国际化路径连接

image.png
这个修改的是MessageSourceAutoConfiguration中的方法MessageSourcePropertiesbasename

然后修改index.html,使用消息表达式#{}

image.png
修改后的页面:

image.png

我们的需求是点击首页中的中文显示中文,点击English显示英文

WebMvcAutoConfiguration中,有个解析器叫做localeResolver(区域化解析器),
image.png
所以我们自定义一个配置
image.png
点击中文或English本质就是链接的跳转,所以在index.html中写上链接及语言
image.png
接收前端传回来的参数并处理

  1. public class MyLocaleResolver implements LocaleResolver {
  2. //解析请求
  3. @Override
  4. public Locale resolveLocale(HttpServletRequest httpServletRequest) {
  5. //获取请求中的语言参数
  6. String lang = httpServletRequest.getParameter("l");
  7. //如果没有就使用默认的
  8. Locale locale = Locale.getDefault();
  9. //如果请求的链接携带了国际化的参数
  10. if(!StringUtils.isEmpty(lang)){
  11. String[] split = lang.split("_");
  12. //国家,地区
  13. locale = new Locale(split[0],split[1]);
  14. }
  15. return locale;
  16. }
  17. @Override
  18. public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
  19. }
  20. }

此时,最重要的来了:要将我们自己的配置类装进spring容器,用Bean注解,且方法名一定要是**localeResolver**不然会失效
image.png