1.请求传参方式
2.日期类型处理
3.处理中文乱码问题
4.文件上传
5.文件下载
6.拦截器的使用
一、请求传参方式
1.情况一
最传统的方式,方法参数中带入request,通过request.getParameter("参数名"),再封装到JavaBean中(不要求掌握).
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2019/12/31 0031
Time: 11:34
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<fieldset>
<legend>请求方式一</legend>
<form action="/request/test1" method="post">
用户名:<input type="text" name="username"/>
密码:<input type="text" name="password"/>
<input type="submit" value="提交">
</form>
</fieldset>
</body>
</html>
package com.xj._04_request;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
/**
* Created by Administrator on 2019/12/31 0031.
*/
@Controller
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/test1")
public ModelAndView test1(HttpServletRequest request){
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username);
System.out.println(password);
return null;
}
}
注:_03_response包下面的类中也有相同的方法test1,所以这里窄化了请求
2.情况二
简单类型参数和RequestParam注解(使用比较多).
一:如果请求参数和Controller方法的形参同名. 可以直接接收.
二:如果请求参数和Controller方法的形参不同名. 使用@RequestParam注解贴在形参前,设置对应的请求参数名称.
(1)同名
<fieldset>
<legend>请求方式二</legend>
<form action="/request/test2" method="post">
用户名:<input type="text" name="username"/>
密码:<input type="text" name="password"/>
<input type="submit" value="提交">
</form>
</fieldset>
@RequestMapping("/test2")
public ModelAndView test2(String username,String password){
System.out.println(username);
System.out.println(password);
return null;
}
注:简单数据类型的参数,可以直接使用方法的形参来接收,基于同名匹配原则。如果请求参数和Controller方法的形参不同名,接收不到数据,显示的都是null
(2)不同名
@RequestMapping("/test2")
public ModelAndView test2(@RequestParam("username") String Myname,
@RequestParam("password") String Mypwd){
System.out.println(Myname);
System.out.println(Mypwd);
return null;
}
@RequestParam注解可以指定形参获取请求参数中哪个请求参数的值。凡是标注了 @RequestParam注解的属性,请求时就必须要传递请求参数。否则会报错
解决方法:加上默认的值
defaultValue:当没有该请求参数时,SpringMVC给请求参数的默认值
3.情况三
对象传参,能够自动把请求参数封装到声明在形参上的对象中,此时请求参数必须和对象的属性同名(使用比较多).
新建一个Employee类
@Setter@Getter
@ToString
public class Employee {
private String username;
private String password;
}
<fieldset>
<legend>请求方式三</legend>
<form action="/request/test3" method="post">
用户名:<input type="text" name="username"/>
密码:<input type="text" name="password"/>
<input type="submit" value="提交">
</form>
</fieldset>
@RequestMapping("/test3")
public ModelAndView test3(Employee employee){
System.out.println(employee);
return null;
}
可以使用对象作为方法的形参,同时接收前台的多个请求参数,SpringMVC会基于同名匹配,将请求参数的值注入对应的对象中的属性中
注意:此时,SpringMVC会将对象参数直接放入request的作用域中,名称为类型首字母小写
新建一个前台界面
${employee}
@RequestMapping("/test3")
public ModelAndView test3(Employee employee){
System.out.println(employee);
ModelAndView mv = new ModelAndView();
mv.setViewName("request/request");
return mv;
}
如果想改变key值,可以使用@ModelAttribute
@ModelAttribute作用如下:
1、设置请求参数绑定到Model对象中并传到视图页面的key名.
2、将方法返回值或请求参数绑定到Model对象中并传到视图页面,设置key名.
4.情况四
数组和List集合类型参数.
(1)接收数组类型参数
<fieldset>
<legend>请求方式四</legend>
<form action="/request/test4" method="post">
<input type="checkbox" name="id" value="1">
<input type="checkbox" name="id" value="2">
<input type="checkbox" name="id" value="3">
<input type="checkbox" name="id" value="4">
<input type="submit" value="提交">
</form>
</fieldset>
@RequestMapping("/test4")
public ModelAndView test4(String id[]){//对于参数名相同的多个请求参数,可以直接使用数组作为方法的形参接收
for(String i:id){
System.out.println(i);
}
return null;
}
(2)接收List类型参数
不能直接获取,只能通过对象封装List集合.
在Employee类中添加一条属性
private List<String> id;
@RequestMapping("/test4")//使用对象中的集合属性接收
public ModelAndView test4(Employee employee){
for(String i:employee.getId()){
System.out.println(i);
}
return null;
}
5.情况五
RESTful是一种软件架构风格,严格上说是一种编码风格,其充分利用 HTTP 协议本身语义从而提供了一组设计原则和约束条件。
主要用于客户端和服务器交互类的软件,该风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
在后台,RequestMapping标签后,可以用{参数名}方式传参,同时需要在形参前加注解@PathVarible,
@RequestMapping("/employee/{id}")
public ModelAndView delete(@PathVariable("id") Integer employeeId){
System.out.println(employeeId);
return null;
}
注:因为前面窄化请求路径,所以这里加上request
如果后面过个参数,可以继续添加
@RequestMapping("/employee/{id}/{deptId}")
public ModelAndView delete(@PathVariable("id") Integer employeeId,@PathVariable("deptId") Integer deptId){
System.out.println(employeeId);
System.out.println(deptId);
return null;
}
二、日期类型处理
浏览器传递String的时间格式到Controller中转换为Date类型:
(1)在Controller形参上添加上@DateTimeFormat(pattern="yyyy-MM-dd")
<fieldset>
<legend>传递日期类型</legend>
<form action="/request/test5" method="post">
<input type="input" name="birthday" />
<input type="submit" value="提交">
</form>
</fieldset>
@RequestMapping("/test5")
public ModelAndView test5(@DateTimeFormat(pattern = "yyyy-MM-dd") Date birthday){
System.out.println(birthday);
return null;
}
(2)在对象字段上添加上@DateTimeFormat(pattern="yyyy-MM-dd")
在实体类中添加一条属性
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
@RequestMapping("/test5")
public ModelAndView test5(Employee employee){
System.out.println(employee.getBirthday());
return null;
}
三、处理中文乱码问题
在web.xml中配置请求编码过滤器
<!--配置请求编码过滤器-->
<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>
<!--设置request作用域强制使用上述设置的编码-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<!--设置response作用域强制使用上述设置的编码-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
四、文件上传
1、导包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
2、上传页面
<form action="/save" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"/><br/>
头像:<input type="file" name="file"/><br/>
<input type="submit" value="保存"/>
</form>
3、在mvc.xml中配置文件上传的解析器
<!--文件上传的解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1048576"/><!--设置文件上传的最大尺寸为1MB 1024*1024-->
</bean>
4、配置控制器
@Controller
public class UploadController {
@Autowired
private ServletContext servletContext;
@RequestMapping("/save")
public ModelAndView save(MultipartFile file,String username) throws Exception{
//把文件对象,以流的方式写出到img的文件夹中
String realPath = servletContext.getRealPath("/img");
//创建保存到服务器的文件的路径
String path = realPath+"/"+new Date().getTime()+file.getOriginalFilename();
File f = new File(path);
file.transferTo(f);
return null;
}
}
解决方法:在img文件夹下随便新建一个文件,然后重新编译
五、文件下载
1、在pom.xml中添加插件
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
2、下载页面(直接在上面传页面添加了)
<a href="/download?name=1577794385267jiushiliu.jpg">下载</a>
3、配置控制器
@Controller
public class DownloadController {
@Autowired
private ServletContext context;
@RequestMapping("/download")
public ModelAndView download(String name, HttpServletResponse response) throws Exception{
response.setContentType("application/x-msdownload");
response.setHeader("Content-Disposition","attachment;filename="+name);
//把文件对象,以流的方式写出到img的文件夹中
String realpath = context.getRealPath("/img");
Files.copy(Paths.get(realpath,name),response.getOutputStream());
return null;
}
}
六、拦截器的使用
Spring MVC 的拦截器类似于Servlet 开发中的过滤器Filter,用于对Controller进行预处理和后处理。
使用SpringMVC拦截器步骤:
1.定义拦截器类
1.1 实现接口 org.springframework.web.servlet.HandlerInterceptor
1.2 继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter
2.在applicationContext.xml中配置拦截器
拦截器方法的执行时机:
1):preHandle:控制器方法执行之前执行,返回结果为true表示放行,如果返回为false,表示拦截(可以做权限拦截,登录检查拦截).
2):postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息).
3):afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等)
(1)定义拦截器第一种方式
1、拦截器
public class MyIntercepter implements HandlerInterceptor {
@Override
//前置拦截
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor.preHandle...");
return false;
}
@Override
//后置拦截
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor.postHandle..");
}
@Override
//最终拦截(视图渲染之后)
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor.afterCompletion..");
}
}
2、控制器
@Controller
public class MyController {
@RequestMapping("/get")
public ModelAndView get() {
System.out.println("MyController.get...");
return null;
}
}
3、配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--拦截什么样的路径-->
<mvc:mapping path="/*"/>
<!--拦截的全限定名-->
<bean class="com.xj._06_intercepter.MyIntercepter"/>
</mvc:interceptor>
</mvc:interceptors>
没有打印控制器中的输出语句,如果将拦截器中的return语句,改为true,表示放行,则打印输出控制器中的输出语句
(2)定义拦截器的第二种方式
public class MyIntercepter2 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor2.preHandle");
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor2.postHandle");
super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor2.afterCompletion");
super.afterCompletion(request, response, handler, ex);
}
}
<mvc:interceptor>
<!--拦截什么样的路径-->
<mvc:mapping path="/*"/>
<!--拦截的全限定名-->
<bean class="com.xj._06_intercepter.MyIntercepter2"/>
</mvc:interceptor>
如果在控制器中添加窄化请求,改变url的访问路径
两个拦截器都没有拦截
原因:
/* : 表示拦截所有的一级路径
/** : 表示拦截任意多级路径
将拦截器1的拦截路径改为/**
在控制器中添加一个方法,假如不想拦截这个路径
@RequestMapping("/list")
public ModelAndView list(){
System.out.println("MyController.list...");
return null;
}
get被拦截
list没有被拦截