springboot 学习 —— springboot 2.x ,thymeleaf 自定义 select 标签

Posted 猎人在吃肉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot 学习 —— springboot 2.x ,thymeleaf 自定义 select 标签相关的知识,希望对你有一定的参考价值。

1、添加依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

2、注册自定义标签类

import java.util.HashSet;
import java.util.Set;
 
import org.springframework.stereotype.Component;
import org.thymeleaf.dialect.AbstractProcessorDialect;
import org.thymeleaf.processor.IProcessor;
import org.thymeleaf.standard.StandardDialect;
 
/**
 * 类说明:自定标签注册类
 */
@Component
public class CustomLabel extends AbstractProcessorDialect
 
	/**
	 * 定义方言名称
	 */
	private static final String NAME="系统自定义标签";
	
	/**
	 * 定义方言属性
	 */
	private static final String PREFIX="bm";

	protected CustomLabel() 
		super(NAME, PREFIX, StandardDialect.PROCESSOR_PRECEDENCE);
	
 
	@Override
	public Set<IProcessor> getProcessors(final String dialectPrefix) 
		final Set<IProcessor> processor=new HashSet<>();
		processor.add(new CustomLabelSelect(PREFIX));  // <bm:select>标签
		// 如果有多个标签时,在下面添加
		//processor.add(new CustomLabelSelect(PREFIX));   
		return processor;
	 

3、自定义标签实现类

import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.util.StrUtil;
import com.xxx.app.common.utils.SpringContextHolder;
import com.xxx.app.modules.service.SysDictService;
import com.xxx.app.modules.service.impl.SysDictServiceImpl;
import com.xxx.app.modules.vo.SysDictShowVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IModelFactory;
import org.thymeleaf.model.IOpenElementTag;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.AbstractElementTagProcessor;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import org.thymeleaf.standard.expression.Expression;
import org.thymeleaf.standard.expression.StandardExpressionParser;
import org.thymeleaf.templatemode.TemplateMode;
import org.unbescape.html.HtmlEscape;


/**
 * 类说明:自定义select标签,使用方法:
 * <pre>
 * <bm:select class="" id="testSelect" name="testSelect" dictType="字典类型" headerLabel="请选择" headerValue="" th:value="$xxx.xxx"></bm:select>
 * </pre>
 */
public class CustomLabelSelect extends AbstractElementTagProcessor 

    private static final String TAG_NAME  = "select";//标签名 select 这个玩意就是 自定义标签的 : select, 应该是可以定义多个标签
    private static final int PRECEDENCE = 1000;//优先级


    public CustomLabelSelect(String dialectPrefix) 
        super(TemplateMode.HTML, // 此处理器将仅应用于HTML模式
                dialectPrefix, // 要应用于名称的匹配前缀
                TAG_NAME, // 标签名称:匹配此名称的特定标签
                true, // 没有应用于标签名的前缀
                null, // 无属性名称:将通过标签名称匹配
                false, // 没有要应用于属性名称的前缀
                PRECEDENCE// 优先(内部方言自己的优先
        );
    

    @Override
    protected void doProcess(ITemplateContext context, IProcessableElementTag tag,
                             IElementTagStructureHandler structureHandler) 

        //1、创建模型
        IModelFactory modelFactory = context.getModelFactory();
        IModel model = modelFactory.createModel();

        //2、创建模型元素 <select>
        IOpenElementTag openElementTag = createModelElement(tag,modelFactory);
        model.add(openElementTag);//<select>

        // 3、组装 options
        List<String> options=createOptions(context,tag);
        model.add(modelFactory.createText(HtmlEscape.unescapeHtml(String.join("\\n", options))));

        //4、关闭</select>
        model.add(modelFactory.createCloseElementTag("select"));

        //5、替换前面的标签
        structureHandler.replaceWith(model, false);
    


    /**
     * 添加模型元素
     * @param tag
     * @param modelFactory
     * @return
     */
    private IOpenElementTag createModelElement(IProcessableElementTag tag, IModelFactory modelFactory) 
        String classValue = tag.getAttributeValue("class");
        String id = tag.getAttributeValue("id");
        String name = tag.getAttributeValue("name");
        String style = tag.getAttributeValue("style");
        String disabled = tag.getAttributeValue("disabled");
        IOpenElementTag openElementTag = modelFactory.createOpenElementTag("select", "class", classValue);
        if (!StringUtils.isEmpty(id)) 
            openElementTag=modelFactory.setAttribute(openElementTag, "id", id);
        
        if (!StringUtils.isEmpty(name)) 
            openElementTag=modelFactory.setAttribute(openElementTag, "name", name);
        
        if (!StringUtils.isEmpty(style)) 
            openElementTag=modelFactory.setAttribute(openElementTag, "style", style);
        
        if (!StringUtils.isEmpty(disabled)) 
            openElementTag=modelFactory.setAttribute(openElementTag, "disabled", disabled);
        
        return openElementTag;
    


    /**
     * 组装 options
     * @param context
     * @param tag
     * @return
     */
    private List<String> createOptions(ITemplateContext context,IProcessableElementTag tag)
        //1、select的option
        List<String> options=new ArrayList<>();
        
        //2、设置默认值
        String defaultHtml = addDefault(tag);
        if (StringUtils.isNotBlank(defaultHtml))
            options.add(0,defaultHtml);
        

        //3、根据字典类型获取数据,如果有value值,则默认选中
        String ptionHtml = getDictDateByType(tag,context);
        options.add(ptionHtml);
        return options;
    

    /**
     * 添加默认值
     * @param tag
     * @return
     */
    private String addDefault(IProcessableElementTag tag) 
        String headerLabel = tag.getAttributeValue("headerLabel");
        String headerValue = tag.getAttributeValue("headerValue");
        StringBuilder sb = new StringBuilder("");
        if (!StringUtils.isEmpty(headerLabel)) 
            sb.append("\\n<option value='" + headerValue + "' >");
            sb.append(headerLabel + "</option>");
        
        return sb.toString();
    

    /**
     * 根据字典类型获取数据
     * @param tag
     * @param context
     * @return
     */
    private String getDictDateByType(IProcessableElementTag tag, ITemplateContext context) 
    
    	// select 中增加了 dictType 属性,用其值 从缓存、、配置、或数据库 中获取数据。
        String dictType = tag.getAttributeValue("dictType");
        if (StringUtils.isEmpty(dictType)) 
            return "";
        
        String value = tag.getAttributeValue("th:value");
        Object executeExpression = null;
        if (!StringUtils.isEmpty(value)) 
            // 执行 th:value ,得到其值
            executeExpression = executeExpression(value, context);
        
        
        // 重点说明:
        // 这块是从缓存、配置文件 或者 数据库 等中,查询得到数据,用来组装 option 标签
        SysDictService sysDictService=SpringContextHolder.getBean(SysDictServiceImpl.class);
        List<SysDictShowVO> dicts =  sysDictService.getListByKey(StrUtil.trim(dictType));
        if (CollectionUtils.isEmpty(dicts)) 
            return "";
        

		// option 标签组装
        StringBuilder sb = new StringBuilder();
        for (int i = 0, len = dicts.size(); i < len; i++) 
            SysDictShowVO   sysDictShowVO = dicts.get(i);
            if (executeExpression != null && executeExpression.toString().equals(sysDictShowVO.getDictValue())) 
                sb.append("<option value='" +sysDictShowVO.getDictValue() + "' selected=\\"selected\\">");
             else 
                sb.append("<option value='" +sysDictShowVO.getDictValue() + "' >");
            
            sb.append(sysDictShowVO.getDictName() + "</option>\\n");
        
        return sb.toString();
    

    /**
     * 执行自定义标签中的表达式
     * @param value
     * @param context
     * @return
     */
    private Object executeExpression(String value, ITemplateContext context) 
        StandardExpressionParser parser = new StandardExpressionParser();
        Expression parseExpression = parser.parseExpression(context, value);
        Object execute = parseExpression.execute(context);
        return execute;
    

4、使用

<!--  没有 th:value ,与普通的select基本一样  -->
<bm:select   id="status" name="status" dictType="status_type" 
		 headerLabel="请选择" headerValue=""  class="form-control" ></bm:select>

<!--  如有 th:value 时,则可以选中option中与之匹配的值  -->
<bm:select   id="status" name="status" dictType="status_type" th:value="$ companys['status'] " 
		 headerLabel="请选择" headerValue=""  class="form-control" ></bm:select>

解析后的源代码:

5、转载

thymeleaf 自定义标签,解析表达式:https://blog.csdn.net/z793397795/article/details/97389063

以上是关于springboot 学习 —— springboot 2.x ,thymeleaf 自定义 select 标签的主要内容,如果未能解决你的问题,请参考以下文章

springboot学习笔记-5 springboot整合shiro

SpringBoot学习笔记.pdf,这个太全了!

Spring Boot学习笔记

springBoot 集成redis客户端傻瓜式流程

SpringBoot2.x,不看后悔系列,建议收藏

SpringBoot2.x,不看后悔系列,建议收藏