Spring Boot视图解析
视图解析:SpringBoot默认不支持 JSP,需要引入第三方模板引擎技术实现页面渲染。
thymeleaf使用:
引入Starter
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
自动配置好了thymeleaf
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ThymeleafProperties.class) @ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class }) @AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class }) public class ThymeleafAutoConfiguration { }
自动配好的策略
● 1、所有thymeleaf的配置值都在 ThymeleafProperties
● 2、配置好了 SpringTemplateEngine
● 3、配好了 ThymeleafViewResolver
● 4、我们只需要直接开发页面
public static final String DEFAULT_PREFIX = "classpath:/templates/"; public static final String DEFAULT_SUFFIX = ".html"; //xxx.html
页面开发:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1 th:text="${msg}">哈哈</h1> <h2> <a href="www.atguigu.com" th:href="${link}">去百度</a> <br/> <a href="www.atguigu.com" th:href="@{link}">去百度2</a> </h2> </body> </html>
构建后台管理系统
1、项目创建
thymeleaf、web-starter、devtools、lombok
2、静态资源处理
自动配置好,我们只需要把所有静态资源放到 static 文件夹下
3、路径构建
th:action="@{/login}"
4、模板抽取
th:insert/replace/include
5、页面跳转
@PostMapping("/login") public String main(User user, HttpSession session, Model model){ if(StringUtils.hasLength(user.getUserName()) && "123456".equals(user.getPassword())){ //把登陆成功的用户保存起来 session.setAttribute("loginUser",user); //登录成功重定向到main.html; 重定向防止表单重复提交 return "redirect:/main.html"; }else { model.addAttribute("msg","账号密码错误"); //回到登录页面 return "login"; } }
6、数据渲染
@GetMapping("/dynamic_table") public String dynamic_table(Model model){ //表格内容的遍历 List<User> users = Arrays.asList(new User("zhangsan", "123456"), new User("lisi", "123444"), new User("haha", "aaaaa"), new User("hehe ", "aaddd")); model.addAttribute("users",users); return "table/dynamic_table"; }
<table class="display table table-bordered" id="hidden-table-info"> <thead> <tr> <th>#</th> <th>用户名</th> <th>密码</th> </tr> </thead> <tbody> <tr class="gradeX" th:each="user,stats:${users}"> <td th:text="${stats.count}">Trident</td> <td th:text="${user.userName}">Internet</td> <td >[[${user.password}]]</td> </tr> </tbody> </table>
拦截器
HandlerInterceptor 接口
/** * 登录检查 * 1、配置好拦截器要拦截哪些请求 * 2、把这些配置放在容器中 */ @Slf4j public class LoginInterceptor implements HandlerInterceptor { /** * 目标方法执行之前 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestURI = request.getRequestURI(); log.info("preHandle拦截的请求路径是{}",requestURI); //登录检查逻辑 HttpSession session = request.getSession(); Object loginUser = session.getAttribute("loginUser"); if(loginUser != null){ //放行 return true; } //拦截住。未登录。跳转到登录页 request.setAttribute("msg","请先登录"); // re.sendRedirect("/"); request.getRequestDispatcher("/").forward(request,response); return false; } /** * 目标方法执行完成以后 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("postHandle执行{}",modelAndView); } /** * 页面渲染以后 * @param request * @param response * @param handler * @param ex * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("afterCompletion执行异常{}",ex); } }
2、配置拦截器
/** * 1、编写一个拦截器实现HandlerInterceptor接口 * 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors) * 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】 */ @Configuration public class AdminWebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") //所有请求都被拦截包括静态资源 .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求 } }
3、拦截器原理
1、根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】
2、先来顺序执行 所有拦截器的 preHandle方法
- 如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
- 如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion;
3、如果任何一个拦截器返回false。直接跳出不执行目标方法
4、所有拦截器都返回True。执行目标方法
5、倒序执行所有拦截器的postHandle方法。
6、前面的步骤有任何异常都会直接倒序触发 afterCompletion
7、页面成功渲染完成以后,也会倒序触发 afterCompletion
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
· 用 C# 插值字符串处理器写一个 sscanf