zoukankan      html  css  js  c++  java
  • springboot如何使用Thymeleaf和一些相关操作

    一、Thymeleaf简介

    Thymeleaf模板引擎主要用来做视图的展示。在springboot中默认支持thymeleaf,来替代原来ssm项目中的jsp。相较于jsp或其他的模板引擎,thymeleaf有如下特点:

    1)动静结合,thymeleaf 既可以在有后台交互的情况下运行,也可以在不与后台交互的情况下运行,方便前后端开发人员协同开发;

    2)多方言的支持,支持spring的标准方言,可以和springboot完美整合;

    二、Thymeleaf 使用

    1)在pom.xml文件中导入依赖;

    <!--        thymeleaf 模板依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>

    2) 在templates 目录下新建html页面,并加入thymeleaf的命名空间即可使用,Thymeleaf的命名空间为:xmlns:th="http://www.thymeleaf.org"

    3)引入命名空间之后,我们便可以使用thymeleaf的语法来展示数据;

    三、Thymeleaf 的语法

    Thyemeleaf的使用与jsp中的jstl和el表达式使用方法相似;

    Thymeleaf 表达式:用来取值,写在thymeleaf属性标签中。

    1) ${} :从域中取值,与el表达式类似;

    注意:当对象不存在的情况下,去获取对象的属性的话,会抛出异常;

    所以取值的时候,如果可能存在不存在的情况,需在对象后添加?判断对象是否存在;

    默认从request域中取值;

     常见的内置对象:

    1)session: 从session中获取值,类似jsp中的${session} == ${sessionScope}

    2)request:  httpServletRequest对象,${request} == ${pageContext.request.} 

    3)servletContext: ServletContext对象(application域)

    4)ctx : 上下文对象

    5)vars: 上下文变量

    6)local: 上下文的语言环境;

    2) *{} :选择变量表达式,需要配合th:object 属性标签一起使用。th:object可以绑定一个对象,*{属性名} 去获取绑定的对象的属性;

    3) #{} :获取国际化消息表达式;

    4) ~{} :代码块表达式,用来加载代码片段。 需配合 th:replace    th:insert     th:include 三个属性标签使用。类似 <%@include >;

    <body>
    <!--  insert 插入代码片段 ,包含最外层的标签  ~{模板名称::代码片段名称}
           </head><header>
                <div>头部导航栏</div>
                <ul>
                    <li>首页</li>
                    <li>文章</li>
                </ul>
            </header></div>
     -->
    <div th:insert="~{admin/common::head}">
        原来内容
    </div>
    
    <table>
        <tr>
            <td>序号</td>
            <td>用户名</td>
            <td>密码</td>
            <td>状态</td>
            <td>创建时间</td>
            <td>操作</td>
        </tr>
    <!--
           for(: xx)
            th:each="遍历出来的单个对象,iterStat(状态对象):要遍历的集合
    -->
        <tr th:object="${admin}" th:each="admin,iterStat:${adminPageInfo.list}">
            <td th:text="${iterStat.count}">序号</td>
            <td th:text="*{account}">用户名</td>
            <td th:text="*{password}">密码</td>
            <td>
    <!--          th:if  判断标签是否显示  -->
                <span th:if="*{status eq '0'}" style="color: coral">正常</span>
                <span th:if="*{status eq '1'}" style="color: red">注销</span>
            </td>
            <td th:text="*{createtime}">创建时间</td>
            <td>
    <!--          @{} 中链接地址需要传值的,通过在链接地址后面添加(key=value,key2=value2)的形式添加  -->
                <a th:href="@{/admin/edit(id=*{id})}">修改</a>
                <a th:href="@{/admin/delete(id=*{id})}">删除</a>
            </td>
        </tr>
    </table>
    
    <!--   替换内容,将引入的标签,替换掉现有标签 ,
         标签内容全部过来
           <footer>
                <div>版权所有,翻版必究</div>
            </footer>
     -->
    <div th:replace="~{admin/common::footerDiv}">
        <span>原来内容</span>
    </div>
    <!--   include 加载代码片段,
       不包含最外面的标签
             <div>
                <div>版权所有,翻版必究</div>
            </div>
         -->
    <div th:include="~{admin/common::footerDiv}">
        <span>原来内容</span>
    </div>
    </body>

    5) @{} :用来定义链接url地址。 比如 img src  a href <script > <link>等;

    四、Thymeleaf 属性标签

    编写在html标签上,替代原有的html标签属性,以达到动态展示数据。

    Thymelaef属性标签都是以th:开头。几乎涵盖了html标签中所有的属性。

    常见的标签:

    1) th:text :设置当前标签 的文本内容;

    2) th:value : 设置当前元素的value值;

    3) th:utext: 设置当前元素的html内容;

    4) th:title ;

    5) th:if :相当于<c:if> 用来做判断,如果表达式为false,则当前标签不显示;

    6) th:each :相当于<c:foreach> ,用来遍历数据;

    7) th:object : 声明变量,配合*{} 一起使用;

    8) th:fragment :用来定义一个代码片段,以供th:insert replace include 调用;

    9) th:insert : 将代码片段的所有内容(包含最外层的标签)插入到使用th:insert的html标签中。 <div th:insert=”~{}”></div>;

    10) th:replace : 将代码片段替换掉使用th:insert的html标签;

    11) th:include :将代码片段的内容(不包含最外层的标签)插入到使用th:insert的html标签中;

     

    五、Thymeleaf 函数

     Thymeleaf 函数写在表达式中,用来对数据进行数据格式话,字符串操作,集合操作等

     常用的函数:

    1) #strings: 字符串操作函数,跟java中string的api类似。 跟jstl el 表达式中 fn:函数标签类似。

    2) #dates :用来对日期进行操作,日期的格式化,获取日期的年月日,创建日期等

    3) #numbers: 用来对数值进行格式化,保留指定小数位,分隔符展示等

    4) #arrays 数组的操作,获取数组长度,是否包含某个元素等等。。。

    5) #maps: map集合操作

    6) 。。。

    测试代码:

    @Controller
    public class FunctionController {
    
        @GetMapping("/function")
        public String function(ModelMap modelMap){
            modelMap.put("name","james");
            modelMap.put("birthday",new Date());
            modelMap.put("arrayData",new String[]{"james","yao","yi"});
            return "function.html";
        }
    }

    function.html界面:

    <body>
         <h1>字符函数</h1>
         长度:<span><div th:text="${#strings.length(name)}"></div></span></br>
         首字母大写:<span><div th:text="${#strings.capitalize(name)}"></div></span></br>
         contains:<span><div th:text="${#strings.contains(name,'jam')}"></div></span></br>
         isEmpty:<span><div th:text="${#strings.isEmpty(name)}"></div></span></br>
         substring:<span><div th:text="${#strings.substring(name,0,2)}"></div></span></br>
    
    <h1>日期函数</h1>
         不格式化:<span th:text="${birthday}"></span><br/>
    format 指定格式:<span th:text="${#dates.format(birthday,'yyyy-MM-dd HH:mm:ss')}"></span><br/>
    format不指定格式:<span th:text="${#dates.format(birthday)}"></span><br/>
    year:<span th:text="${#dates.year(birthday)}"></span><br/>
    month:<span th:text="${#dates.month(birthday)}"></span><br/>
    dayOfWeekName:<span th:text="${#dates.dayOfWeekName(birthday)}"></span><br/>
    创建日期:<span th:text="${#dates.createToday()}"></span><br/>
    
    <h1>数值函数</h1>
    整数的格式化:<span th:text="${#numbers.formatInteger(100,5)}"></span><br/>
    <!--     COMMA 逗号  POINT.WHITESPACE 空格-->
    整数的格式化带分隔符:<span th:text="${#numbers.formatInteger(100,5,'COMMA')}"></span><br/>
    <!--     前两个参数与整数一样,第三个参数为保留的小数位,四舍五入-->
     小数的格式化:<span th:text="${#numbers.formatDecimal(100.94876,5,3)}"></span><br/>
     <!--     COMMA 逗号  POINT.WHITESPACE 空格-->
     小数的格式化带分隔符:<span th:text="${#numbers.formatDecimal(100.94876,3,3,'COMMA')}"></span><br/>
    百分比:<span th:text="${#numbers.formatPercent(0.783646,5,3)}"></span><br/>
    
    <h1>数组函数arrays</h1>
    数组长度:<span th:text="${#arrays.length(arrayData)}"></span><br/>
    是否为空:<span th:text="${#arrays.isEmpty(arrayData)}"></span><br/>
    是否包含:<span th:text="${#arrays.contains(arrayData,'james')}"></span><br/>
    
    <h1>list集合函数</h1>
    <!--     #lists #maps  #sets-->
    <!--<span th:text="${#lists.contains()}"></span>-->
    </body>

    测试结果为:

     

    六、Springboot中文件上传下载

    Springboot中文件上传下载与springmvc 完全一致。

    1)控制层代码:

    @Controller
    public class FileController {
    
        @GetMapping("/toUpload")
        public String toUpload(){
            return "upload.html";
        }
        @PostMapping("/upload")
        public String upload(MultipartFile multipartFile, ModelMap modelMap) throws IOException {
    //        if (multipartFile==null){ throw new FileNotFoundException(); }
            //获取文件名
            String filename = multipartFile.getOriginalFilename();
            // 日期 时间戳+用户ID
            //随机一个uuid名称
            String randName = UUID.randomUUID().toString();
            //a.png
            String fileType = filename.substring(filename.lastIndexOf("."));
            List<String> allowType= Arrays.asList(new String[]{".png",".jpg"});
            if (!allowType.contains(fileType)){//不允许的文件类型
                throw new NotAllowFileTypeException(" 001","上传的格式不支持:"+fileType);
            }
            Date date = new Date();
            SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
            String today=sdf.format(date);
            String path="E:/headpic/"+ today;
            //创建文件对象用来指定保存的位置和名称
            File file=new File(path,randName+fileType);
            //如果父目录不存在,创建
            if (!file.getParentFile().exists()){
                file.getParentFile().mkdirs();
            }
            //将文件保存到对应的目录
            multipartFile.transferTo(file);
            modelMap.put("filePath",today+"/"+randName+fileType);
            modelMap.put("fileName",randName+fileType);
            return "upload.html";
        };
    
        @GetMapping("/download")
        public ResponseEntity<byte[]> download(String fielName,String filePath) throws IOException {
            File file=new File("E:/headpic/",filePath);
            if(!file.exists()|| !file.isFile()){
                throw new FileNotFoundException("未找到文件:"+filePath);
            }
            HttpHeaders httpHeaders=new HttpHeaders();
            //设为返回的数据类型为二进制流
            httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            //设置浏览器以附件形式打开下载
            httpHeaders.setContentDispositionFormData("attachment",fielName);
            byte[] bytes = FileCopyUtils.copyToByteArray(file);
            return new ResponseEntity<>(bytes,httpHeaders, HttpStatus.OK);
        }
    }

    2)后台upload.html页面代码为:

    <body>
    <form th:action="@{/upload}" method="post" enctype="multipart/form-data">
        请选择文件:<input type="file" name="multipartFile">
        <input type="submit" value="上传">
    </form>
    <a th:href="@{/download(fileName=*{fileName},filePath=*{filePath})}" th:text="${'点击下载'+fileName}"></a>
    </body>

    3)要想实现文件的上传和下载,必须要配置资源映射;

    /**
     * springmvc相关配置类
     * WebMvcConfigurer 用来配置springmvc的配置项
     */
    @Configuration//配置类注解
    public class WebConfig implements WebMvcConfigurer {
        /**
         * 配置资源映射,相当于xml中的 <resource></resource>
         * @param registry
         */
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry
                    .addResourceHandler("/headpic/**")//配置请求地址
                    .addResourceLocations("file:E:/headpic/");//配置资源目录
        }
    }

    4)最后我们的界面是这样的;

    七、Springboot全局异常处理

    Spring3.2之后,可以通过@ControllerAdvice+@ExceptionHandler 这两个注解来实现全局的异常处理。

    @ControllerAdvice 加载类上面;

    @ExceptionHandler 添加在异常处理的方法上面;

    步骤:

    1)写一个全局异常处理的类,并添加@ControllerAdvice注解;

    2)写对应异常处理的方法,并在方法上添加@ExceptionHandler注解;

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        /**
         * @ExceptionHandler:指定处理特定异常,当项目发生指定的异常时,便会进入此方法
         * @param e
         * @return
         */
        @ExceptionHandler(FileNotFoundException.class)
        public Object handlerException(FileNotFoundException e){
            String message = e.getMessage();
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("error/fileNotFound.html");
            modelAndView.addObject("msg",message);
            return modelAndView;
        }
        @ExceptionHandler(Exception.class)
        public ModelAndView handlerException(Exception e){
            String message = e.getMessage();
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("error/fileNotFound.html");
            modelAndView.addObject("msg",message);
            return modelAndView;
        }
    }

    3)写一个自定义异常的NotAllowFileTypeException.java类;

    /**
     * 自定义异常
     */
    public class NotAllowFileTypeException extends RuntimeException{
        private String code;
        public NotAllowFileTypeException(String message, String code){
            super(message);
            this.code=code;
        }
        public String getCode() {
            return code;
        }
        public void setCode(String code) {
            this.code = code;
        }
    }

    4)fileNotFound.html页面;

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>文件找不到</title>
    </head>
    <body>
    <h1>您查找的文件不存在</h1>
    <div th:text="${msg}"></div>
    </body>
    </html>

    5)我们现在先测试第一种情况,抛FileNotFoundException 的异常,是一个文件找不到的异常,我们还是在上一个文件上传下载的页面中来测试;

    ①、我们的方法时,先上传图片,然后再去那个文件夹中把所有图片删掉即可;

    点击链接下载,正常情况下,是可以下载的,但是

    由于我们把文件夹中的图片删除了,文件夹里面就没有图片了,就会走fileNotFound.html页面;抛出异常;

    结果就是这样的:

    ②我们再测试一个文件类型不对的异常,使用普通的异常Exception,当我们上传.png,.jpg以外格式的图片时,就会抛出异常;

    点击上传,

    八、Springboot中的拦截器

    1)配置拦截器

    /**
     * springmvc相关配置类
     * WebMvcConfigurer 用来配置springmvc的配置项
     */
    @Configuration//配置类注解
    public class WebConfig implements WebMvcConfigurer {
        /**
         * 配置springmvc拦截器
         * @param registry
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor())//添加拦截器对象
                    .addPathPatterns("/**")//指定需要拦截的地址
                    .excludePathPatterns("/admin/login","/admin/toLogin","/headpic/**")//指定放行的请求
                    .order(1);//指定顺序
        }
    }

    2)登录拦截;

    控制层:

    //跳转到登录页面
        @RequestMapping("/toLogin")
        public String toLogin(){
            return "/admin/login.html";
        }
        @PostMapping("/login")
        public String login(TAdmin tAdmin, HttpSession session,ModelMap modelMap){
            TAdmin tAdmin1=adminService.selectByAccount(tAdmin.getAccount());
            if (tAdmin1==null||!tAdmin.getPassword().equals(tAdmin1.getPassword())){
               //回传登录信息
                modelMap.put("admin",tAdmin);
                modelMap.put("msg","用户名密码不正确");
                return "/admin/login.html";
            }
            //将对象放session域中
            session.setAttribute("admin",tAdmin1);
            return "/admin/detail.html";
        }

    登录拦截器LoginInterceptor,java;

    public class LoginInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            TAdmin admin = (TAdmin) request.getSession().getAttribute("admin");
            if (admin!=null){
                return true;
            }
            response.sendRedirect(request.getContextPath()+"/admin/toLogin");
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
        }
    }

    这样,拦截器的话,差不多就可以了;

  • 相关阅读:
    思维导图
    第九周学习
    java连接数据库执行SQL并把查询到的数据保存到磁盘
    火狐浏览器安装firebug和firepath插件方法(离线)
    selenium自动化测试资源整理(含所有版本chrome、chromedriver、firefox下载链接)
    Jenkins调度Selenium脚本不能打开浏览器解决办法
    selenium如何操作HTML5的画布canvas上的元素
    Java中如何使用非强制类型转换把字符串转换成int类型
    自动化测试如何使用driver.findElements去操作页面元素
    Jmeter响应数据中文乱码
  • 原文地址:https://www.cnblogs.com/xie-qi/p/13270055.html
Copyright © 2011-2022 走看看