在yaml配置文件中能配置的东西,都存在一个固有的规律:
大量的自动配置类xxxAutoConfiguration
里面自动装配了一些默认的属性,然后这些属性是从对应的xxxProperties
类中获取的,xxxProperties
文件又通过@ConfigurationProperties
注解与yaml文件绑定,所有在配置文件(yaml)中能配置的属性都在xxxProperties
文件中封装着,所以如果想要自定义属性,只需要按照规则在yaml文件中配置即可。xxxxAutoConfigurartion
:自动配置类;给容器中添加组件xxxxProperties
:封装配置文件中相关属性;
PS:可以通过debug=true
来查看哪些配置生效
ConditionalOn
:spring底层注解,根据不同条件,来判断当前配置或类是否生效
springboot Web开发
要解决的问题:
- 导入静态资源…
- 首页
- jsp,模板引擎Thymeleaf
- 装配扩展SpringMVC
- 增删改查
- 拦截器
- 国际化!
静态资源
打开WebMvcAutoConfiguration.class
//添加资源处理器
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//如果有自定义配置,则默认值失效
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
//webjars下的资源都可以被识别
if (!registry.hasMappingForPattern("/webjars/**")) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(
new String[]{"/webjars/** 可以等价于"}).addResourceLocations(
///webjars/** 可以等价于classpath:/META-INF/resources/webjars/
new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(
this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(
new String[]{staticPathPattern}).addResourceLocations(
WebMvcAutoConfiguration.getResourceLocations(
//getStaticLocations方法获取静态资源路径
this.resourceProperties.getStaticLocations())).setCachePeriod(
this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
}
点进getStaticLocations
里面有四个可以存放静态资源的路径
总结:
1.springboot可以用以下方式处理静态资源:
- webjars
localhost:8080/webjars/
- 根目录下:public,static,resource,/** 这四个路径映射到
localhost:8080/
2.优先级 resource>static(默认)>public
首页如何定制
静态资源默认路径下的index.html即首页
模板引擎
PS:在templates目录下的所有页面,只能通过controller来跳转
,这个需要模板引擎的支持 thymeleaf
需要使用thymeleaf时,只需要导入依赖,把html放入templates目录下即可
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
thymeleaf基本语法
https://fanlychie.github.io/post/thymeleaf.html#5-%E9%81%8D%E5%8E%86
MVC配置原理
SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的;如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
如果我们要扩展springmvc
,我们要做的就是编写一个@Configuration
注解类,并且类型要为WebMvcConfigurer
,还不能标注@EnableWebMvc
注解;
那么为什么不能标注@EnableWebMvc
注解?
这个注解就是导入了一个类: DelegatingwebMvcConfiguration
:从容器中获取所有的webmvcconfig
;
而DelegatingwebMvcConfiguratio
继承了WebMvcConfigurationSupport
类
而在WebMvc的自动装配类中:
没有WebMvcConfigurationSupport
此类时条件成立,自动装配生效,即如果加上@EnableWebMvc
注解等于加入了此类,会让自动装配失效。
开始web开发
准备工作:
引入lombok,lombok会自动帮我们生成
getter、setter
和equals
方法/**
* 部门表
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Department {
private Integer id;
private String departmentName;
}
```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) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.department = department;
//默认的创建日期
this.birthday = new Date();
} }
- 模拟数据库中的数据,并给出curd方法
```java
/**
* 员工dao
*/
@Repository
public class EmployeeDao {
//模拟数据库中的数据
private static Map<Integer, Employee> employeeMap = null;
//员工有所属的部门
@Autowired
private DepartmentDao departmentDao;
static {
//创建一个部门表
employeeMap = new HashMap<Integer, Employee>();
employeeMap.put(1001,new Employee(1001,"AA","A123456@qq.com",0,new Department(101,"教学部")));
employeeMap.put(1002,new Employee(1002,"BB","B123456@qq.com",1,new Department(102,"市场部")));
employeeMap.put(1003,new Employee(1003,"CC","C123456@qq.com",0,new Department(103,"教研部")));
employeeMap.put(1004,new Employee(1004,"DD","D123456@qq.com",1,new Department(104,"运营部")));
employeeMap.put(1005,new Employee(1005,"EE","E123456@qq.com",0,new Department(105,"后勤部")));
}
//主键自增
private static Integer initId = 1006;
//增加一个员工
public void save(Employee employee){
if(employee.getId()==null){
employee.setId(initId);
}
employee.setDepartment(departmentDao.getDepartmentByID(employee.getDepartment().getId()));
employeeMap.put(employee.getId(),employee);
}
//查询全部员工
public Collection<Employee> getAll(){
return employeeMap.values();
}
//通过id查询员工
public Employee getEmployeeByID(Integer id){
return employeeMap.get(id);
}
//删除员工根据id
public void delete(Integer id){
employeeMap.remove(id);
}
}
/**
* 部门
*/
@Repository
public class DepartmentDao {
//模拟数据库中的数据
private static Map<Integer, Department> departmentMap = null;
static {
//创建一个部门表
departmentMap = new HashMap<Integer, Department>();
departmentMap.put(101,new Department(101,"教学部"));
departmentMap.put(102,new Department(102,"市场部"));
departmentMap.put(103,new Department(103,"教研部"));
departmentMap.put(104,new Department(104,"运营部"));
departmentMap.put(105,new Department(105,"后勤部"));
}
//获得所有部门信息
public Collection<Department> getDepartments(){
return departmentMap.values();
}
//通过id得到部门
public Department getDepartmentByID(Integer id){
return departmentMap.get(id);
}
}
控制层:
@Controller
public class IndexController {
@RequestMapping({"/","/index.html"})
public String index(){
return "index";
}
}
这种方式是可以的,但首页在根目录下,不建议使用这种方式访问根目录下的html文件,更建议使用mvc的扩展
@Configuration
public class MyConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
首页配置:注意点:所有静态资源都使用thymeleaf接管
页面国际化
首先,确保file encoding的编码方式都是utf-8
然后创建名为i18n的文件夹
在里面创建login.properties 和login_zh_CN.properties文件,此时idea会自动生成Resource Bundle ‘login’ 文件夹
点击idea下方的Resource Bundle,可以进行可视化配置
例如:
给首页配置完毕(其中的key,比如login.tip之类的名称可以任意)
然后配置国际化路径连接
这个修改的是MessageSourceAutoConfiguration
中的方法MessageSourceProperties
的basename
然后修改index.html,使用消息表达式#{}
修改后的页面:
我们的需求是点击首页中的中文显示中文,点击English显示英文
在WebMvcAutoConfiguration
中,有个解析器叫做localeResolver
(区域化解析器),
所以我们自定义一个配置
点击中文或English本质就是链接的跳转,所以在index.html中写上链接及语言
接收前端传回来的参数并处理
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
//获取请求中的语言参数
String lang = httpServletRequest.getParameter("l");
//如果没有就使用默认的
Locale locale = Locale.getDefault();
//如果请求的链接携带了国际化的参数
if(!StringUtils.isEmpty(lang)){
String[] split = lang.split("_");
//国家,地区
locale = new Locale(split[0],split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
此时,最重要的来了:要将我们自己的配置类装进spring容器,用Bean注解,且方法名一定要是**localeResolver**
,不然会失效