maven同springmvc的入门配置
maven同springmvc的入门配置
制作人:全心全意
springmvc项目的配置
创建spring的核心配置文件(springmvc.xml,可自定义名称)
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入头文件开始 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> </beans> <!-- 引入头文件结束 -->
配置前端控制器(web.xml)
<!-- 配置前端控制器开始 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 加载springmvc.xml文件 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 启动加载 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> <!-- *.action:访问以action为结尾,由DispatcherServlet进行解析 /:所有地址,都由DispatcherServlet进行解析,不使用(例如,访问图片不可解析) /*:此处不正确的配置,会形成页面和解析器的死循环 --> </servlet-mapping> <!-- 配置前端控制器结束 -->
创建控制器
#===================User对象开始======================================= package com.zq.bean; public class User { private String username; private Integer age; private Integer sex; public User() { } public User(String username, Integer age, Integer sex) { super(); this.username = username; this.age = age; this.sex = sex; } 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 Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } } #===================User对象结束======================================= #===================User1Controller开始======================================= package com.zq.user; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import com.zq.bean.User; public class User1Controller implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { // 生成用户列表 List<User> users = new ArrayList<>(); for (int i = 1; i <= 20; i++) { users.add(new User("username" + i, i, 0)); } // 封装页面的地址和要传入页面的数据 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("users", users); // 向页面传入内容 // 跳转的页面,默认为转发 modelAndView.setViewName("list.jsp"); // modelAndView.setViewName("redirect:list.jsp"); //重定向 return modelAndView; } } #===================User1Controller结束======================================= #===================User2Controller开始======================================= package com.zq.user; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.HttpRequestHandler; import com.zq.bean.User; public class User2Controller implements HttpRequestHandler { @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 生成用户列表 List<User> users = new ArrayList<>(); for (int i = 1; i <= 20; i++) { users.add(new User("username" + i, i, 0)); } // 封装页面的地址和要传入页面的数据 request.setAttribute("users", users); // 向页面传入内容 // 跳转的页面,默认为转发 request.getRequestDispatcher("list.jsp").forward(request, response); } } #===================User2Controller结束=======================================
配置控制器(springmvc.xml)
<!-- 配置控制器开始 --> <bean id="user1Controller" name="/user1Controller.action" class="com.zq.user.User1Controller"></bean> <!-- 配置控制器结束 -->
配置控制器映射器
<!-- 配置控制器映射器开始 --> <!-- 两种控制器映射器 org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping:将bean的name作为url进行查找,也就是handler必须配置name属性 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping:可以配置多个url能够访问 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <!-- 配置控制器映射器结束 -->
配置控制器适配器
<!-- 配置控制器适配器开始 --> <!-- 两种控制器适配器 org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter:Controller实现的是Controller接口 org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter:Controller实现的是HttpRequestHandler接口,例如User2Controller --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- 配置控制器适配器结束 -->
配置视图解析器:
<!-- 配置视图解析器开始 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean> <!-- 配置视图解析器结束 -->
配置测试页面
#=================list.jsp页面开始=================================== <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>用户列表</title> </head> <body> <table width="60%" align="center" border="1" cellpadding="5"> <tr> <th>用户名</th> <th>年龄</th> <th>性别</th> </tr> <c:forEach var="sn" items="${ users }"> <tr> <td align="center">${ sn.username }</td> <td align="center">${ sn.age }</td> <td align="center">${ sn.sex }</td> </tr> </c:forEach> </table> </body> </html> #=================list.jsp页面结束===================================
注意:pom.xml所有spring的插件版本号都应一致
#===================pom.xml开始================================================ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zq.test</groupId> <artifactId>zq-maven-test</artifactId> <packaging>war</packaging> <version>1.0</version> <name>zq-maven-test Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <spring.version>5.2.10.RELEASE</spring.version> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/taglibs/standard --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.2.1</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-web --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <build> <finalName>zq-maven-test</finalName> </build> </project> #===================pom.xml结束================================================
使用注解配置springmvc
创建控制器
#===================User1Controller开始======================================= package com.zq.user; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import com.zq.bean.User; public class User1Controller implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { // 生成用户列表 List<User> users = new ArrayList<>(); for (int i = 1; i <= 20; i++) { users.add(new User("username" + i, i, 0)); } // 封装页面的地址和要传入页面的数据 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("users", users); // 向页面传入内容 // 跳转的页面,默认为转发 modelAndView.setViewName("list.jsp"); // modelAndView.setViewName("redirect:list.jsp"); //重定向 return modelAndView; } } #===================User1Controller结束=======================================
配置控制器(springmvc.xml)
<!-- Controller扫描开始 --> <context:component-scan base-package="com.zq.user"></context:component-scan> <!-- Controller扫描结束 -->
配置控制器映射器
<!-- 配置控制器映射器开始 --> <!-- 两种控制器映射器 spring3.1之前 org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping spring3.1之后 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean> <!-- 配置控制器映射器结束 -->
配置控制器适配器(可省略,不配置)
<!-- 配置控制器适配器开始 --> <!-- spring3.1之前 org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter spring3.1之后 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean> <!-- 配置控制器适配器结束 -->
合并映射器和适配器的配置(建议省略上面的配置,使用合并配置)
<!-- 合并注解映射器和适配器的配置,项目中一般使用此种方式 对映射器和适配器进行加强,例如数据转化,如将对象转成json字符串等等 --> <mvc:annotation-driven></mvc:annotation-driven>
配置视图解析器:(可省略,不配置)
<!-- 配置视图解析器开始 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean> <!-- 配置视图解析器结束 -->
@Controller:声明Controller
作用于类
@RequestMapping:声明请求控制器配置
作用于类
作用于方法
属性说明:
value:配置url
method:配置请求方式
RequestMethod.GET
...
参数传递
基本参数:字符串/数字(参数名和页面元素的name属性对应)
@RequestMapping("addUser") public ModelAndView addUser(String username, Integer age, Integer sex) { System.out.println(username + " " + age + " " + sex); // 封装页面的地址和要传入页面的数据 ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("ok.jsp"); return modelAndView; }
<form action="addUser.action" method="post"> 请输入用户名:<input type="text" name="username"><br> 用户年龄:<input type="text" name="age"><br> 性别:<input type="text" name="sex"><br> <input type="submit" value="提交">
数组(参数名和页面元素的name属性对应)
@RequestMapping("addUser2") public ModelAndView addUser2(String[] hobby) { System.out.println(Arrays.toString(hobby)); // 封装页面的地址和要传入页面的数据 ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("ok.jsp"); return modelAndView; }
<form action="addUser2.action" method="post"> 爱好:<input type="checkbox" name="hobby" value="LOL">LOL <input type="checkbox" name="hobby" value="DNF">DNF <input type="checkbox" name="hobby" value="CF">CF <input type="submit" value="提交"> </form>
对象及时间(对象的set方法字段和页面元素的name属性保持一致,时间的属性在对象中要进行声明,并且需要合并将强映射器/适配器的支持)
@RequestMapping("addUser3") public ModelAndView addUser3(User user) { System.out.println(user); // 封装页面的地址和要传入页面的数据 ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("ok.jsp"); return modelAndView; }
<form action="addUser3.action" method="post"> 请输入用户名:<input type="text" name="username"><br> 用户年龄:<input type="text" name="age"><br> 出生日期:<input type="text" name="birthday"><br> <input type="submit" value="提交"> </form>
private String username; private Integer age; @DateTimeFormat(pattern = "yyyy-MM-dd") //声明时间格式化,前台到后台,转换为日期对象 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") //东8区 //JsonFormat:后台使用jacksion生成json对象时将时间格式化 //声明时间格式化,后台到前台,转换为对应日期格式的字符串,不使用默认为时间戳,timezone为设置时区,不使用相对于当前时区少8小时 private Date birthday;
Controller返回值及Model参数的说明(上述使用的都是ModelAndView)
String:页面的地址(最常用)
@RequestMapping("queryAllUser") public String queryAllUser(Model model) { // 封装页面的地址和要传入页面的数据 List<User> users = new ArrayList<>(); for (int i = 1; i <= 20; i++) { users.add(new User("username" + i, i, new Date())); } model.addAttribute("users", users); return "/list.jsp"; }
web常用对象参数类型的绑定
HttpServletRequest、HttpServletResponse、HttpSession、ServletContext
第一种方法:使用形式参数
@RequestMapping("queryWeb") public String queryWeb(HttpServletRequest request, HttpServletResponse response, HttpSession session1) { System.out.println(request); System.out.println(response); System.out.println(session1); // 从request中取出session HttpSession session2 = request.getSession(); System.out.println(session2); // 从request取出servletContext ServletContext context1 = request.getServletContext(); // 从session取出servletContext ServletContext context2 = session1.getServletContext(); System.out.println(context1); System.out.println(context2); return "/ok.jsp"; }
第二种方法:使用注入的方式(不推荐)声明HttpServletRequest、HttpServletResponse、HttpSession三个变量和对应的注解
@Autowired //该类必须通过spring容器创建 private HttpServletRequest request; @Autowired private HttpServletResponse response; @Autowired private HttpSession session; @RequestMapping("queryWeb2") public String queryWeb2() { System.out.println(request); System.out.println(response); System.out.println(session); // 从request中取出session HttpSession session2 = request.getSession(); System.out.println(session2); System.out.println(session.hashCode() + " " + session2.hashCode()); System.out.println("虽然两个session的输出地址和hashCode不同,但实际上就是一个Session,session经过了包装,session2没有经过包装"); // 从request取出servletContext ServletContext context1 = request.getServletContext(); // 从session取出servletContext ServletContext context2 = session.getServletContext(); System.out.println(context1); System.out.println(context2); return "/ok.jsp"; }
第三种方法:使用解耦方式(取的是当前线程的request)
@RequestMapping("queryWeb3") public String queryWeb3() { StrUtils.getWeb(); return "/ok.jsp"; } #===============StrUtils类开始================================= package com.zq.utils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; public class StrUtils { public static void getWeb() { // 得到request ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder .getRequestAttributes(); System.out.println(requestAttributes.getClass().getSimpleName()); HttpServletRequest request = requestAttributes.getRequest(); HttpServletResponse response = requestAttributes.getResponse(); HttpSession session = request.getSession(); System.out.println(request.hashCode()); System.out.println(response.hashCode()); System.out.println(session.hashCode()); } } #===============StrUtils类结束=================================
springmvc各种乱码问题
request乱码:
1.配置request
request.setCharacterEncoding("utf-8");
2.配置Tomcat
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />
3.解码在编码(一般不使用)
String myname = new String(name.getBytes("iso-8859-1"),"utf-8");
response乱码:
1.配置response
response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.write("你好,世界!"); out.flush(); out.close();
2.强制浏览器使用指定编码解析
response.setContentType("text/html;charset=utf-8");
springmvc解决乱码(过滤器):
<!-- 配置spring编码过滤器开始 --> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <!-- <url-pattern>*.action</url-pattern> --><!-- *.action的url使用此过滤器 --> <servlet-name>springmvc</servlet-name><!-- 调用springmvc servlet的使用此过滤器 --> </filter-mapping> <!-- 配置spring编码过滤器结束 -->
数据库乱码
1.配置JDBC的URL
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
2.配置数据库的默认编码(mysql的my.ini)
[mysql] default-character-set=utf8 #注意,没有-,就是utf8 [mysqld] character-set-server=utf8
转发和重定向
转发:一次请求一次响应,只能在服务器内部转发,页面发生变化,客户端(url)不发生变化
重定向:两次请求两次响应,可以重定向到其它服务器,页面的url会发生变化
servlet中:
转发:
request.getRequestDispatcher("list.jsp").forward(request,response);
重定向:
response.sendRedirect("list.jsp");
springmvc中:
转发:
//modelAndView ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("ok.jsp"); return modelAndView; //String return "/ok.jsp";
重定向:
return "redirect:ok.jsp";
视图解析器
<!-- 配置视图解析器开始 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 添加前缀 --> <property name="prefix" value="/page/"></property> <!-- 添加后缀 --> <property name="suffix" value=".jsp"></property> </bean> <!-- 配置视图解析器结束 -->
前缀和后缀的作用:可在返回页面时省略输入前缀和后缀,例如
return "ok"; //等同于 return "ok.jsp";
spring返回数据到页面
springmvc返回字符串到页面
1.最原始的方法
@RequestMapping("getString") public void getString(HttpServletResponse response) { String str = "我是一个字符串"; response.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); PrintWriter out = null; try { out = response.getWriter(); } catch (IOException e) { e.printStackTrace(); } out.write(str); out.flush(); out.close(); }
2.使用ResponseBody注解
@RequestMapping(value = "getString2", produces = "text/html;charset=utf-8") // 将当前方法的返回值以字符串的形式响应给客户端 ,需在@RequestMapping中定义produces,否则返回中文乱码 @ResponseBody public String getString2() { String str = "我是一个字符串"; return str; }
<script type="text/javascript"> function tt() { //依赖于http://libs.baidu.com/jquery/1.11.1/jquery.min.js $.get("getString2.action", function(data) { console.log(data); }) } </script>
使用fastjson返回自定义对象到页面(需要fastjson的jar包)
//返回一个User对象字符串 @RequestMapping(value = "getUser1", produces = "text/html;charset=utf-8") @ResponseBody public String getUser1() { Date date = new Date(); User user = new User("小明", 12, date); // 将user转成json字符串,使用fastjson String json = JSON.toJSONString(user); return json; } //返回一个User对象list字符串 @RequestMapping(value = "getUsers", produces = "text/html;charset=utf-8") @ResponseBody public String getUsers() { Date date = new Date(); List<User> users = new ArrayList<>(); for (int i = 1; i <= 10; i++) { users.add(new User("小明" + i, i, date)); } String json = JSON.toJSONString(users); return json; }
使用jackson去构造对象(最常用),导入jackson的jar包即可返回对象,springmvc的增强适配器会自动调用
// 返回一个List<User>对象(还可返回Map等对象) @RequestMapping(value = "getUsers2") @ResponseBody public List<User> getUsers2() { Date date = new Date(); List<User> users = new ArrayList<>(); for (int i = 1; i <= 10; i++) { users.add(new User("小明" + i, i, date)); } return users; }
<!-- pom.xml配置 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.2</version> </dependency>
springmvc文件上传
文件上传的jar包:apache提供的commons-fileupload.jar、commons-io.jar
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
配置springmvc对文件上传的支持(springmvc.xml)
<!-- 配置文件上传二进制流的解析器开始 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 指定文件上传的编码,如文件名是中文 --> <property name="defaultEncoding" value="UTF-8"></property> <!-- 指定上传文件保存的临时目录 --> <property name="uploadTempDir" value="/upload/temp"></property> <!-- 指定上传文件的最大大小 1m=1024*1024*1024 --> <property name="maxUploadSize" value="1024000000"></property> </bean> <!-- 配置文件上传二进制流的解析器结束 -->
上传原理:当服务器接收到文件流之后,将文件流写入到服务器的上传的临时目录,文件会丢失文件名和类型,开发者通过自己开发得到上传的文件名称和类型,自定义是否改名,将临时目录中的文件拷贝到上传的目录中,并赋予文件名和类型。
上传单文件
@RequestMapping("upload01") @ResponseBody public String upload01(MultipartFile mf, HttpServletRequest request) { // 获取文件的相关信息 String contentType = mf.getContentType(); // 文件类型,并非后缀名 String inNmae = mf.getName();// 表单input标签对应name的值 String oldName = mf.getOriginalFilename(); // 文件名称 long size = mf.getSize(); // 文件大小 System.out.println(contentType + " " + inNmae + " " + oldName + " " + size); // 获取文件存放位置,相对于系统的绝对路径 String realPath = request.getServletContext().getRealPath("/upload"); System.out.println(realPath); // 组装文件对象,realPath为保存文件路径,oldName为保存文件名 File file = new File(realPath, oldName); // 将文件流写入文件对象 try { mf.transferTo(file); } catch (IllegalStateException | IOException e) { e.printStackTrace(); } return "success"; }
<form action="upload01.action" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="mf"> <br> <input type="submit" value="提交"> </form>
上传多文件
@RequestMapping("upload02") @ResponseBody public String upload02(MultipartFile[] mf, HttpServletRequest request) { if (null != mf && mf.length > 0) { for (int i = 0; i < mf.length; i++) { // 获取文件的相关信息 String contentType = mf[i].getContentType(); // 文件类型,并非后缀名 String inNmae = mf[i].getName();// 表单input标签对应name的值 String oldName = mf[i].getOriginalFilename(); // 文件名称 long size = mf[i].getSize(); // 文件大小 System.out .println(contentType + " " + inNmae + " " + oldName + " " + size); // 获取文件存放位置,相对于系统的绝对路径 String realPath = request.getServletContext().getRealPath("/upload"); System.out.println(realPath); // 组装文件对象 File file = new File(realPath, oldName); // 将文件流写入文件对象 try { mf[i].transferTo(file); } catch (IllegalStateException | IOException e) { e.printStackTrace(); } } } return "success"; }
<form action="upload02.action" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="mf"> <br> <input type="file" name="mf"> <br> <input type="file" name="mf"> <br> <input type="submit" value="提交"> </form>
springmvc文件下载
1.通过路径进行下载
优点:不用写代码
缺点:
暴露文件在服务器的地址
文件的老名称丢失
2.后台下载
优缺点与路径下载相反
第一种:最原始的方式
@RequestMapping("getFile1") public void getFile1(HttpSession session, HttpServletResponse response) throws Exception { String urlpath = "/upload/审计月报.doc"; // 获得相对路径 // 获得服务相对于系统的绝对路径 String path = session.getServletContext().getRealPath("/"); String filePath = path + "/" + urlpath; System.out.println(filePath); File file = new File(filePath); if (file.exists()) { String filename = URLEncoder.encode(file.getName(), "UTF-8"); // 如果文件名有中文,必须使用URLEncoder进行编码 String contentType = Files.probeContentType(Paths.get(filePath)); response.setContentType(contentType); // 设置文件类型 System.out.println(contentType); response.addHeader("Content-Disposition", "attachment;filename=" + filename); // 设置文件下载的名字 int fileLength = (int) file.length(); response.setContentLength(fileLength); // 设置文件长度 // 如果文件长度不等于0 if (fileLength != 0) { InputStream inStream = new FileInputStream(file); // 创建输入 byte[] buf = new byte[4096]; // 创建缓冲区 ServletOutputStream servletOS = response.getOutputStream(); // 创建输出 int readLength; while (((readLength = inStream.read(buf)) != -1)) { servletOS.write(buf, 0, readLength); } inStream.close(); servletOS.flush(); servletOS.close(); } } }
第二种:返回ResponseEntity封装对象
@RequestMapping("getFile2") public ResponseEntity getFile2(HttpSession session) { String urlpath = "/upload/审计月报.doc"; // 获得相对路径 // 获得服务相对于系统的绝对路径 String path = session.getServletContext().getRealPath("/"); String filePath = path + "/" + urlpath; System.out.println(filePath); File file = new File(filePath); // 将下载的文件封装byte[] byte[] bytes = null; try { bytes = FileUtils.readFileToByteArray(file); } catch (IOException e) { e.printStackTrace(); } // 创建封装响应头信息的对象 HttpHeaders header = new HttpHeaders(); // 封装响应内容类型(APPLICATION_OCTET_STREAM 响应的内容不限定) header.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 设置下载的文件的名称 String filename = ""; try { filename = URLEncoder.encode(file.getName(), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } header.setContentDispositionFormData("attachment", filename); // 创建ResponseEntity对象 ResponseEntity entity = new ResponseEntity(bytes, header, HttpStatus.CREATED); return entity; }
拦截器
servlet中的过滤器的作用是在用户请求某个资源之前进行拦截,是否满足条件,满足即放行,执行相关的请求,请求完成后返回到过滤器,再响应给客户端。它可以拦截所有的请求(servlet、jsp、js、css、文件、图片等)
springmvc中的拦截器的作用也是拦截用户请求,但是它只拦截controller
创建拦截器
public class LoginInteceptor implements HandlerInterceptor { /** * 当用户请求时,如果这个URL要被拦截,首先执行的方法 * * @return true 代表放行 false 代表请求不合法 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle方法,当用户请求时,如果这个URL要被拦截,首先执行的方法"); HttpSession session = request.getSession(); Object attribute = session.getAttribute("user"); if (null != attribute) { return true; // 返回true,执行controller中的方法 } response.sendRedirect("index.jsp"); return false; } /** * handler中处理请求的方法,返回ModeAndView对象之前执行,可以对ModeAndView进行再次加工 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle方法,不进行再次加工ModeAndView"); } /** * 当请求controller完全执行完成后,调用该方法 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion方法,当请求controller完全执行完成后,调用该方法"); } }
配置拦截器(springmvc.xml)
<!-- 配置拦截器开始 --> <mvc:interceptors> <!--配置未登录拦截器 --> <mvc:interceptor> <!-- 要拦截的路径 只要经过DispatcherServlet的都要拦截 --> <mvc:mapping path="/**" /> <!-- 排除要拦截的路径 登陆页面和登陆接口 --> <mvc:exclude-mapping path="/login.*" /> <!-- 可简写为"/login.*" --> <!-- 指定使用的拦截器 --> <bean class="com.zq.inteceptor.LoginInteceptor"></bean> </mvc:interceptor> </mvc:interceptor> </mvc:interceptors> <!-- 配置拦截器结束 -->
restFul的使用
前端控制器的配置(使用"/")
<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> <!-- *.action:访问以action为结尾,由DispatcherServlet进行解析 /:所有地址,都由DispatcherServlet进行解析,不使用(例如,访问图片不可解析) ,用在restFul中,使用此项浏览器访问可不加.action /*:此处不正确的配置,会形成页面和解析器的死循环 --> </servlet-mapping>
@RequestMapping(value = "getrestFul/{name}", produces = "text/html;charset=utf-8", method = RequestMethod.GET) @ResponseBody public String getrestFul(@PathVariable(value = "name") String name) { System.out.println(name); return "restFul:" + name; }
在restFul中,一般使用相同请求地址,不同请求方式来操作数据(增加:post、删除:delete、修改:put、单查询:get、全查询:patch)
每种请求方式对应的RequestMapping都可以简写为自己的请求注解
// @RequestMapping(value = "getrestFul", produces = "text/html;charset=utf-8", method = RequestMethod.PUT) @PutMapping(value="getrestFul/{name}", produces = "text/html;charset=utf-8") //put请求的注解 @ResponseBody public String getrestFul(@PathVariable(value = "name") String name) { System.out.println(name); return "restFul:" + name; }