1 概述 表单一直是web程序用户交互的重要途径,通过单行文本、多行文本、单选按钮、复选框、下拉列表、日期等各种组件,向web程序提交各类信息。
本节课程将演示上述各Form组件的使用,及各组件的数据如何在视图层显示。
2 工程结构
pom.xml
<?xml version="1.0" encoding="UTF-8"?>4.0.0 org.springframework.boot spring-boot-starter-parent 2.1.6.RELEASE com.wangshenghua spring-thymeleaf-form 0.0.1-SNAPSHOT spring-thymeleaf-form Demo project for Spring Boot
<properties> <java.version>1.8</java.version> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> thymeleaf-extras-java8time可以让thymeleaf支持Java 8 的日期时间。运行效果图。
3 各组件关键知识点 3.1 单选按钮 单选按钮通常是多选一,应用场景最最常见如性别,要么是男,要么是女。那它是如何实现的呢?
模型层,也就是POJO使用String表示性别,如:
@NotNull(message = “请选择性别”) private String gender; 其次,在控制器层,要提供一个选项通过model对象传递到视图层。
这个选项是一个Map泛型,存储key/value数据。
final static Map<String, String> RADIO_GENDER = Collections.unmodifiableMap(new LinkedHashMap<String, String>() { private static final long serialVersionUID = 1L; { put(“男”, “男”); put(“女”, “女”); } }); 将选项添加到model的Attribute.
@GetMapping("/adduser") public String showAddUserForm(Model model) { User user = new User(); user.setId(userDao.getMaxId()); model.addAttribute(“user”, user); model.addAttribute(“radioItems”, RADIO_GENDER); return “add-user”; } 视图层收到控制传递过来的选项,如何展示呢?遍历!!!
性别 th:each对选项radioItems进行遍历,每次遍历将一项赋值给变量item。然后取item的key和value。这样表单中的数据便能通过控制器保存到模型层。那么模型层的性别如何在视图层显示呢?性别是String类型,不是数组,也不是List,也不是Map,因此同姓名一样采用下面的方式显示:
3.2 复选按钮 复选按钮使用场景也非常广,如投票、选择课程等。在Spring MVC中,复选功能实现也是要从模型层开始,如实现选择多门课程。
@NotNull @Size(min = 1, max = 5, message = “选择课程”) private String[] course; 课程在数据模型是以数组形式存储。这样的数据选项同单选按钮一样,由控制器提供,并通过model传递视图层。
final static Map<String, String> CHECK_COURSE = Collections.unmodifiableMap(new LinkedHashMap<String, String>() { private static final long serialVersionUID = 1L; { put(“Java程序设计”, “java”); put(“Spring”, “spring”); put(“MySQL”, “mysql”); put(“HTML”, “html”); } });
@GetMapping("/adduser") public String showAddUserForm(Model model) { User user = new User(); user.setId(userDao.getMaxId()); model.addAttribute(“user”, user); model.addAttribute(“checkItems”, CHECK_COURSE); return “add-user”; } 视图层又是如何显示控制器传递过来的多选复选框呢?
课程 同单选按钮一样,采用循环来显示各选项。这里的多选(复选)课程如何在详情或列表中显示呢?课程在数据模型是以数组的形式存储,因此显示要采用遍历数组的方式,如下:
3.3 下拉列表 下拉列表可以实现单选和多选功能,从表现形式来讲,比单选按钮、复选按钮更简单。可以实现单选按钮、复选按钮一样的功能。如果是单选,那么数据模型使用String类型即可。
@NotEmpty(message = “请选择故乡”) private String hometown; 如果是多选,那么数据模型使用数组类型。
@NotEmpty(message = “请选择兴趣爱好”) private String[] hobbies; 同样的,控制器需要提供选项通过model传递到视图层。
final static Map<String, String> SELECT_HOMETOWN = Collections.unmodifiableMap(new LinkedHashMap<String, String>() { private static final long serialVersionUID = 1L; { put(“郴州”, “郴州”); put(“耒阳”, “耒阳”); put(“广州”, “广州”); } });
final static Map<String, String> SELECT_HOBBIES = Collections.unmodifiableMap(new LinkedHashMap<String, String>() { private static final long serialVersionUID = 1L; { put(“打球”, “打球”); put(“听歌”, “听歌”); put(“玩游戏”, “玩游戏”); put(“写代码”, “写代码”); put(“吃烧烤”, “吃烧烤”); } });
@GetMapping("/adduser") public String showAddUserForm(Model model) { User user = new User(); user.setId(userDao.getMaxId()); model.addAttribute(“user”, user); model.addAttribute(“selectItems”, SELECT_HOMETOWN); model.addAttribute(“multipleItems”, SELECT_HOBBIES); return “add-user”; } 如你所断,视图层将采用循环的方法来展示这些选项:
故乡 --- 兴趣爱好 控制器传递过来的选项就是 select下拉列表的选项,因此在option标签循环也是你所预料的。那么视图层如何显示数据模型的单选和多选下拉列表呢?还是根据数据形式决定,数据、List则遍历,否则正常显示。
3.4 日期时间 日期时间也是使用非常多的组件,其重要性不言而喻。这里演示的是出生年月,它在数据模型是这样的:@NotNull @DateTimeFormat(pattern = “yyyy-MM-dd”) private LocalDate dateOfBirth; 确定了日期格式,中文格式。控制器不需要做什么。
表单视图层仅需要将input的type属性设置为datetime。
无需做其它操作,日期便能正确的保存到数据模型层。那在thymeleaf模板中,如何显示Java 8的日期时间呢?
4 log4j日志 Spring Boot中默认采用log4j管理日志,采用logback保存日志。Spring Boot 简化了日志管理程序,使用日志仅要3步。
第一步,在src/main/resources目录下添加日期配置文件logback.xml
<?xml version="1.0" encoding="UTF-8"?> <statusListener class="ch.qos.logback.core.status.NopStatusListener" /> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n </Pattern> </layout> </appender> <!-- 按照每天生成日志文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日志文件输出的文件名 --> <FileNamePattern>${LOG_HOME}/test-%d{yyyy-MM-dd}.log </FileNamePattern> <!--日志文件保留天数 --> <MaxHistory>30</MaxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> <!--日志文件最大的大小 --> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>2MB</MaxFileSize> </triggeringPolicy> </appender> <!-- 日志输出级别 --> <root level="DEBUG"> <appender-ref ref="STDOUT" /> <appender-ref ref="FILE" /> </root> <logger name="org.hibernate.type" level="TRACE" additivity="false"> <appender-ref ref="STDOUT" /> <appender-ref ref="FILE" /> </logger> 使用时将LOG_HOME属性的Value做相应的修改,使路径满足所在环境的路径。第二步,在需要使用日期的地方实例化一个Logger,如:
import org.slf4j.Logger; import org.slf4j.LoggerFactory;
@Controller public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);} 第三步,在需要输出日志的地方调用debug() info() error()等方式输出日志。
log.debug(“用户信息:”, user); log.info(“正常信息”); log.error(“错误”); 5 总结 本节课程使用Spring Boot和thymeleaf技术演示表单各特殊组件的用法,及log4j日志的使用。
学员们重点掌握单选按钮、复选按钮、下拉列表、日期时间等组件的使用。
本节课程源码已经上传到github,可以前往下载。