模板引擎–thymeleaf
- Springboot中不支持jsp,所以要进行视图跳转需要引入第三方模板引擎技术实现页面渲染。
https://www.thymeleaf.org/
- thymeleaf缺点:所有请求都需要经过controller处理,高并发场景下性能差。
基本语法
也可以在${}中进行数字运算,字符串拼接等。
使用thymeleaf
依赖引入
springboot具有对该模板的支持,在依赖中添加thymeleaf即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在thymeleaf的配置中可以见到,html页面需要存放在templates目录下,这里如mvc中的视图解析器
开发使用
编写html
使用thymeleaf,必须引入thymeleaf命名空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
html页面:(/templates/wel.html)
- 这里因为服务器没在运行,前端无法感知到model中是否有该变量,idea对其检查就会报错,不影响结果
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a>欢迎页</a>
<!--从域中取出msg-->
<span th:text="${msg}"/>
<h2>
<!--从域中取出list列表,赋给list,并输出-->
<div th:each="list:${lists}" th:text="${list}"></div>
</h2>
</body>
</html>
编写controller
@Controller
public class ThymeleafController {
@RequestMapping("test")
public String test(Model model){
List<String> list=new ArrayList<>();
list.add("Sunny");
list.add("Kobe");
list.add("Ketty");
model.addAttribute("lists",list);
model.addAttribute("msg","This is a message");
return "wel";
}
}
通过url不能直接访问静态资源,因为此时静态资源不在默认目录下。需要使用控制器匹配url,在返回值中指定静态资源的文件名称,并返回给视图解析器。视图解析器在利用前后缀匹配/templates/下的静态资源。
使用原生ServletApi,直接以参数形式传递即可
拦截器
首先编写拦截器类
public class myInteceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
Object attribute = session.getAttribute("loginUser");
if(attribute!=null){
return true;
}
request.setAttribute("msg","请先登录");
request.getRequestDispatcher("/").forward(request,response);
return false;
}
}
使用前置拦截器,从session中拿取并判断属性,用户未登录则返回false,并转发到登录页面
然后注册拦截器
@Configuration
public class myCfg implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new myInteceptor()).addPathPatterns("/main")
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**",
"/js/**","/aa/**");
}
}
使用registry的添加拦截器方法,将拦截器类转入参数,并添加匹配路径和不匹配路径
正常使用即可
文件上传
表单样式:
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data">
html文件存储位置:
Java代码:
@Controller
@Slf4j
public class FormController {
@GetMapping("/form")
public String form_layouts(){
return "form/form_layouts";
}
@PostMapping("upload")
public String upload(@RequestParam("email") String email,
@RequestParam("username") String username,
//MultipartFile封装文件的类型
@RequestPart("headerImg")MultipartFile Img,
//多个文件用数组表示
MultipartFile[] photos) throws IOException {
log.info(email+username);
//非空则有图片
if(!Img.isEmpty()){
//获得文件的名称,MultipartFile类的方法
String filename = Img.getOriginalFilename();
//调用上传方法,MultipartFile类的方法,JavaIO的file
Img.transferTo(new File("d:\\upload"+filename));
}
//数组有长度则有图片
if(photos.length>0){
for (MultipartFile photo : photos) {
String f = photo.getOriginalFilename();
photo.transferTo(new File("d:\\upload"+f));
}
}
return "main";
}
}
异常处理
处理异常经常返回4xx,5xx,在thymeleaf下可以使用对应文件进行处理
文件路径
控制器代码
@Controller
public class ErrorController {
@RequestMapping("text")
public String test(){
//抛出异常
int i=1/0;
return "login";
}
}
访问结果
Web三大组件的使用
使用三大组件需要先创建servlet、listener以及filter类,然后在config类中注册bean,并返回注册后的bean。
整体代码:
三大组件的创建-注意都是Javax下的类
@WebServlet("/servlet")
public class myServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet方法执行");
}
}
public class myListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("容器创建");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("容器销毁");
}
}
public class myFilter extends HttpFilter {
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("过滤器执行");
chain.doFilter(request,response);
}
}
三大组件的注册:
@Controller
public class webConfig {
@Bean
public ServletRegistrationBean servletRegistrationBean(){
ServletRegistrationBean registrationBean=new ServletRegistrationBean();
registrationBean.setServlet(new myServlet());
registrationBean.setUrlMappings(Arrays.asList("/servlet"));
return registrationBean;
}
@Bean
public FilterRegistrationBean doFilter(){
FilterRegistrationBean bean=new FilterRegistrationBean();
bean.setFilter(new myFilter());
bean.setUrlPatterns(Arrays.asList("/servlet"));
return bean;
}
@Bean
public ServletListenerRegistrationBean listenerRegistrationBean(){
ServletListenerRegistrationBean registrationBean =new ServletListenerRegistrationBean();
registrationBean.setListener(new myListener());
return registrationBean;
}
}
Servlet组件
servlet创建需要先继承HttpServlet类,按需重写方法。这里重写doGet方法
将Servlet映射到URL路径是为了让客户端能够通过URL访问到相应的Servlet,从而执行相应的业务逻辑。当客户端发送请求到服务器时,服务器会根据请求的URL路径来找到对应的Servlet进行处理。
@WebServlet("/servlet")
public class myServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet方法执行");
}
}
Servlet需要使用@WebServlet注解,并指定url
filter组件
这里重写的是doFilter方法,最后调用执行链继续执行
public class myFilter extends HttpFilter {
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("过滤器执行");
chain.doFilter(request,response);
}
}
listener组件
listener组件需要重写ServletContextListener,这里监听的是容器的创建和销毁
public class myListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("容器创建");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("容器销毁");
}
}
容器销毁方式:
注册
三大组件注册的逻辑基本相同。先创建返回相应注册类的方法,然后set
相应组件到bean中,并进行特定设置,如url。最后返回注册bean即可。
Servlet的注册
servlet需要指定相应的urlMapping,与组件创建时指定的mapping一直。
registrationBean.setUrlMappings(Arrays.asList("/servlet"));
filter的注册
filter的注册需要指定过滤地址,这里选则的是/servlet
bean.setUrlPatterns(Arrays.asList("/servlet"));
listener的注册
listener创建bean然后设置返回即可。
自定义嵌入web容器
- 首先引入需要的容器的相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
- 将原web容器排除
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
```