SpringMVC
第一个小程序,使用webapp骨架可以避免被采坑
- 首先创建maven工程,之后搞个小的模块,添加web架构
- 引入依赖,肯定有spring-webmvc,然后有个javax.servlet-api,还有个普通的servlet
在父类的xml补充这个加载资源配置文件
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!--EL表达式的依赖-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
- 配置web.xml,注册DispatcherServlet。本质是写servlet
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--注册DispatcherServlet,这是springmvc的核心,就是个servlet-->
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--/ 匹配所有的请求;(不包括.jsp)-->
<!--/* 匹配所有的请求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 编写spring的配置文件,在视图解析器中我们把所有的都存放在/WEB-INF/目录下,这样既可以保护视图的安全,因为这个目录下的文件,客户端不能直接访问。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--处理映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="/user" class="com.zhou.controller.HelloController"/>
</beans>
- 编写操作业务,Controller,有两种方式,一种是实现Controller接口,第二种方式是增加注解,需要返回一个ModelAndView,这个对象用来封装视图和模型
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();
//封装对象,放在ModelAndView中。Model
mv.addObject("msg","HelloSpringMVC! staty");
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("user"); //: /WEB-INF/page/user.jsp
return mv;
}
}
- 把类注入到容器中
<!--把类注入的容器中,注册bean,注意这个是要加/,相当于是url,-->
<bean id="/user" class="com.zhou.controller.HelloController"/>
- 写要跳转的jsp也页面,显示ModelAndViewe存放的数据,以及显示的页面。当然这个jsp是放在WEB-INF/page下面的
注意:要开启这个这个
<%@ page isELIgnored="false" %>
在head中添加这个,才能使${msg}有显示的内容
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<%@ page isELIgnored="false" %>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
IDEA 程序包org.springframework.stereotype不存在的解决方法
SpringMVC的原理
请描述Spring MVC的工作流程?描述一下 DispatcherServlet 的工作流程?
(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
————————————————
版权声明:本文为CSDN博主「ThinkWon」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ThinkWon/article/details/104397427
方法2:使用注释的方法
前面的部分知道web.xml都是一样的,spring的配置直接开启扫包使用注解的方式。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.kuang.controller"/>
<!-- 让Spring MVC不处理静态资源 -->
<mvc:default-servlet-handler />
<!--
支持mvc注解驱动
在spring中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping注解生效
必须向上下文中注册DefaultAnnotationHandlerMapping
和一个AnnotationMethodHandlerAdapter实例
这两个实例分别在类级别和方法级别处理。
而annotation-driven配置帮助我们自动完成上述两个实例的注入。
-->
<mvc:annotation-driven />
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/page/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。
让IOC的注解生效
静态资源过滤 :HTML . JS . CSS . 图片 , 视频 …
MVC的注解驱动
配置视图解析器
@Controller
@RequestMapping("/HelloController")
public class HelloController {
//真实访问地址 : 项目名/HelloController/user
@RequestMapping("/user")
public String sayHello(Model model){
//向模型中添加属性msg与值,可以在JSP页面中取出并渲染
model.addAttribute("msg","hello,SpringMVC");
//web-inf/page/user.jsp
return "user";
}
}
@Controller是为了让Spring IOC容器初始化时自动扫描到;
@RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;
方法中声明Model类型的参数是为了把Action中的数据带到视图中;
方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/page/user.jsp
Spring MVC注解
- 映射:Cookie
Spring MVC通过映射可以直接在业务方法中获取Cookie的值
/*获取cookie,SpringMVC通过映射可以直接在业务中获取COokie*/
@RequestMapping("/cookie")
public String cookie(@CookieValue(value="JSESSIONID") String sessionID){
System.out.println(sessionID);
// 02A96A4FC6E4E7D57E59E1F77AA4718A
return "index";
}
使用javabean绑定参数
Spring MVC会根据请求参数名和javaBean属性名进行自动装配,自动为对象填充属性值,同时支持及联属性,即有类对象的表的那种
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private long id;
private String name;
private Address address;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
private String value;
}
@Controller
@RequestMapping("/hello")
public class HelloHandle {
/*给另一个路径,指定具体的方法,也可以使用直接方法的注释*/
// @RequestMapping(value = "/save",method = RequestMethod.POST)
@PostMapping("/save")
// 参数除了可以传递多个或者单个参数,也可以传递具体的javabean对象,会自动的进行属性匹配
public String save(User user){
System.out.println(user);
return "index";
}
}
搞一个表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--搞一个表,post方法的,试用看是转发还是重定向,所以,搞一个--%>
<form action="/hello/save" method="post">
用户id:<input type="text" name="id"/><br>
用户名:<input type="text" name="name"/><br>
用户地址:<input type="text" name="address.value"><br>
<%--把表格进行提交submit--%>
<input type="submit" value="注册"/>
</form>
</body>
</html>
要是中文发生乱码了,则只需要在web.xml中添加一下这个配置
<!--中文发生乱码了,则在web.xml中加一个过滤器-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--和spring配置一样,这个耶需要init-->
<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>/*</url-pattern>
</filter-mapping>
这个测试:不是像之前那样测试,因为这是post请求,不能直接填http://localhost:8080/hello/save。而是先通过form表单http://localhost:8080/form.jsp,注册之后到save
点击注册之后到save
- JSP页面的转发和重定向:
转发和重定向的区别: - 转发地址栏不会改变。是服务器需要调整,属于同一个请求,所以如果需要请求中的数据可以取出来。
- 重定向地址栏会发生改变,是客户端的调整,相当于从客户端重新发了一个请求过来,两个请求,而这个请求的数据是取不出来的。
SpringMVC默认值以转发的形式响应给JSP
测试:由于是post方法,所以先要访问表单,form.jsp。然后再点击注册,这样就是post的请求。点击注册后会跳转到解析后的index.jsp页面,但是地址栏却是/hello/save,则说明地址栏并没有变化,但他实际解析的是index.jsp,说明SpringMVC的默认是以转发的形式响应jsp的。
/*在搞一个转发*/
@RequestMapping("/forward")
public String forward(){
return "forward:/index.jsp";
// return "index"; 这两个是等价的
}
同一个页面,地址栏没变,但是它是同一个页面index.jsp
2. 重定向
/*重定向*/
@RequestMapping("/redirect")
public String redirect(){
return "redirect:/index.jsp";
}
都是指向同一个页面index.jsp,但是地址栏确变了这就是重定向
Spring MVC数据绑定
数据绑定:在后端的业务中直接获取客户端的HTTP请求中的参数,也就是方法中的形参,将请求参数映射到业务方法的形参,SpringMVC中的数据绑定的工作,是由HandlerAdapter来完成的。
- 基本数据类型
@Controller
public class HandleDemo01 {
@RequestMapping("/baseType")
@ResponseBody // 获取客户端HTTP的请求参数即方法中的形参,需要加返回本体@ResponseBody
public String baseType(int id){
return id+"";
}
// http://localhost:8080/baseType?id=2 页面显示的是2传递的参数是什么就显示什么
// 如果不写这个参数的话则会报错, 'id' is present but cannot be translated into a null value
// id不能是null值,所以要解决这个问题要传递包装类 // 如果这个把int改为Integer不传参数的话,返回的是null
}
@ResponseBody 表示 Spring MVC 会直接将业务⽅方法的返回值响应给客户端,如果不不加@ResponseBody 注解,SpringMVC会将业务方法的返回值传递给DispatcherServlet,再由DispatcherServlet调用ViewResolver视图解析器进行解析,映射到一个JSP资源
- 包装类
@RequestMapping("/packageType")
@ResponseBody
public String packageType(@RequestParam(value = "num",required = false,defaultValue = "0") Integer id){
// 上面的注解是给注解进行约束
// 让传参的参数直接能返回看到
return id+"";
}
@RequestParam,请求参数的注解: 这里面的参数第一个是域名称的参数,即写在域名上的参数,后面的那个参数是形参,域名参会把值赋给形参,所以所如果域名num=3,则id=3
value = “num”:将 HTTP 请求中名为 num 的参数赋给形参 id。
requried:设置 num 是否为必填项, true 表示必填, false 表示⾮非必填,可省略略
defaultValue = “0”:如果 HTTP 请求中没有 num 参数,默认值为0
- 数组
/*数组,当参数为数组的时候*/
@RequestMapping("/array")
@ResponseBody // 这个返回本体的注释,还可以直接在类名上加@RestController
public String array(String[] name){
// 把传进来的参数变成数组 Arrays.toString(数组名)
String str = Arrays.toString(name);
return str;
}
http://localhost:8080/array?name=zhan&name=li&name=yingzi
@RestController表示该控制器会直接将业务方法的返回值给客户端,不进行视图解析
@Controller表示该控制器的每一个业务方法的返回值都会交给视图解析器进行解析,如果只需要将数据响应给客户端,而不需要进行视图解析,则需要在对应的业务方法那里添加@ResponseBody
@Controller
public class HandleDemo01 {
/*数组,当参数为数组的时候*/
@RequestMapping("/array")
@ResponseBody // 这个返回本体的注释,还可以直接在类名上加@RestController
public String array(String[] name){
// 把传进来的参数变成数组 Arrays.toString(数组名)
String str = Arrays.toString(name);
return str;
}
}
等价于
@RestController
@Controller
public class HandleDemo01 {
/*数组,当参数为数组的时候*/
@RequestMapping("/array")
public String array(String[] name){
// 把传进来的参数变成数组 Arrays.toString(数组名)
String str = Arrays.toString(name);
return str;
}
}
- 参数是List
Spring MVC不支持List类型的直接转换,需要对List集合进行包装。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserList {
// 我需要传一个User对象的集合。参数那里不能的传list
// 要把集合封装成一个对象(类型是一个集合),来传。
private List<User> users;
}
注册的页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--写个form表,input属性的name里面是空格,需要填写的内容
value是框框里面具体的值。需要传多个参数的话是集合类型的使用具体数组的索引.属性
--%>
<form action="/data/list" method="post">
用户1编号:<input type="text" name="users[0].id"/><br>
用户1名称:<input type="text" name="users[0].name"/><br>
用户1地址:<input type="text" name="users[0].address.value"/><br>
用户2编号:<input type="text" name="uses[1].id"/><br>
用户2名称:<input type="text" name="users[1].name"/><br>
用户2地址:<input type="text" name="users[1].address.value"/><br>
<input type="submit" value="提交"/>
</form>
</body>
</html>
@Controller
@RequestMapping("/data")
public class HandleDemo01 {
/*集合list*/
@RequestMapping("/list")
@ResponseBody
public String list(UserList userList){
// 直接返回的传递的集合,需要加返回本体注解
// StringBuffer比String节省内存
StringBuffer str = new StringBuffer();
// 遍历传递进来的集合对象
for (User user : userList.getUsers()) {
// 把user对象拼接起来,使用append
str.append(user);
}
return str.toString();
}
}
乱码:需要在Spring.xml配置中加一个配置
<!--开启mvc的注解-->
<mvc:annotation-driven>
<!--加个消息转换器,来处理中文乱码问题-->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
Map
也是需要封装成一个集合类
// 传递集合Map
@RequestMapping("/map")
@ResponseBody
public String map(UserMap userMap){
// 遍历出Map集合,通过key来遍历。取key的方法是keySet。
StringBuffer str = new StringBuffer();
for (String key : userMap.getUserMap().keySet()) {
// 通过key来查询值,get(key)
User user = userMap.getUserMap().get(key);
str.append(user);
}
return str.toString();
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/data/map" method="post">
<%--这个里面对应的是属性--%>
用户1编号:<input type="text" name="userMap['a'].id"/><br>
用户1名称:<input type="text" name="userMap['a'].name"/><br>
用户1的地址:<input type="text" name="userMap['a'].address.value"><br>
用户2编号:<input type="text" name="userMap['b'].id"/><br>
用户2名称:<input type="text" name="userMap['b'].name"/><br>
用户2的地址:<input type="text" name="userMap['b'].address.value"><br>
<input type="submit" value="提交"/>
</form>
</body>
</html>
json
客户端发生了json格式的数据,直接通过Spring MVC绑定到业务方法的形参中。
处理SpringMVC无法加载静态资源,在web.xml中添加配置即可
<!--把.js文件不过滤,springmvc无法加载静态资源,需要把.js排除-->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
引入js需要的jquery包,在webapp下建一个js,放这个里面
json数据要使用jqery,不能使用表格了,表格传递不了json数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%--把jquery引入--%>
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function (){
// 先写个看下能不能弹出,看下jquery是否引入成功
/*alert(123);*/
// 把对象以键值对的形式变成json形式
var user = {
"id":1,
"name":"张三"
}
/*路径*/
$.ajax({
url:"/data/json",
data:JSON.stringify(user), // 把user形式转为json形式
type:"POST", // 方法类型type
contentType:"application/json;charset=UTF-8", // 设置编码格式
dataType:"JSON", // 传递过去的数据类型:json
// 回调函数
success:function (data){
alert(data.id+"----"+data.name);
}
})
});
</script>
</head>
<body>
</body>
</html>
/*方法,传递的参数是json格式的参数*/
@RequestMapping("/json")
@ResponseBody
/*传递的如果是json格式的数据对象,则必须要指定请求参数的注解*/
public User json(@RequestBody User user){
System.out.println(user);
user.setId(6);
user.setName("赵云");
return user;
}
MVC中的json和javabean的转换,需要借助fastjson的pom.xml的依赖
<!--JSON和JavaBean的转换,需要借助fastjson,引入相关依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.37</version>
</dependency>
在spring.xml中的配置,要加上fastjson配置
<!--开启mvc的注解-->
<mvc:annotation-driven>
<!--加个消息转换器,来处理中文乱码问题-->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
</bean>
<!--配置fastjson,和json数据相关的-->
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
测试:http://localhost:8080/json.jsp。打印的是:User(id=1, name=张三, address=null)
之后弹出
说明,先是json转成user对象,然后user对象转为json后面又返回了
Spring MVC模型数据分析
JSP:四大作用域对应的内置对象:pageContext,request,session,application。
模型数据的绑定是由ViewResolver来完成的,实际开发中,我们需要先添加数据模型,在交给ViewResolver来绑定。
SpringMVC提供了以下几种方式添加模型的数据。
- Map
- Model
- ModelAndView
- @SessionAttribute
- @ModelAttibute
将模式数据绑定到request对象
@Controller
public class ViewHandle {
@RequestMapping("/map")
public String Map(Map<String, User> map){
// 我们要添加模型数据,第一种方式是Map方式
// 实例化一个User对象,然后把它添添加到域中
User user = new User();
user.setId(1L);
user.setName("张三");
Address address = new Address();
address.setValue("广州");
user.setAddress(address);
// 然后把对象放到map中
map.put("user",user);
return "view";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%@ page isELIgnored="false" %></head>
<body>
<%--在request域中去取--%>
${requestScope.user}
</body>
</html>
和之前显示的传递的参数是不一样的,这个是显示的是模型的数据然后解析后展示的视图jsp。
-
- Model第二种方式:存到Model中
model.addAttribute(),添加属性
- Model第二种方式:存到Model中
/*使用Model对象来寸模型数据*/
@RequestMapping("/model")
public String model(Model model){
// 模型数据存到model中
// 实例化User为模型数据
User user = new User();
user.setId(1L);
user.setName("张三");
model.addAttribute("user",user);
return "view";
}
- 3.第三种方式:ModelAndView
/**
* 使用modelAndView方法来存,想象之前的mvc入门。需要
* @param modelAndView
* @return
*/
@RequestMapping("/modelAndView")
// 这个方式类似之前入门springmvc的使用配置入门的第一个程序
public ModelAndView modelAndView(){
User user = new User();
user.setId(1L);
user.setName("张三");
// 和之前入门MVC有类似出
ModelAndView mv = new ModelAndView();
mv.addObject("user",user);
// 取视图的名字
mv.setViewName("view");
// mv是ModelAndObject对象,模型和数据对象。而不是字符串对象,所以之前是报错巅峰
return mv;
}
ModelAndView方式的第二种方法
/*使用modelAndView的第二种方式*/
@RequestMapping("/modelAndView2")
public ModelAndView modelAndView2(){
User user = new User();
user.setId(2L);
user.setName("李四");
ModelAndView mv = new ModelAndView();
// 封装到数据模型
mv.addObject("user",user);
// 转发到view页面,除了设置view的名字,还可以借助InternalResourceView接口
View view = new InternalResourceView("/view.jsp");
mv.setView(view);
return mv;
}
ModelAndView方式的第三种方法,直接返回modelAndView对象
// 使用modelAndView方式的第三种方式
@RequestMapping("/modelAndView3")
public ModelAndView modelAndView3(){
User user = new User();
user.setId(1L);
user.setName("赵云");
// 封装到数据模型,view的名字直接在这个方法上写
ModelAndView modelAndView = new ModelAndView("view");
modelAndView.addObject("user",user);
// 直接返回mv对象,ModelAndView方法中包含了view name
return modelAndView;
}
@RequestMapping("/modelAndView4")
public ModelAndView modelAndView4(){
User user = new User();
user.setId(1L);
user.setName("张三");
View view = new InternalResourceView("/view.jsp");
ModelAndView modelAndView = new ModelAndView(view);
modelAndView.addObject("user",user);
return modelAndView;
}
/*方法5使用Map*/
@RequestMapping("/modelAndView5")
public ModelAndView modelAndView5(){
User user = new User();
user.setId(1L);
user.setName("英子");
// 使用Map来存,不是直接放参数上
Map<String,User> map = new HashMap<>();
map.put("user",user);
ModelAndView modelAndView = new ModelAndView("view", map);
return modelAndView;
}
@RequestMapping("/modelAndView7")
public ModelAndView modelAndView7(){
User user = new User();
user.setId(1L);
user.setName("张三");
// 把map,换成了直接把对象传过去
ModelAndView modelAndView = new ModelAndView("view","user",user);
return modelAndView;
}
@RequestMapping("/modelAndView8")
public ModelAndView modelAndView8(){
User user = new User();
user.setId(1L);
user.setName("张三");
View view = new InternalResourceView("/view.jsp");
ModelAndView modelAndView = new ModelAndView(view,"user",user);
return modelAndView;
}
-
- HttpServletRequest
/*使用HttpServletRequest方法存*/
@RequestMapping("/request")
/*需要引入servlet-api的依赖*/
public String request(HttpServletRequest request){
User user = new User();
user.setId(1L);
user.setName("张三");
request.setAttribute("user",user);
return "view";
}
-
- @ModelAttribute
定义一个方法,该方法专门用来返回要填充的到模型数据中的对象
- @ModelAttribute
/*本来User对象应该向前面的填充到模型的数据中
* 可以把填充的对象通过@ModelAttribute注解单独给拿出来
* */
@ModelAttribute
public User getUser(){
User user = new User();
user.setId(1L);
user.setName("张三");
return user;
}
// 上面那个已经把模型数据存起来了,所以这个就只需要视图
@RequestMapping("/modelAttribute")
public String modelAttribute(){
return "view";
}
使用Map形式的返回填充的数据对象
/*如果不返回,就一个void那么可以在方法中的参数,加集合,用它来保存*/
// 专门用来返回要填充到模型数据中的对象
@ModelAttribute
public void getUser(Map<String,User> map){
User user = new User();
user.setId(1L);
user.setName("张三");
// 键值对的形式
map.put("user",user);
}
使用Model对象返回填充的方式
// 上面那个已经把模型数据存起来了,所以这个就只需要视图
@RequestMapping("/modelAttribute")
public String modelAttribute(){
return "view";
}
/*如果不返回,就一个void那么可以在方法中的参数,加集合,用它来保存*/
// 专门用来返回要填充到模型数据中的对象
@ModelAttribute
public void getUser(Map<String,User> map){
User user = new User();
user.setId(2L);
user.setName("磊儿");
// 键值对的形式
map.put("user",user);
}
// 使用Model的方法,来返回填充的数据的值
@ModelAttribute
public void getUser(Model model){
User user = new User();
user.setId(3L);
user.setName("杨杨");
model.addAttribute("user",user);
}
业务中方法无需要处理模型的数据,只需要返回视图即可
@RequestMapping("/modelAttribute")
public String modelAttribute(){
return "view";
}
将模型数据绑定到session对象
- 使用原生的ServletAPI
// 使用Model的方法,来返回填充的数据的值
@ModelAttribute //,一旦这个没有写这个注解,那么就不会进这个方法
public void getUser(Model model){
User user = new User();
user.setId(3L);
user.setName("杨杨");
model.addAttribute("user",user);
}
/*把模型数据绑定到session对象中*/
@RequestMapping("/session")
public String session(HttpServletRequest request){
// 使用request来获取session
HttpSession session = request.getSession();
// 再把对象绑定到session中去
User user = new User();
user.setId(1L);
user.setName("英子");
session.setAttribute("user",user);
return "view";
}
view.jsp中
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%@ page isELIgnored="false" %></head>
<body>
<%--在request域中去取--%>
${requestScope.user}
<%--session域中取--%>
${sessionScope.user}
</body>
</html>
有前面的那个@ModelAttribute填充的注解,即使发送的是session请求,也会先进这个方法,因为是在request域中,所以是肯定有这个,再往session域中注入
第二中数据绑定session的方式:HttpSession session。使用HttpSession来绑定
/*第二种session绑定数据的方式*/
@RequestMapping("/session2")
public String session2(HttpSession session){
User user = new User();
user.setId(1L);
user.setName("英子");
session.setAttribute("user",user);
return "view";
}
session绑定数据的第三种方式:在类上加@SessionAttribute。这样的话就是所有的类都会添加,一般不推荐。
@SessionAttributes(value = {"user","address"})
public class ViewHandler {
}
对于ViewHandler中的所有的业务方法,只要向request中添加了key=“user”,key="address"的对象时,SpringMVC会自动将数据添加到session中,保持key不变。
还有一种方式是传参数类型的
@SessionAttributes(types = {User.class,Address.class})
public class ViewHandler {
}
- 将模型数据绑定到application对象,绑定application对象也是需要在HttpServletRequest request中
/*绑定application对象*/
@RequestMapping("/application")
public String application(HttpServletRequest request) {
ServletContext application = request.getSession().getServletContext();
User user = new User();
user.setId(1L);
user.setName("张三");
application.setAttribute("user", user);
return "view";
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%@ page isELIgnored="false" %></head>
<body>
<%--在request域中去取--%>
${requestScope.user}
<%--session域中取--%>
${sessionScope.user}
<hr>
<%--从application域中去取。--%>
${applicationScope.user}
</body>
</html>
SpringMVC自定义数据转换器
数据转换器是指客户端HTTP请求中的参数转为业务方法中定义的形参,自定义表示开发者可以自主设计转换的方式,HandlerApdter已经提供了通用的转换,String转int,String转double,表单数据的封装等,但是在特殊的业务下,是不能转的,需要自定义
如:客户端输⼊入 String 类型的数据 “2019-03-03”,⾃自定义转换器器将该数据转为 Date 类型的对象。
package com.zhou.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*converter是转换器的意思,*/
// 转换器的实现要使用Converter转换器接口
// 首先要考虑把什么转化成什么?比如:把字符串形式的日期转成Date
public class DateConverter implements Converter<String, Date> {
// 日期,需要一个成员变量pattern
private String pattern;
public DateConverter(String pattern) {
this.pattern = pattern;
}
@Override
public Date convert(String s) {
// 转日期的格式:想到simpleDateFormat
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.pattern);
// 要转成Date
Date date = null;
try {
// 提升作用域Date
date = simpleDateFormat.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
- sprinmvc.xml配置转换器
<!--配置自定义转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.zhou.converter.DateConverter">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd"/>
</bean>
</list>
</property>
</bean>
<!--注意配置转换器的配置时,下面的conversion-service不能忘记-->
<!--开启mvc的注解-->
<mvc:annotation-driven conversion-service="conversionService">
<!--加个消息转换器,来处理中文乱码问题-->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
</bean>
<!--配置fastjson,和json数据相关的-->
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
addDate.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--给个表单,填写日期的表单--%>
<form action="/converter/date" method="post">
请输⼊日期:<input type="text" name="date"/>(yyyy-MM-dd)<br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
package com.zhou.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
//@Controller
@RestController
@RequestMapping("/converter")
public class ConverterHandle {
/*输入日期,还是显示转换后的日期,也就是相当于显示本体*/
@RequestMapping("/date")
// @ResponseBody
public String date(Date date){
return date.toString();
}
}
String转Student
- 写个Student类,注意写这个类的时候一定要在entity(实体类)包下创建。实体类特点是:数据表对应到实体类的映射
开发中model,entity和pojo的区别
一、Bean
对于Bean而言,我的理解是只要是Java的类的就可以称为一个Bean,更用在Spring上,被Spring管理的对象就可以将其称作为Bean。
1、所有属性为private。
2、提供无参数的构造器。
3、getter和setter来访问。
4、可序列化的。实现serializable接口。
Javabean虽然数据的获取与POJO一样,但是javabean当中可以有其它的方法。
POJO
(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为POJO类中有属性和get、set方法,但是没有业务逻辑
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private Long id;
private String name;
private int age;
}
要在url中输入student类的字符串,然后要显示,一般使用表单来提交
addStudent.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--请输入了学生的数据之后然后提交,使用表单的情况去提交--%>
<form action="converter/student" method="post">
<%--给输入的样式一个格式--%>
请输入学生的对象:<input type="text" name="student">(id-name-age)<br>
<input type="submit" value="提交"/>
</form>
</body>
</html>
student类要是不放在entity包下,这里就无法传入会报错
/*在handle里面实现方法*/
// 在controller里面处理程序handle:处理程序的英文
@RequestMapping("/student")
public String student(Student student){
return student.toString();
}
之所以为空是因为没有使用转换器进行转换。写一个转换器
package com.zhou.converter;
import com.zhou.entity.Student;
import org.springframework.core.convert.converter.Converter;
public class StudentConverter implements Converter<String,Student> {
@Override
public Student convert(String s) {
// 字符串"1-张三-23"转成Student对象。Student(id=null, name=null, age=0)
// 也就是说把这个数据分割,遍历出来,然后再实例化即可
// {“1”,"张三",“23”}这样就是数组的第一个就是id,第二个是姓名
// 分割split
String[] args = s.split("-");
Student student = new Student();
// 取出来之后还是String类型,要转换成Long类型,搞成包装类,parseLong类型
student.setId(Long.parseLong(args[0]));
student.setName(args[1]);
student.setAge(Integer.parseInt(args[2]));
return student;
}
}
在Spring.xml中进行自定义转换器的配置
<!-- 配置⾃自定义转换器器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.zhou.converter.DateConverter">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd">
</constructor-arg>
</bean>
<!--因为这个是通过无参去调用-->
<bean class="com.zhou.converter.StudentConverter"/>
</list>
</property>
</bean>
测试
SpringMVC REST
REST:资源表现层状态转换,是目前比较主流的一种互联网软件架构,结构清晰,标准规范,易于理解,便与扩展。
- 资源:网上存在的一个具体的信息,都可以看成是一个具体的资源,可以使用URL(统一资源定位符)指向它,每个资源都有对应的一个特定的URI,要获取资源的时候,只需要访问对应的URI即可。
- 表现层:资源呈现出来的形式,比如:文本可以用txt格式表示,也可以是可用HTML,XML,JSON等格式来表示
- 状态转换:客户端如果希望操作服务器中的某个资源,就需要通过某种方式让服务端发生状态转换,这种转换是建立在表现层之上的,所有的表现层状态。
特点:URL更加的简洁
有利于不同的系统之间的资源共享,只需要遵守一定得规范,不需要进行其他的配置即可实现资源的共享。
如何使用:REST具体的操作就是HTTP协议中四个表示操作方式对应CRUD基本操作,
GET:用来表示获取资源。
POST:用来表示新建的资源
PUT:用来表示修改资源
DELETE:用来表示删除资源
repository包:相当于dao的组件,操作数据库的
在repository:下创建一个操纵Student的StudenConverter
package com.zhou.repository;
import com.zhou.entity.Student;
import java.util.Collection;
public interface StudentRepositroy {
/*repository是资源操作数据库类似dao的功能,*/
// 增删改查,使用接口去实现
// 1.查询返回全部的数据, Collection容器,使用容器来存
Collection<Student> findAll();
// 还有一种是通过id去查具体的
Student findById(long id);
// 增,新增,指的是数据库多了一条,所以返回值是int,我觉得可以是int表示
// 这里添加和修改写到一个方法中,这样的话,使用void比较合适
void saveOrUpdate(Student student);
// 删除
void deleteById(long id);
}
实现类
package com.zhou.repository.impl;
import com.zhou.entity.Student;
import com.zhou.repository.StudentRepositroy;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
// 然后要把这个数据注入到handle中
@Repository
public class StudentRepositoryImpl implements StudentRepositroy {
// 定义一个静态的集合,来模拟数据库,dao层的实现类就是操作数据库中的数据的
private static Map<Long, Student> studentMap;
static{
// 在静态代码块中实例化数据,实例化map
studentMap = new HashMap<>();
// 在map中多添加几个数据来模拟数据库
studentMap.put(1L,new Student(1L,"张三",22));
studentMap.put(2L,new Student(2L,"李四",23));
studentMap.put(3L,new Student(3L,"王五",24));
}
@Override
public Collection<Student> findAll() {
return studentMap.values(); // 这个是返回整个容器
}
@Override
public Student findById(long id) {
return studentMap.get(id);
}
@Override
public void saveOrUpdate(Student student) {
studentMap.put(student.getId(),student);
}
@Override
public void deleteById(long id) {
studentMap.remove(id);
}
}
在controller包下创建一个Handle处理程序的controller对象
RESTHandler
package com.zhou.controller;
import com.zhou.entity.Student;
import com.zhou.repository.StudentRepositroy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
//@Controller
@RestController // 把结果直接返回
@RequestMapping("/rest")
public class RESTHandle {
@Autowired // 通过类型注入到ioc容器里面
private StudentRepositroy studentRepositroy;
/*查真正的数据,先对数据进行处理,repository,dao的组件,先写repository*/
// 查询所有的student数据
@RequestMapping("/findAll")
public Collection<Student> findAll(){
return studentRepositroy.findAll();
}
// 写好一个方法就测试一个,我的并没有乱码
// 通过id来查询,这个是使用REST风格的URL,需要指定参数@PathVariable
@GetMapping("/findById/{id}")
public Student findById(@PathVariable("id") long id){
return studentRepositroy.findById(id);
}
// 增改这种是属于Post请求,因为不止改多个元素,post请求比较好
@PostMapping("/save")
// 因为传过来的请求参数是json数据,所以需要加@RequestBody注释
public void save(@RequestBody Student student){
studentRepositroy.saveOrUpdate(student);
}
// 删除
@DeleteMapping("/deleteById/{id}")
public void deleteById(@PathVariable("id") long id){
// void是没有返回return的
studentRepositroy.deleteById(id);
}
}
测试
post请求使用工具去测,postman,因为需要传多个数据,在没有表单的情况使用工具室比较好的。
SpringMVC文件上传
- 单文件上传
上传:把客户端的资源上传到服务器
底层是使用Apache fileupload组件完成上传,Spring MVC对这种方式进行了封装
pom.xml:需要加io流和fileupload文件上传下载依赖
<!--需要HttpServletRequest request需要引入javax.servlet-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--io流 commons-io-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!--文件上传和下载依赖fileupload-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
上传的话,肯定是通过页面给用户提供一个上传的入口,所以写个jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--上传下载通过表单来完成,multipart多部分,--%>
<form action="/file/upload" method="post" enctype="multipart/form-data">
上传个图片:<input type="file" name="img"/>
<input type="submit" value="上传"/>
</form>
<%--如果要让上传的图片进行显示,则加个img标签,然后给个动态的标签--%>
<img src="${path}">
</body>
</html>
注意事项:1.input的type类型设置为file是文件的格式,之前名字是text上面放的是文字,这个需要放文件所以type=“file”
2. method方法是post,get方法只能将文件名传给服务器,这个文件是需要post
3. from的enctype设置为multipart-from-data这个是,如果不设置只能将文件名传给服务器。
- Handle方法,后台的业务代码,让文件上传的方法
package com.zhou.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
@Controller
@RequestMapping("/file")
public class FileHandle {
// handle处理程序
// 文件上传处理程序程序
// 把表单提交的图的二进制代码会传到后台代码,需要一个接受对象,最后是要展示一个也买你的,所以返回值是String
// @RequestMapping("/upload")
// 没有指定Post方法,所以没反应
@PostMapping("/upload")
public String upload(MultipartFile img, HttpServletRequest request){
// 接收它,即保存,首先判断过来的对象是否为空
if(img.getSize()>0){
// 过来的参数是二进制文件,所以可以看图片的大小,getSize
// 获取保存上传文件的file路径,也就是从哪里上传的文件名,文件所在地的文件夹
// <!--需要HttpServletRequest request需要引入javax.servlet-api-->
String path = request.getServletContext().getRealPath("file");
// 获取上传文件夹里面的文件名,即图片的文件名,获取原始的文件名
String name = img.getOriginalFilename();
// 结合存放的路径,构建新的文件名称。
File file = new File(path, name); // 在这个path路径新创建一个name的名字的文件,此时这个文件为空,还需要进行写入
// 判断路径是否存在,不存在则新创建一个
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
System.out.println("创建目录" + file);
}
// 文件上传到目标文件目录中
try {
// 把img的内容转入到file文件中
img.transferTo(file);
// 保存上传之后的文件路径
request.setAttribute("path","/file/"+name);
} catch (IOException e) {
e.printStackTrace();
}
}
return "upload";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--上传下载通过表单来完成,multipart多部分,--%>
<form action="/file/upload" method="post" enctype="multipart/form-data">
上传个图片:<input type="file" name="img"/>
<input type="submit" value="上传"/>
</form>
<%--如果要让上传的图片进行显示,则加个img标签,然后给个动态的标签--%>
<img src="${path}">
</body>
</html>
spring和web.xml的配置
<!--把.png文件不过滤-->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
spring.xml上传配置
<!--需要配置上传组件-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
多文件上传
只需要把jsp页面改成上传多个文件的jsp
uploads.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--表达式忘记加了,所以那个图片加载不出来--%>
<%@ page isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/file/uploads" method="post" enctype="multipart/form-data">
第一个文件file1:<input type="file" name="imgs"><br>
第二个文件file2:<input type="file" name="imgs"><br>
第三个文件file3:<input type="file" name="imgs"><br>
<%--上传按钮--%>
<input type="submit" value="上传">
</form>
<%--让上传的图片显示,多个,所以需要遍历--%>
<c:forEach items="${files}" var="file">
<img src="${file}" width="300px"/>
</c:forEach>
</body>
</html>
/*上传多个文件*/
@PostMapping("/uploads")
/*数组的形式来传[]*/
public String uploads(MultipartFile[] imgs,HttpServletRequest request){
/*定义一个集合来存多个路径*/
List<String> files = new ArrayList<>();
// 遍历数组imgs
for (MultipartFile img : imgs) {
// 现在img就是单个文件了,所以可以和上面一样
// 接收它,即保存,首先判断过来的对象是否为空
if(img.getSize()>0){
// 过来的参数是二进制文件,所以可以看图片的大小,getSize
// 获取保存上传文件的file路径,也就是从哪里上传的文件名,文件所在地的文件夹
// <!--需要HttpServletRequest request需要引入javax.servlet-api-->
String path = request.getServletContext().getRealPath("file");
// 获取上传文件夹里面的文件名,即图片的文件名,获取原始的文件名
String name = img.getOriginalFilename();
// 结合存放的路径,构建新的文件名称。
File file = new File(path, name); // 在这个path路径新创建一个name的名字的文件,此时这个文件为空,还需要进行写入
// 判断路径是否存在,不存在则新创建一个
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
System.out.println("创建目录" + file);
}
// 文件上传到目标文件目录中
try {
// 把img的内容转入到file文件中
img.transferTo(file);
// 保存上传之后的文件路径
// 这个路径不止一个,有多个,所以定义一个list集合来存
files.add("/file/"+name);
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 遍历完了后,路径会存到数组中,然后发送到request域中
request.setAttribute("files",files);
return "uploads";
}
下载,不太懂,等二刷了io流再回来
<%--
Created by IntelliJ IDEA.
User: southwind
Date: 2019-03-15
Time: 10:36
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>
<a href="/file/download/1">1.png</a>
<a href="/file/download/2">2.png</a>
<a href="/file/download/3">3.png</a>
</body>
</html>
handle
@GetMapping("/download/{name}")
public void download(@PathVariable("name") String name, HttpServletRequest
request, HttpServletResponse response){
if(name != null){
name += ".png";
String path = request.getServletContext().getRealPath("file");
File file = new File(path,name);
OutputStream outputStream = null;
if(file.exists()){
response.setContentType("application/forc-download");
response.setHeader("ContentDisposition","attachment;filename="+name);
try {
outputStream = response.getOutputStream();
outputStream.write(FileUtils.readFileToByteArray(file));
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
Spring MVC表单标签库
另外2的老师好像也没讲,以后再学,还有表单校验也一起以后又需要再
- handle运行程序