Spring 的 核心 是 提供 了 一个 容器( container), 通常 称为 Spring 应用 上下文( Spring application context), 它们 会 创建 和 管理 应用 组件。 这些 组件 也可以 称为 bean, 会在 Spring 应用 上下 文中 装配 在一起, 从而 形成 一个 完整 的 应用 程序。 这就 像 砖块、 砂浆、 木材、 管道 和 电线 组合 在一起, 形成 一 栋 房子 似的。
将 bean 装配 在一起 的 行为 是 通过 一种 基于 依赖 注入( dependency injection, DI) 的 模式 实现 的。 此时, 组件 不会 再去 创建 它 所 依赖 的 组件 并 管理 它们 的 生命 周期, 而是通过Spring application context( 容器) 来 创建 和 维护 所有 的 组件, 并将 其 注入 到 需要 它们 的 bean 中。 通常, 这是 通过 构造 器 参数 和 属性 访问 方法 来 实现 的。
只有 在必 要的 时候 才 使用 显 式 配置。 因为 Spring XML 配置 是一 种 过时 的 方式, 所以 我们 主要 关注 Spring 基于 Java 的 配置。
Spring MVC 的 核心 是 控制器( controller) 的 理念。 控制器 是 处理 请求 并以 某种 方式 进行 信息 响应 的 类。 在 面向 浏览器 的 应用 中, 控制器 会 填充 可选 的 数据 模型 并将 请求 传递 给 一个 视图, 以便 于 生成 返回 给 浏览器 的 HTML。
视图控制器(Thymeleaf视图)
视图控制器:控制器非常简单, 不需要填充模型Model或处理输入。好处:不需要编写标注含@Controller注解的控制器类。
对于 没有 模型数据 和 逻辑处理 的 HTTP GET 请求, 可以 使用 视图控制器。
package tacos.web;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");//urlPath:request请求路径, home:视图名称
}
}
模板缓存
默认 情况下, 模板 只有 在 第一次 使用 的 时候 解析 一次, 解析 的 结果 会被 后续 的 请求 所 使用。
在开发时关闭模板缓存,在应用程序配置文件application.properties中添加以下代码:
spring.thymeleaf.cache=false
开发时创建数据库架构和插入基础数据
Spring Boot 应用启动时将会基于数据库执行以下路径文件中的SQL。
“src/main/resources/schema.sql" //创建数据库架构
同时还会执行名为data.sql文件中的SQL。
"src/main/resources/data.sql" //插入基础数据,用于测试
JPA插入初始数据
@SpringBootApplication
public class TacoCloudApplication {
public static void main(String[] args) {
SpringApplication.run(TacoCloudApplication.class, args);
}
//程序启动之前执行,初始化数据库,输入基础数据
@Bean
public CommandLineRunner dataLoader(IngredientRepository repo) {
return new CommandLineRunner() {
@Override
public void run(String... args) throws Exception {
repo.save(new Ingredient("FLTO", "Flour Tortilla", Ingredient.Type.WRAP));
repo.save(new Ingredient("COTO", "Corn Tortilla", Ingredient.Type.WRAP));
repo.save(new Ingredient("GRBF", "Ground Beef", Ingredient.Type.PROTEIN));
repo.save(new Ingredient("CARN", "Carnitas", Ingredient.Type.PROTEIN));
repo.save(new Ingredient("TMTO", "Diced Tomatoes", Ingredient.Type.VEGGIES));
repo.save(new Ingredient("LETC", "Lettuce", Ingredient.Type.VEGGIES));
repo.save(new Ingredient("CHED", "Cheddar", Ingredient.Type.CHEESE));
repo.save(new Ingredient("JACK", "Monterrey Jack", Ingredient.Type.CHEESE));
repo.save(new Ingredient("SLSA", "Salsa", Ingredient.Type.SAUCE));
repo.save(new Ingredient("SRCR", "Sour Cream", Ingredient.Type.SAUCE));
}
};
}
}
获取当前登录用户信息
1.使用@AuthenticationPrincipal 注解 来 标注 方法。(提示:控件器中获取用户最佳方法)
@PostMapping
public String processOrder(@Valid Order order, Errors errors, SessionStatus sessionStatus,
@AuthenticationPrincipal User user){
if(errors.hasErrors()){
return "orderForm";
}
log.info("Order submitted: "+order);
order.setUser(user);
orderRepo.save(order);
sessionStatus.setComplete();
return "redirect:/";
}
2.使用 SecurityContextHolder 来 获取 安全 上下文;(非控件器的地方使用)
优势: 它可 以在 应用 程序 的 任何 地方 使用, 而 不仅仅 是在 控制器 的 处理器 方法 中。 这 使得 它 非常 适合 在 较低级 别的 代码 中 使用。
@GetMapping
public String showDesignForm(Model model){
//与表单对应的对象Taco: <form method="post" th:object="${design}">
//model.addAttribute("design",new Taco());
Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
User user=(User)authentication.getPrincipal();
model.addAttribute("user",user);
return "design";
}
3.注入 Authentication 对象 到 控制器 方法 中;
@PostMapping
public String processOrder(@Valid Order order, Errors errors, SessionStatus sessionStatus,
Authentication authentication){
if(errors.hasErrors()){
return "orderForm";
}
log.info("Order submitted: "+order);
User user=(User)authentication.getPrincipal();
order.setUser(user);
orderRepo.save(order);
sessionStatus.setComplete();
return "redirect:/";
}
4. 注入 Principal 对象 到 控制器 方法 中;
@PostMapping
public String processOrder(@Valid Order order, Errors errors, SessionStatus sessionStatus,
Principal principal){
if(errors.hasErrors()){
return "orderForm";
}
log.info("Order submitted: "+order);
User user=userRepository.findByUsername(principal.getName());
order.setUser(user);
orderRepo.save(order);
sessionStatus.setComplete();
return "redirect:/";
}