1. SpringMVC控制器业务操作
在SpringMVC第二节中我们了解到mvc控制器处理页面url请求返回响应视图,除了这些操作外,控制器还需要处理更重要的业务,如:接收前台页面传递的参数、绑定数据到页面、返回json数据、文件上传、文件下载等业务操作。
1.1.参数接收
1.1.1. 配置请求编码过滤器
SpringMVC框架本身没有处理请求编码,在前台参数接收Post请求的时候,可能会出现编码乱码的问题,而Spring框架为我们提供了一个请求编码过滤器,我们只需要在web.xml中配置一个请求编码过滤器即可:
web.xml中配置UTF-8编码如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置post请求编码乱码处理过滤器-->
<filter>
<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
1.1.2. 参数接收方式
GET接收方式:
① 使用方法的形参接收:注意形参要和请求参数一致;
@Controller
@RequestMapping(value = "/paramController", method = RequestMethod.GET)
public class ParamRecCotroller {
/**
* 参数接收方式一:使用形参接收,前台get请求传入的参数名和方法接收的参数名保持一致
* @param username
* @param age
*/
@RequestMapping("/insert")
public void insert(String username, Integer age){
System.out.println(username);
System.out.println(age);
}
}
前台get参数传递方式:
http://localhost:8080/paramController/insert?username=”青海”&age=21
获取到的参数信息:

② 如果形参名称和前台传入的参数名不一致,需要使用@RequestParam(value=”前台参数名”)进行映射对应;
@Controller
@RequestMapping(value = "/paramController", method = RequestMethod.GET)
public class ParamRecCotroller {
/**
* 参数接收方式二:前台get传递的参数url与方法形参某个参数不一致,需要使用@@RequestParam(value = "前台参数名")
* @param username
* @param age
*/
@RequestMapping("/insert")
public void insert(@RequestParam(value = "name") String username, Integer age){
System.out.println(username);
System.out.println(age);
}
}
前台get参数传递方式:
http://localhost:8080/paramController/insert?name=”青海”&age=21
获取到的参数信息:

③ 直接使用一个Domain对象接收前台参数,会根据Domain中的属性来进行匹配装值;
@Controller
@RequestMapping(value = "/paramController", method = RequestMethod.GET)
public class ParamRecCotroller {
/**
* 参数接收方式三:直接使用一个Domain对象来接收前台参数,每个前台参数必须和User里面的属性名保持一致(前台参数直接映射属性),
* 不然无法获取对应的参数值,而且必须保证User内有一个无参数的构造器
* @param user
*/
@RequestMapping("/insert")
public void insert(User user){
System.out.println(user);
}
}
对应Domain中的User类:
public class User {
private String username;
private Integer age;
private String password;
public User() {
}
public User(String username, Integer age, String password) {
this.username = username;
this.age = age;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
", password='" + password + '\'' +
'}';
}
}
前台get参数传递方式:
http://localhost:8080/paramController/insert?username=”青海”&age=21&password= 3454
获取到的参数信息:

④ 使用原始的HttpServletRequest来获取请求参数信息;
@Controller
@RequestMapping(value = "/paramController", method = RequestMethod.GET)
public class ParamRecCotroller {
/**
* 参数接收方式四:直接使用HttpServletRequest获取
* @param request
*/
@RequestMapping("/insert")
public void insert(HttpServletRequest request){
String username = request.getParameter("username");
Integer age = Integer.valueOf(request.getParameter("age"));
String pwd = request.getParameter("pwd");
System.out.println(username);
System.out.println(age);
System.out.println(pwd);
}
}
前台get参数传递方式:
http://localhost:8080/paramController/insert?username=”青海”&age=21&pwd= 3454
获取到的参数信息:

⑤ Restful风格请求参数传递:直接在映射地址上使用{id}占位符,id表示传递的参数名,方法接收时对方法的形参使用@PathVariable(“id”),这里面的id应该和映射地址上的id名称保持一致;
@Controller
@RequestMapping(value = "/paramController", method = RequestMethod.GET)
public class ParamRecCotroller {
/**
* 参数接收方式四:前台请求地址中包含id参数信息,使用restful风格映射对应相同的提取参数
* 注意:前台参数名称必须与restful风格的参数一一对应,名称一致
* @param idVal
*/
@RequestMapping("/insert/{id}")
public void getUserById(@PathVariable(value = "id") Integer idVal){
System.out.println(idVal);
}
}
前台get参数传递方式:
http://localhost:8080/paramController/insert/5
获取到的参数信息:

1.2.数据传递
简单地说,就是使用SpringMVC中Controller向前台页面传递数据。使用Controller进行数据传递的方式主要有四种传递方式:
① 通过ModelAndView对象传递
@Controller
@RequestMapping("/dataController")
public class DataTransController {
/**
* 页面展示返回数据方式一:通过ModelAndView对象传递
* setViewName:返回一个结果视图
* addObject(name, value):可以通过name到对应的显示页面上去取数据,value表示显示的数据,
* 也可以传递对象来取值
* @return
*/
@RequestMapping("/getData")
public ModelAndView getDataRes(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", "随便写一个msg信息");
modelAndView.setViewName("/WEB-INF/views/dataView.jsp");
User user = new User("青海", 21, "2332");
modelAndView.addObject("user", user);
return modelAndView;
}
}
对应jsp页面取值:
<body>
${msg}<br/>
${user}<br/>
${user.username}<br/>
${user.age}<br/>
${user.password}<br/>
</body>
对应页面展示数据信息如下:

② 通过Model对象进行数据传递;
@Controller
@RequestMapping("/dataController")
public class DataTransController {
/**
* 页面展示返回数据方式二:通过Model对象传递
* return:返回一个结果视图
* addObject(name, value):可以通过name到对应的显示页面上去取数据,value表示显示的数据,
* 也可以传递对象来取值
* @return
*/
@RequestMapping("/getModel")
public String getModelRes(Model model){
model.addAttribute("msg", "Model对象的信息");
User user = new User("青海", 21, "2332");
model.addAttribute("user", user);
return "/WEB-INF/views/modelDataView.jsp";
}
}
对应jsp页面取值:
${msg}<br/>
${user}<br/>
${user.username}<br/>
${user.age}<br/>
${user.password}<br/>
对应页面展示数据信息如下:

③ 通过HttpServletRequest对象进行数据传递;
这种方式与Model对象传递方式类似,就是把参数换成HttpServletRequest对象,调用request.setAttribute(“msg”, 传递信息或者对象信息),这里就不再详细说明;
1.3.SpringMVC返回JSON数据
1.3.1. 实现方式
SpringMVC返回JSON数据格式需要导入Jackson的jar包,Jackson是解析JSON和XML的一个框架,简单易用,性能较高。
在项目中我们需要导入Jackson json的工具包,如下:
jackson-annotations-2.5.0.jar
jackson-core-2.5.0.jar
jackson-databind-2.5.0.jar

对应Controller实现方式:
@Controller
@RequestMapping("/jsonController")
public class JsonDemoController {
@RequestMapping("/getJson")
//加上@ResponseBody注解,返回值是通过JSON流的方式输出,Springmvc获取返回值,把对象自动转换为JSON
//然后通过response.getWriter().print(jsonString)输出在前台页面
@ResponseBody
public User getJsonUserData(){
User user = new User("青海", 21, "2332");
return user;
}
}
前台页面进行数据访问,访问地址:http://localhost:8080/jsonController/getJson

同样可以返回一个JSON集合,对应实现如下:
@Controller
@RequestMapping("/jsonController")
public class JsonDemoController {
@RequestMapping("/getJsonList")
@ResponseBody
public List<User> getJsonUserLstData(){
User user1 = new User("青海", 21, "2332");
User user2 = new User("俊杰", 23, "3306");
List<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
return userList;
}
}
前台页面进行数据访问,访问地址:http://localhost:8080/jsonController/getJsonList

1.3.2 日期型数据格式化
在处理日期Date类型的数据,如果后台不进行处理,那么默认返回的是时间戳的json日期格式:比如"birthday":1584261823034,此时需要在Domain的日期get属性方法上加上@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
/**
* 如果不加JsonFormat,默认返回的日期格式是时间戳:比如"birthday":1584261823034
* 需要在日期属性Date的getXXX()方法上加上自定义的日期格式@JsonFormat注解
* @return
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
public Date getBirthday() {
return birthday;
}
同理,在前台向后台传入字符串类型的Date数据时,需要在Domain的日期set属性方法上加上@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss"),后台才能接收到对应的Date参数并转换为日期数据到后台
/**
* 前台Get方式brithday以字符形式传递,需要加上@DateTimeFormat注解,
* 才能向后台传递Date类型数据
* @param birthday
*/
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
1.4.SpringMVC文件上传
SpringMvc自己没有实现文件上传,需要使用apache.commons.fileupload,需要导入文件上传相关的包:
com.springsource.org.apache.commons.fileupload-1.2.0.jar
com.springsource.org.apache.commons.io-1.4.0.jar

创建FileUploadController:
@Controller
@RequestMapping
public class FileUploadController {
//通过get请求,返回一个文件上传的jsp页面--结果视图
@RequestMapping(value = "/upload", method = RequestMethod.GET)
public String uploadFileGet(){
return "/WEB-INF/views/upload.jsp";
}
//文件上传的实现方法
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String uploadFilePost(String name, MultipartFile imge, HttpServletRequest request) throws IOException {
//获取上传文件的原始文件名
String oriFilename = imge.getOriginalFilename();
//获取文件名的后缀
String suffix = FilenameUtils.getExtension(oriFilename);
//产生一个随机的文件名
String uuidName = UUID.randomUUID().toString();
String fileName = uuidName + "." +suffix;
//获取文件的保存路径
String fileDir = request.getServletContext().getRealPath("/upload");
//使用File流来写入文件
File file = new File(fileDir, fileName);
//文件夹不存在,就创建一个保存路径
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
//IO流的拷贝
IOUtils.copy(imge.getInputStream(), new FileOutputStream(file));
return "/WEB-INF/views/upload.jsp";
}
}
准备jsp上传页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传页面</title>
</head>
<body>
<!—文件上传:必须写:enctype="multipart/form-data"—>
<form action="/upload" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="name"/><br/>
头像:<input type="file" name="imge"/><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
在applicationContext-mvc.xml中配置multipartResolver:
<!--配置文件上传解析器:id="multipartResolver",这个id不能乱写,还可以
设置一个maxUploadSize属性,就是上传文件的大小-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>2000000000</value>
</property>
</bean>
1.5. ViewResolver视图解析器
前面我们在Controller中返回ModelAndView结果视图时,如果是多个方法,需要一一返回结果视图,结果视图重复的内容还是需要写一遍,比较麻烦:

使用ViewResolver视图解析器配置返回的结果视图.jsp,可以设置视图路径的前后缀,该配置可以让我们写视图路径的时间更加简单。
具体需要在applicationContext-mvc.xml中配置如下内容:
<!--配置默认的视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
之后在Controller中即可简化视图访问的写法:
@Controller
@RequestMapping("/resolver")
public class ResolverController {
@RequestMapping("/demo1")
public ModelAndView demo1(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("resolver_demo1");
return modelAndView;
}
@RequestMapping("/demo2")
public ModelAndView demo2(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("resolver_demo2");
return modelAndView;
}
}
对应前台的页面访问:


来源:https://www.cnblogs.com/yif0118/p/12500419.html