文章目录
- 第三章、SpringMVC其他应用
- 一、关联对象赋值
- 二、日期类型转换
- 三、解决中文乱码
- 1、Web应用的中文乱码由来
- 2、中文乱码的配置
- 四、响应输出结果
- 1、响应中产生结果
- 2、@ResponseBody
- 3、ModelAndView
- 4、ModelAndView对象核心用法
- 五、SpringMVC整合Freemarker
- 1、pom.xml引入依赖
- 2、启用Freemarker模板引擎
- 3、配置Freemarker参数
- 4、代码演示
第三章、SpringMVC其他应用
一、关联对象赋值
面向对象设计
复杂内容表单
代码演示
在com.ql.springmvc.entity包下新增Delivery实体类
package com.ql.springmvc.entity;
public class Delivery {
private String name;
private String address;
private String mobile;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
@Override
public String toString() {
return "Delivery{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
", mobile='" + mobile + '\'' +
'}';
}
}
然后在Form实体类中关联,注意,引用对象比在当前类中实例化,才能保证赋值的成功。
package com.ql.springmvc.entity;
import java.util.List;
public class Form {
private String name;
private String course;
private List<Integer> purpose;
private Delivery delivery = new Delivery();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = course;
}
public List<Integer> getPurpose() {
return purpose;
}
public void setPurpose(List<Integer> purpose) {
this.purpose = purpose;
}
public Delivery getDelivery() {
return delivery;
}
public void setDelivery(Delivery delivery) {
this.delivery = delivery;
}
@Override
public String toString() {
return "Form{" +
"name='" + name + '\'' +
", course='" + course + '\'' +
", purpose=" + purpose +
", delivery=" + delivery +
'}';
}
}
修改form.html表单内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<h2>学员调查问卷</h2>
<form action="./apply" method="post">
<h3>您的姓名</h3>
<input name="name" >
<h3>您正在学习的技术方向</h3>
<select name="course">
<option value="java">Java</option>
<option value="h5">HTML5</option>
<option value="php">PHP</option>
<option value="python">Python</option>
</select>
<div>
<h3>您学习的目的:</h3>
<input type="checkbox" name="purpose" value="1">就业找工作
<input type="checkbox" name="purpose" value="2">工作要求
<input type="checkbox" name="purpose" value="3">兴趣爱好
<input type="checkbox" name="purpose" value="4">其他
</div>
<h3>收货人</h3>
<input name="delivery.name">
<h3>联系电话</h3>
<input name="delivery.mobile">
<h3>收货地址</h3>
<input name="delivery.address">
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
用实体类接受参数
@PostMapping("/apply")
@ResponseBody
public String apply(Form form){
System.out.println(form);
return "SUCCESS";
}
运行提交表单
二、日期类型转换
修改index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/um/p" method="post">
用户名<input name="username"><br>
密码<input name="password"><br>
创建时间<input name="createTime"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
修改接受方法为,接受日期格式参数时,参数前面需要加@DateTimeFormat注解并指定格式,不然无法接受参数。
@PostMapping("/p")
@ResponseBody
public String postMapping(String username, String password, @DateTimeFormat(pattern = "yyyy-MM-dd") Date createTime){
System.out.println(username+":"+password+"["+createTime+"]");
return "This is post method";
}
运行提交表单
如果接受类型改成实体类
修改实体类User,接受日期格式参数时,参数前面需要加@DateTimeFormat注解并指定格式,不然无法接受参数。
package com.ql.springmvc.entity;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
public class User {
private String username;
private Long password;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date createTime;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Long getPassword() {
return password;
}
public void setPassword(Long password) {
this.password = password;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password=" + password +
", createTime=" + createTime +
'}';
}
}
修改接受方法
@PostMapping("/p")
@ResponseBody
public String postMapping(User user){
System.out.println(user);
return "This is post method";
}
运行提交表单
全局时间参数转换器
如果每个日期格式参数前都加@DateTimeFormat实属有些麻烦,因此可以引入全局的默认时间参数转换器
在com.ql.springmvc.converter包下创建日期转换器类
package com.ql.springmvc.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyDateConverter implements Converter<String, Date> {
@Override
public Date convert(String s) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = sdf.parse(s);
return date;
} catch (ParseException e) {
return null;
}
}
}
在applicationContext.xml文件中配置下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--
context:component-scan 标签作用
在Spring IOC初始化过程中,自动创建并管理com.ql及子包中拥有以下注解的对象。
@Repository
@Service
@Controller
@Component
-->
<context:component-scan base-package="com.ql.springmvc"/>
<!--启用Spring MVC的注解开发模式-->
<mvc:annotation-driven conversion-service="conversionService"/>
<!--将图片/JS/CSS等静态资源排除在外,可提高执行效率-->
<mvc:default-servlet-handler/>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.ql.springmvc.converter.MyDateConverter"/>
</set>
</property>
</bean>
</beans>
修改URLMappingController类中的getMapping方法
@RequestMapping(value = "/g", method = RequestMethod.GET) //作用在方法上,默认不再区分get/post请求
@ResponseBody
public String getMapping(@RequestParam("manager_name") String managerName, Date createTime){
System.out.println("managerName:"+managerName);
System.out.println("managerName:"+createTime);
return "This is get method";
}
运行,在浏览器地址栏中输入http://localhost:8080/um/g?manager_name=lily&createTime=2022-07-20
注意:
一旦加入了全局时间参数转换器,即使时间参数前面加了@DateTimeFormat注解,SpringMVC还是优先使用转换器类实现转换工作,所以全局时间参数转换器和@DateTimeFormat注解只能二者选其一。如果使用全局时间参数转换器,出现多个时间格式参数,就在转换器类中加格式判断处理。
三、解决中文乱码
1、Web应用的中文乱码由来
Tomcat默认使用字符集ISO-8859-1,属于西欧字符集。
解决乱码的核心思路将ISO-8859-1转换为UTF-8。
Controller中请求与相应都需要设置UTF-8字符集。
2、中文乱码的配置
Get请求乱码 - server.xml增加URIEncoding属性。
打开在tomcat安装目录的conf文件夹下的server.xml配置文件,找到如下配置,添加URIEncoding="UTF-8"属性。(注:在tomcat 8.0以后版本URIEncoding属性默认为UTF-8)
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>
Post请求乱码 - web.xml配置CharacterEncodingFilter
打开web.xml,添加配置
<filter>
<filter-name>characterFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Response响应乱码 - Spring配置StringHttpMessageConverter
修改applicationContext.xml文件的mvc:annotation-driven标签为
<!--启用Spring MVC的注解开发模式-->
<mvc:annotation-driven conversion-service="conversionService">
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<!--response.setContentType("text/html;charset=utf-8")-->
<value>text/html;charset=utf-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
四、响应输出结果
1、响应中产生结果
@ResponseBody - 产生响应文本
ModelAndView - 利用模板引擎渲染输出
2、@ResponseBody
@ResponseBody直接产生响应体的数据,过程不涉及任何视图。
@ResponseBody可产生标准字符串/JSON/XML等格式数据。
@ResponseBody被StringHttpMessageConverter所影响。
3、ModelAndView
ModelAndView对象是指“模型(数据)与视图(界面)”对象。
通过ModelAndView可将包含数据对象与模板引擎进行绑定。
SpringMVC中默认的View是JSP,也可以配置其他模板引擎。
代码演示
给URLMappingController类新增一个方法
@GetMapping("/view")
public ModelAndView showView(Integer userId){
ModelAndView modelAndView = new ModelAndView("/view.jsp");
User user = new User();
if(userId == 1){
user.setUsername("lily");
}else if(userId == 2){
user.setUsername("smith");
}
modelAndView.addObject("user", user);
return modelAndView;
}
在webapp下新增view.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>I'm view page</h1>
<hr>
<h2>Username:${user.username}</h2>
</body>
</html>
运行,在浏览器地址栏输入http://localhost:8080/um/view?userId=2
4、ModelAndView对象核心用法
modelAndView.addObject()方法设置的属性默认存放在当前请求中。
默认ModelAndView使用请求转发(forward)至页面。
重定向使用new ModelAndView(“redirect:/index.jsp”)
修改URLMappingController的showView方法
@GetMapping("/view")
public ModelAndView showView(Integer userId){
ModelAndView modelAndView = new ModelAndView("redirect:/view.jsp");
User user = new User();
if(userId == 1){
user.setUsername("lily");
}else if(userId == 2){
user.setUsername("smith");
}
modelAndView.addObject("user", user);
return modelAndView;
}
重新运行,在浏览器地址栏再次输入http://localhost:8080/um/view?userId=2
重定向后重新打开了一个请求,上一个请求的参数(username)也不会传过来。
String与ModelMap实现跟返回ModelAndView类似功能
Controller方法返回String的情况
1、方法被@ResponseBody描述,SpringMVC直接响应String字符串本身。
2、方法不存在@ResponseBody,则SpringMVC处理String指代的视图(页面)
修改URLMappingController的showView方法
@GetMapping("/view")
public String showView(Integer userId, ModelMap modelMap){
User user = new User();
if(userId == 1){
user.setUsername("lily");
}else if(userId == 2){
user.setUsername("smith");
}
modelMap.addAttribute("user", user);
return "/view.jsp";
}
运行测试,结果跟返回ModelAndView一样。
注:如果不需要返回数据的话,ModelMap参数可以省略。
五、SpringMVC整合Freemarker
1、pom.xml引入依赖
2、启用Freemarker模板引擎
3、配置Freemarker参数
4、代码演示
打开pom.xml文件,引入依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
打开applicationContext.xml添加配置
<bean id="ViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="contentType" value="text/html;charset=utf-8"/>
<property name="suffix" value=".ftl"/>
</bean>
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl"/>
<property name="freemarkerSettings">
<props>
<prop key="defaultEncoding">UTF-8</prop>
</props>
</property>
</bean>
在com.ql.springmvc.controller包下创建FreemarkerController类
package com.ql.springmvc.controller;
import com.ql.springmvc.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/fm")
public class FreemarkerController {
@GetMapping("/test")
public ModelAndView showTest(){
ModelAndView modelAndView = new ModelAndView("/test");
User user = new User();
user.setUsername("andy");
modelAndView.addObject("user", user);
return modelAndView;
}
}
在src/main/webapp/WEB-INF/ftl目录下创建test.ftl
<h1>${user.username}</h1>
运行tomcat,在浏览器地址栏中输入http://localhost:8080/fm/test