SpringMVC
文章目录
1. 什么是MVC
MVC:
model 模型(dao,service)执行业务,保存数据
view 视图(jsp) : 显示页面
Controller 控制器(Servlet) :获得前端数据,调用业务,页面跳转
这是一种规范
1.1 回顾servlet
jar包:
<!-- Jstl 表达式 依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- servlet 依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- jsp 依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
编写servlet类
//1.从前端获得参数
String method = req.getParameter("method");
if (method.equals("add")){
req.setAttribute("hello","执行add方法");
}else if (method.equals("delete")){
req.setAttribute("hello","执行了delete方法");
}
//2.交给业务层去做
//3.视图跳转
req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
在web.xml中注册
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.liang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
启动tomcat 测试
http://localhost:8080/hello?method=delete
http://localhost:8080/hello?method=add
1.2 MVC框架要做哪些事
1.将url映射到java类或者java类的方法
2.封装用户提交的数据
3.处理请求——调用相关业务处理——封装响应数据
4.将响应的数据进行渲染 jsp/html等表示层数据
2. 初识springMVC
基于Java实现MVC的轻量级web框架
2.1 为什么要学springMVC
1.轻量级,简单好学
2.高效,基于请求响应的MVC框架
3.与Spring兼容性好,无缝结合
4.预定大于配置
5.功能强大
中心控制器:
spring的web框架围绕DispatcherServlet(调度servlet)设计
DispatchaerServlet的作用:将请求分发到不同的处理器
以请求为驱动,围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet(他继承自HttpServlet基类)
2.2 spring MVC原理:(重点)
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器再将结果返回给请求者
1.DispatcherServlet表示前端控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
- 我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
- 如上url拆分成三部分:
- http://localhost:8080服务器域名
- SpringMVC部署在服务器上的web站点
- hello表示控制器
- 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
2.HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
3.HandlerExecution表示具体的Handler其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
4.HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
5.HandlerAdapter表示处理器适配器,(寻找hangdler到底对应哪个controller)其按照特定的规则去执行Handler。
6.Handler让具体的Controller执行。
7.Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
8.HandlerAdapter将视图逻辑名或模型(需要跳转的页面和传递的数据)传递给DispatcherServlet。
9.DispatcherServlet调用**视图解析器(ViewResolver)**来解析HandlerAdapter传递的逻辑视图名。
10.视图解析器将解析的逻辑视图名传给DispatcherServlet。
11.DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
12.最终视图呈现给用户
2.3 HelloSpringMVC
配置web.xml
<?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">
<!--1.注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--启动级别-1-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--/ 匹配所有的请求;(不包括.jsp)-->
<!--/* 匹配所有的请求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
编写SpringMVC 的 配置文件!名称:springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
</beans>
添加 处理映射器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
添加 处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
添加 视图解析器
<!--视图解析器:DispatcherServlet给他的ModelAndView
获取ModelAndView的数据
解析ModelAndView的视图名字
拼接视图名字 /WEB_INF/jsp/hello.jsp
将数据渲染到视图上,呈现视图
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;
//注意:这里我们先导入Controller接口
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();
//封装对象,放在ModelAndView中。Model
mv.addObject("hello","HelloSpringMVC!");
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
return mv;
}
}
将自己的类交给SpringIOC容器,注册bean
<!--Handler-->
<bean id="/hello" class="com.liang.controller.HelloController"/>
写要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面
(坑)注意:
2.4 注解版 HelloSpringMVC
- 搭建环境
导入jar包
防止资源过滤
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
2.配置web.xml(web.xml必须用最新版本4.0)
<?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">
<!--1.注册servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 启动顺序,数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有请求都会被springmvc拦截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
编写springmvc-servlet.xml 的配置:
- 让ioc注解生效
- 静态资源过滤:HTML,JS,CSS
- MVC注解驱动(处理器映射器,处理器适配器)
- 配置视图解析器
<?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.liang.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/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
创建Controller
@org.springframework.stereotype.Controller
public class Controller {
// 访问地址: localhost:8080/hello
@RequestMapping("/hello")
public String hello(Model model){
//向模型中添加数据 会在jsp页面渲染视图
model.addAttribute("hello", "Hello!SpringMVCannotation!");
// 视图解析器完成解析后: WEB_INF/jsp/hello.jsp
return "hello";
}
}
-
@org.springframework.stereotype.Controller 为了让spring IOC容器初始化能够自动扫描到(被注释的类,所有方法中如果返回String且有这个页面可以跳转,就会被视图解析器解析)
-
@RequestMapping是为了映射请求路径
-
方法中的参数是为了把数据带到视图
-
方法中的返回结果是视图名称 加上前后缀就是:WEB_INF/jsp/hello.jsp
最后创建视图层 ,启动tomcat测试
使用SpringMVC 必须配置三大件:处理器映射器(HandlerMapping),处理器适配器(HandlerAdapter),视图解析器(ViewResolver)
通常,我们只需要手动配置视图解析器,而处理器映射器和处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置
3. RestFul 风格
3.1 功能
资源:互联网所有事物都可以被抽象为资源
资源操作:使用POST(添加),DELETE(删除),PUT(修改),GET(查询),使用不同方法对资源进行操作
3.2 对比传统方式
传统方式操作资源:通过不同的参数来实现不同效果,方法只有post,get
RestFul操作资源:通过不同的请求方式来实现不同的效果(请求地址一样,但是可以实现不同功能)
@Controller
public class Restful {
@RequestMapping("/test/{a}/{b}")
public String test(@PathVariable int a,@PathVariable int b, Model model){
//传统方式url: http://localhost:8080/test?a=1&b=1
//Restful方式url: http://localhost:8080/test/1/1
int count = a + b;
model.addAttribute("test","总计:"+count);
return "test";
}
}
注释: @PathVariable 用来在浏览器输入的值绑定该方法的参数
Restful还可以使用method属性指定请求类型(这里指定GET方法)
@RequestMapping(value = "/test/{a}/{b}",method = RequestMethod.GET)
等价于
@GetMapping("/test/{a}/{b}")
小结:
SpringMVC 的@RequestMapping注解能够处理HTTP请求的方法(GET, PUT, POST, DELETE 以及 PATCH)
@RequestMapping
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
4. 结果跳转方式
真正页面地址:视图解析器前缀+viewname+视图解析器后缀
4.1 通过SpringMVC实现转发与重定向
无视图解析器时(需要写的路径非常麻烦):
//转发
return "forward:/WEB-INF/jsp/test.jsp";
//重定向
return "redirect:/WEB-INF/jsp/test.jsp";
有视图解析器时(不仅可以重定向路径还可以重定向一个请求):
//转发
return "test";
//重定向 一个路径
return "redirect:/index.jsp";
//重定向 一个请求 hello.do为另一个请求/
return "redirect:hello.do";
重定向不需要视图解析,因为本来就是重新请求一个新地方,所以注意路径问题
默认[forward:] 不用写
5. 数据处理
5.1 前端参数
参数相同
提交数据:http://localhost:8080/param1?name=chenliang
@Controller
public class Params {
@RequestMapping("/param1")
public String param01(String name, Model model){
//获取前端参数
System.out.println(name);
//视图跳转
return "param";
}
}
后台显示:chenliang
参数不同
提交数据:http://localhost:8080/param1?username=chenliang
@Controller
public class Params {
@RequestMapping("/param1")
public String param01(@RequestParam("username") String name, Model model){
//获取前端参数
System.out.println(name);
//视图跳转
return "param";
}
}
前端显示:{username=chenliang}
参数是对象
提交数据:http://localhost:8080/param1?username=chenliang&age=18&sex=boy
@Controller
public class Params {
@RequestMapping("/param1")
public String param01(User user, Model model){
//获取前端参数
System.out.println(user);
//视图跳转
return "param";
}
}
后台显示:{username=chenliang,age=18,sex=boy}
如果参数是一个对象,传递的参数名要和对象的字段名一致,不然为null
注意:
最好都打注释@RequestParam,方便查看前端传递参数是什么
5.2 数据显示到前端
第一种:ModelAndView
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一个模型视图对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}
第二种:ModelMap
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("name",name);
System.out.println(name);
return "hello";
}
第三种:Model
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
对比:
-
Model 只适合用于储存数据
-
ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;
-
ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
5.3 乱码问题
SpringMVC为我们提供的过滤器
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
如有极端方式(自定义过滤器):
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* 解决get和post请求 全部乱码的过滤器
*/
public class GenericEncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//处理response的字符编码
HttpServletResponse myResponse=(HttpServletResponse) response;
myResponse.setContentType("text/html;charset=UTF-8");
// 转型为与协议相关对象
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 对request包装增强
HttpServletRequest myrequest = new MyRequest(httpServletRequest);
chain.doFilter(myrequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
//是否编码的标记
private boolean hasEncode;
//定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
public MyRequest(HttpServletRequest request) {
super(request);// super必须写
this.request = request;
}
// 对需要增强方法 进行覆盖
@Override
public Map getParameterMap() {
// 先获得请求方式
String method = request.getMethod();
if (method.equalsIgnoreCase("post")) {
// post请求
try {
// 处理post乱码
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if (method.equalsIgnoreCase("get")) {
// get请求
Map<String, String[]> parameterMap = request.getParameterMap();
if (!hasEncode) { // 确保get手动编码逻辑只运行一次
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
// 处理get乱码
values[i] = new String(values[i]
.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
//取一个值
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回参数的第一个值
}
//取所有值
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
6. JSON
6.1 什么是JSON
JSON(JavaScript Object Notation, JS 对象标记)是一种轻量级的数据交换格式,使用广泛
采用完全独立于编程语言的文本格式来存储,表示数据
简单,结构清晰,易于人阅读编写,机器解析生成,提高网络传输效率
6.2 JSON语法格式
- 对象表示为键值对,数据用逗号分隔
- 花括号保存对象
- 方括号保存数组
6.3 使用Jackson
导入Jar包
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
web.xml
<?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">
<!--1.注册servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 启动顺序,数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有请求都会被springmvc拦截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
</web-app>
springmvc-servlet.xml
<?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"/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
乱码解决
第一种(固定不变):
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
第二种:
//produces:指定响应体返回类型和编码
@RequestMapping(value = "/json1",produces = "application/json;charset=utf-8")
编写实体类User
(略)
编写Controller
//@RestController 在类上使用后,此类所有方法返回结果为json字符串 不用每个方法都加注释@ResponseBody(将str转成json格式返回)
@Controller
public class UserController {
@RequestMapping("/json1")
@ResponseBody
public String json1() throws JsonProcessingException {
//创建一个jackson的对象映射器,用来解析数据
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
User user1 = new User("张三", 3, "男");
User user2 = new User("李四", 3, "男");
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(list);
return str;
}
}
结果:
[{"name": "张三","age": "3","sex": "男"},{"name": "李四","age": "3","sex": "男"}]
输出时间对象
- 默认日期格式会变成一个数字,是1970年1月1日到当前日期的毫秒数!
- Jackson 默认是会把时间转成timestamps(时间戳)形式
@RequestMapping("/json3")
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//创建时间一个对象,java.util.Date
Date date = new Date();
//自定义日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
//将我们的对象解析成为json格式
String str = mapper.writeValueAsString(sdf.format(date));
return str;
}
6.4 使用FastJson
导入依赖:
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.4</version>
</dependency>
FastJson三个主要的类:
- 【JSONObject 代表 json 对象 】
- JSONObject实现了Map接口, 猜想 JSONObject底层操作是由Map实现的。
- JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键:值"对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。
- 【JSONArray 代表 json 对象数组】
- 内部是有List接口中的方法来完成操作的。
- 【JSON 代表 JSONObject和JSONArray的转化】
- JSON类源码分析与使用
- 仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。
//创建一个对象
User user1 = new User("秦疆1号", 3, "男");
User user2 = new User("秦疆2号", 3, "男");
User user3 = new User("秦疆3号", 3, "男");
User user4 = new User("秦疆4号", 3, "男");
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
System.out.println("*******Java对象 转 JSON字符串*******");
String str1 = JSON.toJSONString(list);
System.out.println("JSON.toJSONString(list)==>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)==>"+str2);
System.out.println("\n****** JSON字符串 转 Java对象*******");
User jp_user1=JSON.parseObject(str2,User.class);
System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
System.out.println("\n****** Java对象 转 JSON对象 ******");
JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));
System.out.println("\n****** JSON对象 转 Java对象 ******");
User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
后台显示:
Java对象 转 JSON字符串
JSON.toJSONString(list)>[{“age”:3,“name”:“秦疆1号”,“sex”:“男”},{“age”:3,“name”:“秦疆2号”,“sex”:“男”},{“age”:3,“name”:“秦疆3号”,“sex”:“男”},{“age”:3,“name”:“秦疆4号”,“sex”:“男”}]
JSON.toJSONString(user1)>{“age”:3,“name”:“秦疆1号”,“sex”:“男”}
****** JSON字符串 转 Java对象*******
JSON.parseObject(str2,User.class)==>User{age=3, name=‘秦疆1号’, sex=‘男’}
****** Java对象 转 JSON对象 ******
(JSONObject) JSON.toJSON(user2)==>秦疆2号
****** JSON对象 转 Java对象 ******
JSON.toJavaObject(jsonObject1, User.class)==>User{age=3, name=‘秦疆2号’, sex=‘男’}
7. 整合SSM
7.1 数据库环境
CREATE DATABASE `ssmbuild`;
USE `ssmbuild`;
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books` (
`bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名',
`bookCounts` INT(11) NOT NULL COMMENT '数量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢');
7.2 环境搭建
依赖:
-
<dependencies> <!--Junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!--数据库驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <!-- 数据库连接池 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <!--Servlet - JSP --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--Mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.2</version> </dependency> <!--Spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.1.9.RELEASE</version> </dependency> </dependencies>
静态资源过滤
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
建立基本结构和配置框架
-
com.liang.pojo
-
com.liang.dao
-
com.liang.service
-
com.liang.controller
-
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> </configuration>
-
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" 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"> </beans>
7.3 Mybatis层
1. 数据库配置文件 database.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
2. idea关联数据库
3.实体类
public class Books {
private int bookID;
private String bookName;
private int bookCounts;
private String detail;
//set,get,构造,tostring
}
4. Mybatis核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置数据源,交给spring去做 -->
<typeAliases>
<package name="com.liang.pojo"/>
</typeAliases>
<!-- 注册mapper-->
<mappers>
<mapper class="com.liang.dao.BookMapper"/>
</mappers>
</configuration>
5. Dao层BookMapper接口
public interface BookMapper {
//增加一本书
int addBooks(Books books);
//删除一本书
int deleteBookByid(@Param("bookID") int id);
//更新一本书
int updateBook(Books books);
//查询一本书
Books queryBook(@Param("bookID") int id);
//查询全部的书
List<Books> queryAllBook();
}
6. BookMapper接口对应的Mapper.xml文件
此文件的头文件只需要将mybatis核心配置文件做出一下调整即可
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.liang.dao.BookMapper">
<insert id="addBooks" parameterType="Books">
insert into ssmbuild.books (bookName, bookCounts, detail)
values (#{bookName},#{bookCounts},#{detail});
</insert>
<delete id="deleteBookByid" parameterType="int">
delete from ssmbuild.books where ssmbuild.books.bookID = #{bookID}
</delete>
<update id="updateBook" parameterType="Books">
update ssmbuild.books
set bookName =#{bookName} ,bookCounts = #{bookCounts},detail =#{detail}
where bookID=#{bookID};
</update>
<select id="queryBook" resultType="Books">
select * from ssmbuild.books where bookID=#{bookID};
</select>
<select id="queryAllBook" resultType="Books">
select * from ssmbuild.books;
</select>
</mapper>
注意:每次写完Mapper.xml文件就应该去mybatis核心配置文件进行注册
7. Service层接口
public interface BookService {
//增加一本书
int addBooks(Books books);
//删除一本书
int deleteBookByid(int id);
//更新一本书
int updateBook(Books books);
//查询一本书
Books queryBook(int id);
//查询全部的书
List<Books> queryAllBook();
}
8. Service层 接口实现类
public class BookServiceImpl implements BookService {
//因为要调用dao 所以引入
private BookMapper bookMapper;
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
public int addBooks(Books books) {
return bookMapper.addBooks(books);
}
public int deleteBookByid(int id) {
return bookMapper.deleteBookByid(id);
}
public int updateBook(Books books) {
return bookMapper.updateBook(books);
}
public Books queryBook(int id) {
return bookMapper.queryBook(id);
}
public List<Books> queryAllBook() {
return bookMapper.queryAllBook();
}
}
7.4 Spring层
1.spring整合mybatis配置文件 spring-dao.xml
此文件的头文件只需将application.xml头文件进行调整
<?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"
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">
<!-- 1.读取资源文件 -->
<context:property-placeholder location="classpath:detebase.properties"/>
<!-- 2.数据库连接池-->
<bean id="database" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 关闭连接后不自动commit -->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 当获取连接失败重试次数 -->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!-- 3.配置sqlSessionFactory对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池-->
<property name="dataSource" ref="database"/>
<!-- 配置MyBaties全局配置文件:mybatis-config.xml-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 给出需要扫描的dao接口包 后面 -->
<property name="basePackage" value="com.liang.dao"/>
</bean>
</beans>
2. spring整合service层 spring-service.xml
此文件头文件如spring-dao.xml一致
<?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"
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">
<!--1. 扫描service相关的bean -->
<context:component-scan base-package="com.liang.service"/>
<!--2.BookServiceImpl注入到IOC容器中-->
<bean id="BookServiceImpl" class="com.liang.service.BookServiceImpl">
<!--这里的bokkMapper 是spring-dao.xml中4.配置扫描dao接口包那里 扫描过来的 -->
<property name="bookMapper" ref="bookMapper"/>
</bean>
<!--3.配置事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<!--注入数据库连接池-->
<property name="dataSource" ref="database"/>
</bean>
<!--4.aop事务 -->
</beans>
7.5 SpringMVC层
1. web.xml
<?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">
<!-- DispatcherServlet-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Filter-->
<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>
<!--Session过期时间-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
2. spring-mvc.xml
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解驱动-->
<mvc:annotation-driven/>
<!-- 过滤静态资源-->
<mvc:default-servlet-handler/>
<!--视图解析-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 扫描包-->
<context:component-scan base-package="com.liang.controller"/>
</beans>
3. spring整合配置文件 application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="spring-mvc.xml"/>
</beans>
7.6 增删改查
@Controller
@RequestMapping("/book")
public class BookController {
//要调用业务层就要先引入
@Autowired
@Qualifier("BookServiceImpl")
private BookService bookService;
//查询所有书
@RequestMapping("/allbook")
public String query(Model model){
List<Books> list = bookService.queryAllBook();
model.addAttribute("list",list);
return "allbook";
}
//点击新增
@RequestMapping("/toAddBook")
public String toAddBook(){
return "addBook";//进入新增书籍页面
}
@RequestMapping("/addBook")
public String add(Books books){
System.out.println(books);
bookService.addBooks(books);//数据库添加这个books
return "redirect:/book/allbook";
}
//点击更改
@RequestMapping("/toUpdateBook")
public String toUpdateBook(int id,Model model){
Books books = bookService.queryBook(id);
System.out.println(books);
model.addAttribute("book",books);//给前端传一个默认值(也就是要修改的那个他自己)
return "updateBook";//进入更改页面
}
@RequestMapping("/updateBook")
public String updateBook(Books book,Model model){
bookService.updateBook(book);
int bookID = book.getBookID();
Books books = bookService.queryBook(bookID);
model.addAttribute("book",books);
System.out.println(books);
return "redirect:/book/allbook";
}
//点击删除
@RequestMapping("/del/{id}")
public String del(@PathVariable int id){
bookService.deleteBookByid(id);
return "redirect:/book/allbook";
}
}
8. 拦截器
SpringMVC的处理器拦截器:HandlerInterceptor
类似Servlet开发中的过滤器
过滤器
- servlet的一部分,任何java web工程都可以用
- 配置/*后,可以对所有要访问的资源进行拦截
拦截器
- 是SpringMVC框架自有的,使用SpringMVC框架工程才可以用
- 拦截器只会拦截访问的控制器方法,若访问的是jsp/image/html/css/js
等是不会进行拦截的
- 拦截器是AOP思想(面向切面编程)
拦截器必须实现HanlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//返回 true 为通过 ,false为拦截(不通过)
System.out.println("执行前============================");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("执行后==============================");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("清理");
}
}
在配置文件中配置拦截器
<!--拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
<!--/admin/** 拦截的是/admin/下的所有-->
<mvc:mapping path="/**"/>
<bean class="com.liang.Interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
编写控制器
@Controller
public class Interceptor {
@RequestMapping("interceptor")
public String test(){
System.out.println("控制器的方法执行了!");
return "interceptor";
}
}
后台显示:
执行前============================
控制器的方法执行了!
执行后==============================
清理
8.1 登录判断验证
控制器
@Controller
@RequestMapping("user")
public class LoginController {
//点击登录
@RequestMapping("jumplogin")
public String jumplogin(){
return "login";
}
@RequestMapping("login")
public String login(String username, String pwd, HttpSession session){
System.out.println("接受前端信息:"+username+":"+pwd);
session.setAttribute("UserName",username);//为了方便拦截器判断用户是否登录
return "succussful";
}
@RequestMapping("logout")
public String logout(HttpSession session){
session.invalidate();//点击注销 注销session
return "redirect:/index.jsp";
}
@RequestMapping("jumpSuccess")
public String jumpSuccess(){
return "succussful";
}
}
拦截器
public class MyInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (request.getRequestURI().contains("jumplogin")){
return true;//点击登录 不拦截
} else if (request.getRequestURI().contains("login")){
return true;//点击提交用户名密码时 不拦截
}else if (request.getSession().getAttribute("UserName")!=null){
return true;//如果有用户信息则不拦截
}else {
response.sendRedirect("/error.jsp");
return false;
}
}
}
配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<bean class="com.liang.Interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
9. 文件上传与下载
9.1 文件上传
-
前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;
-
后台:SpringMVC上下文中默认没有装配MultipartResolver,为了实现文件上传,需要在上下文中配置MultipartResolver
导入jar包:
<!--文件上传-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
配置bean:multipartResolver(这个bena的id必须为:multipartResolver)
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上传文件大小上限,单位为字节(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
CommonsMultipartFile 的 常用方法:
- String getOriginalFilename():获取上传文件的原名
- InputStream getInputStream():获取文件流
- void transferTo(File dest):将上传文件保存到一个目录文件中
控制器(第一种方式):
@Controller
public class FileController {
//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//获取文件名 : file.getOriginalFilename();
String uploadFilename = file.getOriginalFilename();
//如果文件名为空,直接回首页
if ("".equals(uploadFilename)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名:"+uploadFilename);
//上传路径保存设置 先获得servlet容器(tomcat容器) 再获取 在容器中的实际发布运行的根路径
String path = request.getSession().getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();//创建
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream();//文件输入流
OutputStream os = new FileOutputStream(new File(realPath, uploadFilename));//文件输出流
//读取写出
int len = 0;
byte [] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
}
第二种方式(采用file.Transto)
*
* 采用file.Transto 来保存上传的文件
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
System.out.println("上传文件保存地址:"+realPath);
//通过CommonsMultipartFile的方法直接写文件(注意这个时候)
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
return "redirect:/index.jsp";
}
9.2 文件下载
@Controller
public class FileController {
//上传文件
//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//获取文件名 : file.getOriginalFilename();
String uploadFilename = file.getOriginalFilename();
//如果文件名为空,直接回首页
if ("".equals(uploadFilename)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名:"+uploadFilename);
//上传路径保存设置 先获得servlet容器(tomcat容器) 再获取 在容器中的实际发布运行的根路径
String path = request.getSession().getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();//创建
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream();//文件输入流
OutputStream os = new FileOutputStream(new File(realPath, uploadFilename));//文件输出流
//读取写出
int len = 0;
byte [] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
//下载文件
@RequestMapping("/download")
public String download(HttpServletRequest request, HttpServletResponse response) throws IOException {
//要下载的图片地址 只需要变这里的代码 地址与名字
String path = request.getSession().getServletContext().getRealPath("/upload");
String fileName = "QQ截图20200222224904.png";
//1.设置响应头
response.reset();//不缓存 清空buffer
response.setCharacterEncoding("UTF-8");
response.setContentType("multipart/form-data");//二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path, fileName);
//2.读取文件--输入流
InputStream input = new FileInputStream(file);
//3.写出文件--输出流
OutputStream out = response.getOutputStream();
byte[] buff = new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}
}
oadFilename);
//上传路径保存设置 先获得servlet容器(tomcat容器) 再获取 在容器中的实际发布运行的根路径
String path = request.getSession().getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();//创建
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream();//文件输入流
OutputStream os = new FileOutputStream(new File(realPath, uploadFilename));//文件输出流
//读取写出
int len = 0;
byte [] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
//下载文件
@RequestMapping("/download")
public String download(HttpServletRequest request, HttpServletResponse response) throws IOException {
//要下载的图片地址 只需要变这里的代码 地址与名字
String path = request.getSession().getServletContext().getRealPath("/upload");
String fileName = "QQ截图20200222224904.png";
//1.设置响应头
response.reset();//不缓存 清空buffer
response.setCharacterEncoding("UTF-8");
response.setContentType("multipart/form-data");//二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path, fileName);
//2.读取文件--输入流
InputStream input = new FileInputStream(file);
//3.写出文件--输出流
OutputStream out = response.getOutputStream();
byte[] buff = new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}
}
来源:CSDN
作者:Tc.l
链接:https://blog.csdn.net/Tc_lccc/article/details/104512776