SpringMVC注解_@SessionAttributes
作用:将Model模型中的数据存到session域中
位置:类上方
@Controller @RequestMapping("/c4") // 将模型中的name数据保存到session中 @SessionAttributes("name") public class MyController4 { @RequestMapping("/t1") public String t1(Model model){ // model中保存name数据 model.addAttribute("name","北京大乱斗"); return "baizhan"; } @RequestMapping("/t2") public String t2(HttpSession session){ // 从session中获取name数据 System.out.println(session.getAttribute("name")); return "baizhan"; } }
SpringMVC注解_@ModelAttribute
作用1:设置指定方法在控制器其他方法前执行
位置:方法上方
@Controller @RequestMapping("/c5") public class MyController5 { @ModelAttribute public void before(){ System.out.println("前置方法"); } @RequestMapping("/t1") public String t1(){ System.out.println("t1"); return "baizhan"; } }
作用2:从Model模型中获取数据给参数赋值
位置:方法参数前
@Controller @RequestMapping("/c6") public class MyController6 { // 前置方法向Model中设置数据 @ModelAttribute public void before(Model model){ model.addAttribute("name","辛苦学堂"); } // 该参数不是从请求中获取,而是从Model中获取 @RequestMapping("/t1") public String t1(@ModelAttribute("name") String name){ System.out.println(name); return "baizhan"; } }
SpringMVC注解_RESTful风格支持
RESTful风格介绍
RESTful风格是一种URL路径的设计风格。在RESTful风格的URL路 径中,网络上的任意数据都可以看成一个资源,它可以是一段文 本、一张图片,也可以是一个Java对象。而每个资源都会占据一个 网络路径,无论对该资源进行增删改查,访问的路径是一致的。
传统URL:
查找id为1的学生:http://localhost:8080/student/findById?id=30
删除id为1的学生: http://localhost:8080/student/deleteById?id=30RESTful风格URL:查找id为30的学生: http://localhost:8080/student/30 删除id为30的学生: http://localhost:8080/student/30
那么如何区分对该资源是哪一种操作?通过请求方式不同,判断进 行的是什么操作。
之前我们学过两种请求方式,GET请求和POST请求,而访问 RESTful风格的URL一共有四种请求方式:
1、GET请求:查询操作
2、POST请求:新增操作
3、DELETE请求:删除操作
4、PUT请求:修改操作
RESTful风格URL:
查找id为30的学生: http://localhost:8080/student/30 GET方式请求
删除id为30的学生: http://localhost:8080/student/30 DELETE方式请求
RESTful风格的优点:
结构清晰、符合标准、易于理解、扩展方便。
Postman使用
默认情况下浏览器是无法发送DELETE请求和PUT请求的,我们可以 使用Postman工具发送这些请求。
1、双击安装包安装Postman
2、点击new-collection创建请求集合
3、添加请求
4、保存请求到集合,以后可以随时发送该请求
@PathVariable
作用:在RESTful风格的URL中获取占位符的值
位置:方法参数前
属性:
1、value:获取哪个占位符的值作为参数值,如果占位符和参数名相同,可以省略该属性。
@Controller @RequestMapping("/student") // 模拟学生的增删改查控制器 public class StudentController { // 路径中的{id}表示占位符,最后会封装到方法的参数中使用 // 删除学生 @RequestMapping(value = "/{id}",method = RequestMethod.DELETE) public String deleteStudent(@PathVariable("id") int id){ System.out.println("删除id为"+id+"的学生"); return "baizhan"; } // 如果占位符和参数名相同,可以省略 @PathVariable的value属性 // 根据id查询学生 @RequestMapping(value = "/{id}",method = RequestMethod.GET) public String findStudentById(@PathVariable int id){ System.out.println(id); System.out.println("根据id查询学生"); return "baizhan"; } // 新增学生 @RequestMapping(value = "/{id}",method = RequestMethod.POST) public String addStudent(@PathVariable int id, Student student){ System.out.println(id); System.out.println(student); System.out.println("新增学生"); return "baizhan"; } // 修改学生 @RequestMapping(value = "/{id}",method = RequestMethod.PUT) public String updateStudent(@PathVariable int id, Student student){ System.out.println(id); System.out.println(student); System.out.println("修改学生"); return "baizhan"; } }
访问方式:
新增学生:POST http://localhost:8080/student/1?name=辛苦学堂&sex=男
修改学生:PUT http://localhost:8080/student/1?name=辛苦学堂&sex=男
删除学生:DELETE http://localhost:8080/student/1
查询学生:GET http://localhost:8080/student/1
@PostMapping、@GetMapping、@PutMapping、 @DeleteMapping
作用:简化设置请求方式的@RequestMapping写法
位置:方法上方。
@Controller @RequestMapping("/student") public class StudentController { // 删除学生 @DeleteMapping("/{id}") public String deleteStudent(@PathVariable("id") int id){ System.out.println("删除id为"+id+"的学生"); return "baizhan"; } // 根据id查询学生 @GetMapping("/{id}") public String findStudentById(@PathVariable int id){ System.out.println(id); System.out.println("根据id查询学生"); return "baizhan"; } // 新增学生 @PostMapping("/{id}") public String addStudent(@PathVariable int id, Student student){ System.out.println(id); System.out.println(student); System.out.println("新增学生"); return "baizhan"; } // 修改学生 @PutMapping("/{id}") public String updateStudent(@PathVariable int id, Student student){ System.out.println(id); System.out.println(student); System.out.println("修改学生"); return "baizhan"; } }
HiddentHttpMethodFilter
由于浏览器form表单只支持GET与POST请求,而DELETE、PUT请 求并不支持,SpringMVC有一个过滤器,可以将浏览器的POST请求 改为指定的请求方式,发送给的控制器方法。
用法如下:
1、在web.xml中配置过滤器
<!-- 请求方式过滤器 --> <filter> <filter-name>httpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>httpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2、编写控制器方法
@Controller @RequestMapping("/c7") public class MyController7 { @DeleteMapping("/delete") public String testDelete(){ System.out.println("删除方法"); return "baizhan"; } @PutMapping("/put") public String testPut(){ System.out.println("修改方法"); return "baizhan"; } }
3、在jsp中编写表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>DELETE、PUT提交</title> </head> <body> <!-- 删除 --> <%-- 提交DELETE、PUT请求,表单必须提交方式为post --%> <%-- 表单中有一个隐藏域,name值为 _method,value值为提交方式 --%> <form action="/c7/delete" method="post"> <input type="hidden" name="_method" value="DELETE"> <input type="submit" value="删除"> </form> <hr/> <!-- 修改 --> <form action="/c7/put" method="post"> <input type="hidden" name="_method" value="PUT"> <input type="submit" value="修改"> </form> </body> </html>
SpringMVC注解_@ResponseBody
作用:方法返回的对象转换为JSON格式,并将JSON数据直接写入 到输出流中,使用此注解后不会再经过视图解析器。使用该注解可 以处理Ajax请求。
位置:方法上方或方法返回值前
1、编写jsp页面,发送ajax请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>ajax请求</title> <script src="/js/jquery-2.1.1.min.js"></script> <script> $(function () {$("#btn").click(function () { var name = $("#name").val(); var sex = $("#sex").val(); $.get("/c8/addStudent", {"name":name,"sex":sex},function (data){ console.log(data); }); }); }); </script> </head> <body> 姓名:<input id="name"/><br/> 性别:<input id="sex"/><br/> <input type="button" value="提交" id="btn"/> </body> </html>
2、由于jsp页面中引入jQuery的js文件,而SpringMVC会拦截所有 资源,造成jquery.js失效,需要在SpringMVC核心配置文件中放 行静态资源。
<!-- 放行静态资源 --> <mvc:default-servlet-handler />
3、编写结果实体类,该实体类会封装一个请求的结果
// 请求的结果对象 public class Result { private boolean flag; // 请求是否成功 private String message; // 请求提示信息 // 省略getter/setter/构造方法 }
4、编写控制器
@PostMapping("/addStudent") @ResponseBody public Result addStudent(String name, String sex) { // 输出接受到的参数,模拟添加学生 System.out.println(name+":"+sex); // 返回添加结果 Result result = new Result(true, "添加学生成功!"); return result; }
5、SpringMVC会将Result对象转为JSON格式写入输出流,而 SpringMVC默认使用的JSON转换器是jackson,需要在pom中添 加jackson依赖。
<!-- jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jacksondatabind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jacksonannotations</artifactId> <version>2.9.0</version> </dependency>
SpringMVC注解_@RestController
如果一个控制器类下的所有控制器方法都返回JSON格式数据且不进 行跳转,可以使用@RestController代替@Controller,此时每个方 法上的@ResponseBody都可以省略。
@RestController @RequestMapping("/c8") public class MyController8 { @PostMapping("/addStudent") public Result addStudent(String name, String sex) { // 输出接受到的参数,模拟添加学生 System.out.println(name+":"+sex); // 返回结果 Result result = new Result(true, "添加学生成功!"); return result; } }
静态资源映射
当在DispatcherServlet的<url-pattern> 中配置拦截 “/” 时,除了jsp文件 不会拦截以外,其他所有的请求都会经过前端控制器进行匹配。此 时静态资源例如css、js、jpg等就会被前端控制器拦截,导致不能访 问,出现404问题。想要正常映射静态资源共有三种方案:
配置静态资源筛查器
在SpringMVC的配置文件中配置 后,会在Spring容器中创建一个资源检查器,它对进入 DispatcherServlet的URL进行筛查,如果不是静态资源,才由 DispatcherServlet处理。
修改SpringMVC核心配置文件:
<mvc:default-servlet-handler/>
配置静态资源映射器
SpringMVC模块提供了静态资源映射器组件,通过 标签 配置静态资源映射器,配置后的路径不会由DispatcherServlet处 理。
修改SpringMVC核心配置文件:
<!--配置静态资源映射器--> <!-- mapping:配置请求的URL location:资源路径--> <mvc:resources mapping="/img/" location="/img/"/><mvc:resources mapping="/js/" location="/js/"/>
配置默认Servlet处理静态资源
在web.xml可以配置默认Servlet处理静态资源,该Servlet由tomcat 提供,它会直接访问静态资源不进行其他操作。这样就避免了使用 DispatcherServlet对静态资源的拦截:
修改web.xml:
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.png</url-pattern> </servlet-mapping>
SpringMVC注解_@RequestBody
作用:将请求中JSON格式的参数转为JAVA对象
位置:写在方法参数前
1、AJAX请求发送JSON格式的参数
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>ajax请求</title> <script src="/js/jquery2.1.1.min.js"></script> <script> $(function (){ $("#btn").click(function(){ var name=$("#name").val(); var sex=$("#sex").val(); var param = JSON.stringify({"name":name,"sex":sex}); $.ajax({ url:"/c8/addStudent2", contentType:"application/json", type:"post",data:param,success:function(data){ console.log(data); } }) }) }) </script> </head> <br> 姓名:<input id="name"><br /> 性别:<input id="sex"><br /> <input type="button" value="提交"id="btn"> </body> </html>
2、编写控制器
@PostMapping("/addStudent2") @ResponseBody public Result addStudent2(@RequestBody Student student) { System.out.println(student); // 返回添加结果 Result result = new Result(true, "添加学生成功!"); return result; }
SpringMVC文件上传_原生方式上传
上传是Web工程中很常见的功能,SpringMVC框架简化了文件上传 的代码,我们首先使用JAVAEE原生方式上传文件:
1、创建新的SpringMVC项目,在web.xml中将项目从2.3改为3.1, 即可默认开启el表达式
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/webapp_3_1.xsd" id="WebApp_ID" version="3.1">
2、编写上传表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>上传</title> </head> <body> <h3>文件上传</h3> <%-- 上传表单的提交方式必须是post --%> <%-- enctype属性为multipart/formdata,意思是不对表单数据进行编码 --%> <form action="/fileUpload" method="post" enctype="multipart/formdata"> <%-- 文件选择控件,类型是file,必须要有name属性--%> 选择文件:<input type="file"name="upload"/> <input type="submit" value="上传"/> </form> </body> </html>
3、接收请求体数据:
@RequestMapping("/fileUpload") public String upload(HttpServletRequest request) throws Exception { // 获取输入流 ServletInputStream is = request.getInputStream(); // 从输入流获取请求体数据 int i = 0; while ((i=is.read())!=-1){ System.out.println((char)i); } return "index"; }
接下来需要分析请求体中的文件项,并将数据写入磁盘,此时需要 借助文件上传工具
1、引入文件上传依赖:
<!-- 文件上传 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commonsfileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
2、编写控制器接收上传请求,控制器进行三步操作:
2.1 创建文件夹,存放上传文件。
2.2 分析请求体,找到上传文件数据。
2.3 将文件数据写入文件夹。
@RequestMapping("/fileUpload") public String upload(HttpServletRequest request) throws Exception { // 创建文件夹,存放上传文件 // 1.设置上传文件夹的真实路径 String realPath = request.getSession().getServletContext().getRealPath("/upload"); // 2.判断该目录是否存在,如果不存在,创建该目录 File file = new File(realPath); if(!file.exists()){ file.mkdirs(); } // 分析请求体,找到上传文件数据 // 1.创建磁盘文件工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); // 2.创建上传数据分析器对象 ServletFileUpload servletFileUpload = new ServletFileUpload(factory); // 3.利用分析器对象解析请求体,返回所有数据项 List<FileItem> fileItems = servletFileUpload.parseRequest(request); // 4.遍历所有数据,找到文件项(非表单项) for (FileItem fileItem:fileItems){ if(!fileItem.isFormField()){ // 将文件数据写入文件夹 // 1.获取文件名 String name = fileItem.getName(); // 2.将文件写入磁盘 fileItem.write(new File(file,name)); // 3.删除内存中的临时文件 fileItem.delete(); } } return "index"; }
SpringMVC文件上传_SpringMVC方式上传
SpringMVC使用框架提供的文件解析器对象,可以直接将请求体中 的文件数据转为MultipartFile对象,从而省略原生上传中分析请求体的步骤。
1、在SpringMVC核心配置文件配置文件解析器
<!-- 文件解析器对象,id名称必须是 multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 支持一次上传文件的总容量。单位:字节 100M = 100*1024*1024--> <property name="maxUploadSize" value="104857600"/> <!-- 文件名的编码方式--> <property name="defaultEncoding" value="utf-8"/> </bean>
2、创建JSP表单
<form action="/fileUpload2" method="post" enctype="multipart/form-data"> <input type="file" name="file"/> <input type="submit" value="上传"/> </form>
3、编写控制器接收上传请求
// MultipartFile参数名必须和JSP文件空间的name 属性一致 @RequestMapping("/fileUpload2") public String upload2(MultipartFile file,HttpServletRequest request) throws IOException { // 创建文件夹,存放上传文件 String realPath = request.getSession().getServletContext().getRealPath("/upload"); File dir = new File(realPath); if(!dir.exists()){ dir.mkdirs(); } // 将上传的数据写到文件夹的文件中 // 1.拿到上传的文件名 String filename = file.getOriginalFilename(); filename = UUID.randomUUID()+"_"+filename; // 2.创建空文件 File newFile = new File(dir,filename); // 3.将数据写入空文件中 file.transferTo(newFile); return "index"; }
SpringMVC文件上传_上传多文件
SpringMVC支持一次性上传多个文件,写法如下:
1、创建JSP表单
<form action="/fileUpload3" method="post" enctype="multipart/form-data"> 用户名:<input name="username"/> 文件1:<input type="file" name="files"/> 文件2:<input type="file" name="files"/> <input type="submit" value="上传"/> </form>
2、编写控制器接收上传请求
// 处理多文件上传,参数类型为MultipartFile数组,参数名和JSP文件控件的name属性一致 @RequestMapping("/fileUpload3") public String upload3(MultipartFile files[],String username,HttpServletRequest request) throws Exception { System.out.println(username); //1.设置上传文件保存的文件夹 String realPath =request.getSession().getServletContext().getRealPath("/upload"); File dir = new File(realPath); if (!dir.exists()){ dir.mkdirs(); } //2.遍历数组,将上传文件保存到文件夹 for(MultipartFile file:files){ String filename =file.getOriginalFilename(); filename =UUID.randomUUID()+"_"+filename; File newFile = new File(dir,filename); file.transferTo(newFile); } return "index"; }
SpringMVC文件上传_异步上传
之前的上传方案,在上传成功后都会跳转页面。而在实际开发中, 很多情况下上传后不进行跳转,而是进行页面的局部刷新,比如: 上传头像成功后将头像显示在网页中。这时候就需要使用异步文件上传。
1、编写JSP页面,引入jQuery和jQuery表单上传工具
jquery.form.js
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>上传</title> <script src="/js/jquery-2.1.1.min.js"></script> <script src="/js/jquery.form.js"> </script> </head> <body> <h3>文件上传</h3> <form id="ajaxForm" enctype="multipart/form-data" > <input type="file" name="file"/> <%-- 按钮类型不能是submit,否则会刷新页面 --%> <input type="button" value="上传头像"id="btn"/> </form> <%-- 上传头像后展示的位置 --%> <img src="/" width="100" id="img"> <script> $(function () { $("#btn").click(function () { // 异步提交表单 $("#ajaxForm").ajaxSubmit({ url:"/fileUpload4", type:"post", success:function (data) { $("#img").attr("src",data); } }) }) }) </script> </body> </html>
2、编写控制器接收异步上传请求
@RequestMapping("/fileUpload4") //不进行页面跳转 @ResponseBody public String upload3(HttpServletRequest request, MultipartFile file) throws Exception { // 创建文件夹,存放上传文件。 String realPath = request.getSession().getServletContext().getRealPath("/upload"); File dir = new File(realPath); if (!dir.exists()){ dir.mkdirs(); } // 拿到上传文件名 String filename = file.getOriginalFilename(); filename = UUID.randomUUID()+"_"+filename; // 创建空文件 File newFile = new File(dir, filename); // 将上传的文件写到空文件中 file.transferTo(newFile); // 返回文件的路径 return "/upload/"+filename; }
SpringMVC文件上传_跨服务器上传
由于文件占据磁盘空间较大,在实际开发中往往会将文件上传到其 他服务器中,此时需要使用跨服务器上传文件。
1、解压tomcat作为图片服务器,在tomcat的webapps下创建 upload目录作为文件上传目录。
2、修改tomcat的 conf/web.xml 文件,支持跨服上传。
<servlet> <init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param> </servlet>
3、修改tomcat的 conf/server.xml 文件,修改tomcat端口,修改完开启 tomcat服务器
<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
4、编写JSP上传表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>上传</title> <script src="/js/jquery2.1.1.min.js"></script> <script src="/js/jquery.form.js"></script> </head> <body> <h3>文件上传</h3> <form id="ajaxForm" enctype="multipart/form-data" > <input type="file" name="file"/> <input type="button" value="上传头像" id="btn"/> </form> <img src="/" width="100" id="img"> <script> $(function () { $("#btn").click(function() { $("#ajaxForm").ajaxSubmit({url:"/fileUpload5", type:"post",success:function(data) { $("#img").attr("src",data); } }) }) }) </script> </body> </html>
5、添加跨服上传依赖
<!-- 跨服上传 --> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-core</artifactId> <version>1.18.1</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.18.1</version> </dependency>
6、创建控制器方法,该方法在接受到上传请求后将文件保存到其他服务器上。
@RequestMapping("/fileUpload5") @ResponseBody public String upload4(HttpServletRequest request, MultipartFile file) throws Exception { // 设置跨服上传的服务器路径 String path = "http://localhost:8081/upload/"; // 获取上传的文件名 String filename = file.getOriginalFilename(); filename = UUID.randomUUID()+"_"+filename; // 跨服上传: // 1.创建客户端对象 Client client = Client.create(); // 2.使用客户端对象连接图片服务器 WebResource resource = client.resource(path + filename); //3.传输数据 resource.put(file.getBytes()); return path+filename; }