MVC三层架构:
模型(Model)、view(视图)、控制器(Controller),是一种软件设计规范!
- 将业务逻辑、数据、显示分离的方法来组织代码
- mvc只要作用是降低视图与业务逻辑间的双向耦合
- mvc不是设计模式,是一种架构模式
Controller:控制器
- 取得表单数据
- 调用业务逻辑
- 转向指定的页面
Model:模型
- 业务逻辑
- 保存数据的状态
View:视图
- 显示页面
官方文档:Web on Servlet Stack (spring.io)
1、回顾servlet
1.1 创建maven项目
1.导入依赖包:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<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.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2.创建普通的maven项目后要将新建的模块右键添加为web项目
出现web的项目文件才创建完成!
1.2 创建项目
1.servlet层
package com.liu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取前端参数
String method = req.getParameter("method");
if (method.equals("add")){
req.getSession().setAttribute("msg","执行了add方法");
}
if (method.equals("delete")){
req.getSession().setAttribute("msg","执行了delete方法");
}
//2.调取业务层
//3.视图转发或重定向
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2.创建跳转的页面jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
3.在web.xml里配置servlet映射路径
<?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">
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.liu.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!-- <session-config>-->
<!-- <session-timeout>15</session-timeout>-->
<!-- </session-config>-->
<!-- -->
<!-- <welcome-file-list>-->
<!-- <welcome-file>index.jsp</welcome-file>-->
<!-- </welcome-file-list>-->
</web-app>
4.创建一个提交表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/hello" method="post">
<input type="text" name="method">
<input type="submit">
</form>
</body>
</html>
回顾form表单的各属性值
input 标签的 value 属性的作用是由 input 标签的 type 属性的值决定的
当 type 的取值为 button、reset、submit 中的其中一个时,此时 value 属性的值表示的是按钮上显示的文本
当 type 的取值为 text、password、hidden 中的其中一个时,此时 value 属性的值表示的是输入框中显示的初始值,此初始值可以更改,并且在提交表单时,value 属性的值会发送给服务器(既是初始值,也是提交给服务器的值)
当 type 的取值为 checkbox、radio 中的其中一个时,此时 value 属性的值表示的是提交给服务器的值
当 type 的取值为 image 时,点击它提交表单后,会将用户的点击位置相对于图像左上角的 x 坐标和 y 坐标提交给服务器
- 当设置 input 标签的 type 属性值为checkbox 或者 radio 时,必须同时设置 input 标签的 value 属性。
- 当 type=“file” 时,不能使用 value 属性
- name 属性规定 input 元素的名称
- name 属性用于对提交到服务器后的表单数据进行标识,或者在客户端通过 JavaScript 引用表单数据
- 只有设置了 name 属性的表单元素才能在提交表单时传递它们的值,因为服务端获取表单提交的数据是通过表单元素的 name 属性的值而得到的,没有 name 属性就无法得到表单元素提交给服务端的值。
5.配置tomcat并启动
1.3 MVC框架完成的事
- 将url映射到java类或Java类的方法
- 封装用户提交的数据
- 处理请求-调用业务处理-封装响应数据
- 将响应的数据进行渲染 .jsp/html等表示层数据
2、为什么要学习MVC
Spring MVC的特点:
1.轻量级 简单易学
2.高效,基于请求响应的MVC框架
3.与Spring兼容性好
4.约定大于配置
5.功能强大:RESTful,数据验证、格式化、本地化、主题
6.简洁灵活
Spring的web框架围绕DispatcherServlet【请求分发到不同的处理请的作用】设计
3、HelloSpringMVC
配置:
- 新建一个module,添加web支持
- 确定导入了springMVC的依赖
- 配置web.xml,注册DispatcherServlet
不用在web.xml里配置了!!
在web.xml里注册DispatcherServlet
<!--注册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-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
注意点:
*/和/的区别:
- /:只匹配所有的请求,不会去匹配jsp页面
- /*:匹配所有的请求包括jsp页面
在resource目录下编写springMVC的配置文件:名称: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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
添加处理映射器
这个beanName处理器需要根据bean的id查找,需要有bean,以后不用这个处理器!
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
添加处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
添加视图解析器
<!--视图解析器
1.获取了ModelAndView的数据
2.解析ModelAndView的视图和名字
3.拼接视图名字
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
写一个控制层的类
package com.liu.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//modelAndView 模型和视图
ModelAndView mv = new ModelAndView();
//封装对象,放在ModelAndView中
mv.addObject("msg","HelloSpringMVC!");
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("hello");//:/WEB-INF/jsp/hello.jsp
return mv;
}
}
将自己的类交给spring容器,注册bean
<!--Handler-->
<bean id="/hello" class="com.liu.controller.HelloController"/>
写要跳转的页面,显示ModelAndView存放的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
配置tomcat启动测试
可能遇到的问题404:
1.查看控制台输出,看一下是不是缺少jar包
2.如果jar包存在显示无法输出,就在IDEA的项目发布中添加lib依赖
3.重启tomcat
4、springMVC的执行原理
实线都是spring做了,我们只用做虚线部分!
分析执行流程:
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调用,主要作用是根据url查找Handler
3.HandlerExecution表示具体的Handler,主要作用是根据url查找控制器,如上url被查找控制器为hello
4.HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
5.HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
6.Handler让具体的Controller执行
7.Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView
8.HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
9.DispatcherServlet调用视图解析器(ViewResolver)来解析HanderAdapter传递的逻辑视图名
10.视图解析器将解析的逻辑视图名传递给DispatcherServlet
11.DispatcherServlet根据视图解析器的视图结果调用具体的视图
12.视图呈现给用户
5、注解版
5.1、解决资源过滤问题
在pom.xml文件中配置:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
在普通项目里创建maven项目,右键add框架变成maven项目,变成4.0版本的
在工程里面导入jar包
5.2 注册DispatcherServlet
<!--注册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-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
5.3、在resource目录下配置spirngmvc-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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="com.liu.controller"/>
<!--让springMVC不处理静态资源 jsp mp3 mp4-->
<mvc:default-servlet-handler/>
<!--支持mvc注解驱动
在spring中一般采用@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>
在视图解析器下把所有的视图放在/WEB-INF/目录下可以保证视图安全,因为这个目录下的文件,客户端不能直接访问
5.4 创建Controller
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/hello") //真实访问地址:项目名/HelloController/hello
public String hello(Model model){
//封装数据,向模型中添加属性msg和值,可以在jsp中取出并渲染
model.addAttribute("msg","Hello,Controller!");
return "hello";//返回的字符串就是视图的名字,会被视图解析器处理
}
@RequestMapping("/hello")
public String hello2(Model model){
//封装数据
model.addAttribute("msg","Hello,Controller!");
return "hello";//返回的字符串就是视图的名字,会被视图解析器处理
}
}
@RequestMapping如果作用在类上,要先经过类的路径,再通过方法上的路径
@Controller是为了让Spring IOC容器初始化时自动扫描到
@RestController不会被视图解析器解析,返回的就是字符串,json形式
@RequestMapping是为了映射请求路径
方法中声明Model类型的参数是为了把Action中的数据带到视图层
方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。
5.5 创建视图层
在WEB-INF/jsp目录中创建hello.jsp,视图可以直接取出并展示从Controller带回的信息
可以通过EL表示取出Model中存放的值或者对象;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
5.6 配置tomcat运行
6、Controller接口
控制器Controller
- 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解两种方式实现
- 控制器负责解析用户的请求并将其转换为一个模型
- 在Spring MVC中一个控制器类可以包含多个方法,对Controller的配置方式有很多种
实现Controller接口
在org.springframework.web.servlet.mvc包下,接口只有一个方法
1.编写一个实现Controller接口的类
package com.liu.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 实现了Controller接口的类说明这是一个控制器了
public class ControllerDemo1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerHello!");
mv.setViewName("hello");
return mv;
}
}
2.编写完后去spring配置文件中注册请求的bean;name对应请求路径,class对应处理请求的类
<bean name="/hello" class="com.liu.controller.ControllerDemo1"/>
这种配置方式缺点:在实现了Controller接口的类里只能写一个方法
第二中方式:注解(推荐)
@Controller注解类型用于声明Spring类的实例是一个控制器
Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描。
<!-- 自动扫描包,所有注解类交给IOC容器管理-->
<context:component-scan base-package="com.liu.controller"/>
@Component 组件
@Repository dao层
@Service service层
@Controller controller层 代表这个类会被spring接管
增加一个ControllerDemo2类,并使用注解实现:
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerDemo2 {
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","ControllerTest!");
return "hello";//视图解析器的名字 也就是jsp的名字
}
}
RequestMapping注解
映射路径注解;
- @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中所有响应请求的方法都是以该地址作为父路径。
- 只用在方法上更为精确。
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/c1")
public class ControllerDemo2 {
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","ControllerTest!");
return "hello";//视图解析器的名字 也就是jsp的名字
}
//url路径:WEB-INF/jsp/项目名/c1/hello
}
7、RestFul风格
url全部都是以/分割!
- 就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格,基于这个风格设计的软件可以更为简洁,更有层次,更易于实现缓存等机制。
作用:安全,简洁,高效
功能:
- 资源
- 资源操作:使用POST,GET,PUT,DELETE,使用不同方法对资源进行不同的操作
- 分别对应 添加、查询、修改、删除
使用restful风格操作资源:可以通过不同的请求方式来实现不同的效果:请求地址一样,但功能不同
- http://127.0.0.1/item/1 查询GET
- http://127.0.0.1/item 新增POST
- http://127.0.0.1/item 更新PUT
- http://127.0.0.1/item/1 删除 DELETE
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class RestController {
//原始方式:
//http://localhost:8080/springmvc_04_controller_war_exploded/add?a=1&b=2
//RestFul风格:http://localhost:8080/springmvc_04_controller_war_exploded/add/a/b
// @RequestMapping("/add/{a}/{b}")
@GetMapping("/add/{a}/{b}")
@PostMapping()
public String test(@PathVariable int a, @PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg","结果为:"+res);
return "hello";
}
}
-
在SpringMVC中可以使用@PathVariable注解,让方法参数的值对应绑定到一个URL模板变量上
-
可以用衍生的简化注解方式特定选择不同方式提交(推荐)
-
@GetMapping @PostMapping @DeleteMapping
-
可以选择自定义不同的方法来提交(不推荐)
-
@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
8、springMVC实现重定向和转发
- 无需视图解析器!
转发:
@Controller
public class ModelTest {
//转发
@RequestMapping("/m1/t1")
public String test1(Model model){
model.addAttribute("msg","ModelTest1");
return "forward:/WEB-INF/jsp/hello.jsp";
}
}
重定向:
@Controller
public class ModelTest {
//重定向
@RequestMapping("/m1/t1")
public String test1(Model model){
model.addAttribute("msg","ModelTest1");
return "redirect:/index.jsp";
}
}
- 有视图解析器的情况,直接返回即可!
9、数据处理
1.
提交数据:http://localhost:8080/springmvc_04_controller_war_exploded/user/t1?username=liuxiang
@Controller
@RequestMapping("/user")
public class UserController {
//localhost:8080/user/t1?name=xxx;
@RequestMapping("/t1")
public String test1(@RequestParam("username") String name, Model model){
//1.接收前端参数
System.out.println("将接收到前端的参数为:"+name);
//2.将返回的结果传递给前端
model.addAttribute("msg",name);
//3.视图跳转
return "hello";
}
}
后台输出:liuxiang
@RequestParam:代表前端要接收的数据
2.前端接收的是对象
提交数据:http://localhost:8080/springmvc_04_controller_war_exploded/user/t2?id=1&name=liuxiang&age=10
//前端接收的是一个对象
@GetMapping("/t2")
public String test2(User user){
System.out.println(user);
return "hello";
}
1.接收前端用户传递的参数,判断参数的名字,假设名字在方法上则直接使用
2.假设传递的是一个对象User,匹配User对象中的字段名,如果和实例类中的字段名一样则OK,如果不一致则会返回null值
LinkedHashMap
ModelMap 继承了LinkedHashMap,拥有全部功能
Model 大部分情况下用这个精简版的
10、乱码问题
10.1 自定义过滤器
package com.liu.filiter;
import javax.servlet.*;
import java.io.IOException;
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.liu.filiter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
10.2 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>
11、JSON
- JSON是一种轻量级的数据交换格式,目前使用最为广泛
- 采用完全独立于编程语言的文本格式来存储和表示数据
- 简洁和清晰的层次结构使得JSON成为理想的数据交换语言
在JavaScript语言中一切的都是对象,包括字符串、数字、对象等都可以通过JSON来表示
- 对象表示为键值对,数据由逗号隔开
- 花括号保存对象
- 方括号保存数组
JSON和JavaScript对象互转
JSON转JavaScript对象,使用JSON.prase()方法
var obj = JSON.prase('{"a";"Hello","b"}')
//结果:{a;'Hello';b}
JavaScript转JSON字符串,使用JSON.stringify()方法
var json = JSON.stringify({a;'Hello';b});
//结果:'{"a";"Hello","b"}'
代码测试:
<script type="text/javascript">
//编写一个JavaScript对象 ES6
var user = {
name:"刘想",
age:3,
sex:"男"
}
//将JavaScript对象转换为json对象
var json = JSON.stringify(user);
//将json转换为JavaScript对象
var obj = JSON.parse(json);
console.log(obj);
console.log(json);
console.log(user);
</script>
11.1、Controller返回JSON数据
- Jackson解析工具
- fastjson解析工具
- 使用jackson,需要导入相关jar包:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
- 配置springMVC需要的配置
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">
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<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>
<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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.liu.controller"/>
<mvc:default-servlet-handler/>
<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>
测试
package com.liu.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liu.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RestController //下面所有的方法只会返回json字符串,不走视图解析器
public class UserController {
@RequestMapping("/j1")
@ResponseBody //不会走视图解析器,会直接返回一个字符串
public String json1() throws JsonProcessingException {
//jackson,ObjectMapper
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
User user = new User("刘想",3,"男");
String str = mapper.writeValueAsString(user);
return str; //{"name":"??","age":3,"sex":"?"} json格式
}
}
11.2 解决乱码问题
1.通过@RequestMapping的produces属性来实现
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
//结果:{"name":"刘想","age":3,"sex":"男"}
这种方法比较麻烦,需要在不同请求中都要配置,通过spring配置统一管理
2.在springmvc的配置文件中添加一段消息StringHttpMessageConverter转换配置
<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>
11.3 时间格式化
1.老方法
@RequestMapping("/j2")
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sdf.format(date);
String str = mapper.writeValueAsString(format);
return str;
}
2.使用ObjectMapper来格式化输出
@RequestMapping("/j2")
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//使用ObjectMapper来格式化输出
//关闭时间戳的方式
mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mapper.setDateFormat(sdf);
Date date = new Date();
String str = mapper.writeValueAsString(date);
return str;
}
11.4 JSON工具类
package com.liu.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.text.SimpleDateFormat;
public class JsonUtils {
//传一个参数
public static String getJson(Object object){
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}
//传两个参数
public static String getJson(Object object,String dateFormat){
ObjectMapper mapper = new ObjectMapper();
//关闭时间戳的方式
mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false);
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
mapper.setDateFormat(sdf);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
fastjson工具:
1.导jar包
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
2.配置web.xml
3.配置springmvc-servlet.xml
4.测试
fastjson主要有三个类:
- JSONObject代表json对象
- 实现了Map接口,底层由Map实现
- 通过各种形式的get()方法可以获取json对象中的数据,如size(),isEmpty()等方法获取键值对的个数
- JSONArray代表json对象数组
- 内部由List接口中的方法来完成
- JSON代表JSONObject和JSONArray的转化
- JSON类源码分析和使用
@RequestMapping("/j3")
public String json3(){
ArrayList<User> list = new ArrayList<>();
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.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
return JSON.toJSONString(list);
}
12、ssm项目整合
1.创建数据库
CREATE DATABASE ssmbuild;
USE ssmbuild;
CREATE TABLE `books`(
`bookID` INT NOT NULL AUTO_INCREMENT COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名',
`bookCounts` INT 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,'从进门到进牢');
2.搭建环境,创建新项目
2.1 依赖jar包
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.liu</groupId>
<artifactId>ssmbuild</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
</dependencies>
<!--静态资源导出问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
2.2 mybatis核心配置
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>
<!--配置数据源,交给spring做-->
<typeAliases>
<package name="com.liu.pojo"/>
</typeAliases>
</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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<import resource="spring-dao.xml"/>
<import resource="spring-service.xml"/>
<import resource="springmvc-servlet.xml"/>
</beans>
2.3 mtbatis层编写
专注数据和业务!(dao和service层)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456789
- 如果使用的是mybatis8.0+版本,需要设置时区的配置;&serverTimezone=Asia/Shanghai
2.3.1 实体类编写
- 要与数据库字段一一对应
package com.liu.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Books {
private int bookID;
private String bookName;
private int bookCounts;
private String detail;
}
2.3.2 接口和实现类
- 需求
package com.liu.dao;
import com.liu.pojo.Books;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BookMapper {
//增加一本书
int addBook(Books books);
//删除一本书
int deleteBookById(@Param("bookId") int id);
//更新一本书
int updateBook(Books books);
//查询一本书
Books queryBookById(@Param("bookId")int id);
//查询全部的书
List<Books> queryAllBook();
}
- BookMapper.xml
<?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.liu.dao.BookMapper">
<insert id="addBook" parameterType="Books">
insert into ssmbuild.books (bookName, bookCounts, detail)
values (#{bookName},#{bookCounts},#{detail});
</insert>
<delete id="deleteBookById" parameterType="int">
delete from ssmbuild.books where bookID = #{bookId};
</delete>
<update id="updateBook" parameterType="Books">
update ssmbuild.books
set bookName = #{bookName},bookCounts=#{bookCounts},detail=#{detail}
where bookID=#{bookID};
</update>
<select id="queryBookById" resultType="Books">
select * from ssmbuild.books where bookID=#{bookId};
</select>
<select id="queryAllBook" resultType="Books">
select *
from ssmbuild.books;
</select>
</mapper>
- 在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.liu.pojo"/>
</typeAliases>
<mappers>
<mapper class="com.liu.dao.BookMapper"/>
</mappers>
</configuration>
2.3.3 service层接口和实现类
package com.liu.service;
import com.liu.pojo.Books;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface BookService {
//增加一本书
int addBook(Books books);
//删除一本书
int deleteBookById(int id);
//更新一本书
int updateBook(Books books);
//查询一本书
Books queryBookById(int id);
//查询全部的书
List<Books> queryAllBook();
}
- 实现类
package com.liu.service;
import com.liu.dao.BookMapper;
import com.liu.pojo.Books;
import java.util.List;
public class BookServiceImpl implements BookService{
//service调dao层 组合dao层
private BookMapper bookMapper;
//set注入
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
public int addBook(Books books) {
return bookMapper.addBook(books);
}
public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}
public int updateBook(Books books) {
return bookMapper.updateBook(books);
}
public Books queryBookById(int id) {
return bookMapper.queryBookById(id);
}
public List<Books> queryAllBook() {
return bookMapper.queryAllBook();
}
}
2.4 spring层的编写
2.4.1 编写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"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--关联数据库配置文件-->
<context:property-placeholder location="classpath:database.properties"/>
<!--连接池
dbcp:半自动化操作,不能自动来连接
c3p0:自动化操作(自动加载配置文件,并且可以自动设置到对象中)
druid:hikari
-->
<bean id="dataSource" 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"/>
<!--关闭连接后不自动提交-->
<property name="autoCommitOnClose" value="false"/>
<!--获取连接超时时间-->
<property name="checkoutTimeout" value="10000"/>
<!--当连接获取失败重试次数-->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--绑定mybatis的配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--配置dao接口扫描包,动态的实现dao接口可以注入到spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--要扫描的dao包-->
<property name="basePackage" value="com.liu.dao"/>
</bean>
</beans>
- 老方法实现dao接口注入到spring中:
package com.liu.dao;
import com.liu.pojo.Books;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class BookMapperImpl extends SqlSessionDaoSupport implements BookMapper{
public int addBook(Books books) {
return 0;
}
public int deleteBookById(int id) {
return 0;
}
public int updateBook(Books books) {
return 0;
}
public Books queryBookById(int id) {
return null;
}
public List<Books> queryAllBook() {
return null;
}
}
- 动态实现注入(在spring-dao.xml文件中)
<!--配置dao接口扫描包,动态的实现dao接口可以注入到spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--要扫描的dao包-->
<property name="basePackage" value="com.liu.dao"/>
</bean>
2.4.2 service层(spring-service.xml)
注入方式1:配置
<?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:aop="http://www.springframework.org/schema/aop"
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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描service下的包-->
<context:component-scan base-package="com.liu.service"/>
<!--将所有的业务类注入到spring中,通过配置或注解-->
<bean id="BookServiceImpl" class="com.liu.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>
<!--声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
注入方式2:注解自动注入
package com.liu.service;
import com.liu.dao.BookMapper;
import com.liu.pojo.Books;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookServiceImpl implements BookService{
//service调dao层 组合dao层
private BookMapper bookMapper;
//set注入
@Autowired
public void setBookMapper(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
public int addBook(Books books) {
return bookMapper.addBook(books);
}
public int deleteBookById(int id) {
return bookMapper.deleteBookById(id);
}
public int updateBook(Books books) {
return bookMapper.updateBook(books);
}
public Books queryBookById(int id) {
return bookMapper.queryBookById(id);
}
public List<Books> queryAllBook() {
return bookMapper.queryAllBook();
}
}
2.5 springMVC层(springmvc-servlet.xml)
2.5.1 变成web项目
2.5.2 在web.xml里注册DispatchServlet和乱码过滤
<?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">
<servlet>
<servlet-name>springmvc</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>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>
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
2.5.3 配置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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--注解驱动-->
<mvc:annotation-driven/>
<context:component-scan base-package="com.liu.controller"/>
<!--静态资源过滤-->
<mvc:default-servlet-handler/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
2.6 controller层
package com.liu.controller;
import com.liu.pojo.Books;
import com.liu.service.BookService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping("/book")
public class BookController {
//controller调service层
@Autowired
@Qualifier("BookServiceImpl")
private BookService bookService;
//查询全部的书籍,并返回一个书籍展示页面
@RequestMapping("/allBook")
public String list(Model model){
List<Books> list = bookService.queryAllBook();
model.addAttribute("list",list);
return "allBook";
}
//跳转到增加书籍页面
@RequestMapping("/addBook")
public String toAddPaper(){
return "addBook";
}
//添加书籍的请求
@RequestMapping("/AddBooks")
public String addBook(Books books){
System.out.println("addBook=>"+books);
bookService.addBook(books);
return "redirect:/book/allBook";//重定向
}
//跳转到修改页面
@RequestMapping("/updateBook")
public String toUpdatePaper(int id,Model model){
Books books = bookService.queryBookById(id);
model.addAttribute("QBook",books);
return "updateBook";
}
//修改书籍
@RequestMapping("/UpdateBooks")
public String updateBook(Books books){
System.out.println("updateBook=>"+books);
int i = bookService.updateBook(books);
if (i>0){
System.out.println("修改成功!");
}
return "redirect:/book/allBook";
}
//跳转到删除书籍页面
@RequestMapping("/deleteBook/{bookId}")
public String deleteBook(@PathVariable("bookId") int id){
bookService.deleteBookById(id);
return "redirect:/book/allBook";
}
//查询书籍
@RequestMapping("/queryBook")
public String queryBook(String queryBookName,Model model){
Books books = bookService.queryBookName(queryBookName);
List<Books> list = new ArrayList<Books>();
list.add(books);
if (books==null){
list = bookService.queryAllBook();
model.addAttribute("error","未查到");
}
model.addAttribute("list",list);
return "allBook";
}
}
2.6.1 要跳转的jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示页面</title>
</head>
<body>
<h1>书籍展示</h1>
${list}
</body>
</html>
2.6.2 问题:bean不存在
步骤:
- 查看这个bean注入是否成功
- junit单元词测试,看代码能否查询出结果。
- 如果报错如这种错误:
the server time zone value ‘�й���ʱ��’ is unrecognized or represents more than one time zone. You mus
-
需要在url要操作的库后面加上:?serverTimezone=UTC
-
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8
- 如果均没有问题,问题不在底层,问题在spring
- springMVC整合的时候没有调用到service层的bean
- applicationContext.xml没有注入bean
- 在web.xml配置dispatcherServlet时候关联的是springmvc-servlet.xml文件
- 将applicationContext.xml替换springmvc-servlet.xml即可
- 如果运行tomcat报:由于之前的错误,context运行失败
- 解决:添加lib目录,加入所有依赖jar包
2.7 美化界面
bootstrap在线引用:
Bootstrap 3.3.0 js 文件
<script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
Bootstrap 3.3.0 css 文件
<link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">
Bootstrap 3.0.3 js 文件
<script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
Bootstrap 3.0.3 css 文件
<link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet" />
- 报错:/WEB-INF/jsp/allBook.jsp (行.: [52], 列: [97]) #{…} 不允许出现在模板文本中
- 解决:前端页面取值将$符号写成了#
2.7.1 首页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
<style>
a{
text-decoration: none;
color: black;
font-size: 18px;
}
h3{
width: 180px;
height: 38px;
margin: 100px auto;
text-align: center;
line-height: 38px;
background: deepskyblue;
border-radius: 5px; /*圆角边框*/
}
</style>
</head>
<body>
<h3>
<a href="${pageContext.request.contextPath}/book/allBook">跳转到书籍展示页面</a>
</h3>
</body>
</html>
2.7.2 所有书籍
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>书籍展示页面</title>
<%--BootStrap 美化页面--%>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>书籍列表 —————— 显示所有书籍</small>
</h1>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/addBook">新增书籍</a>
<a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">显示全部书籍</a>
</div>
<div class="col-md-4 column"></div>
<div class="col-md-4 column">
<%--查询书籍--%>
<form class="form-inline" action="${pageContext.request.contextPath}/book/queryBook" method="post" style="float: right">
<span style="color: red;font-weight: bolder">${error}</span>
<input type="text" name="queryBookName" class="form-control" placeholder="请输入要查询的书籍名称">
<input type="submit" value="查询" class="btn btn-primary">
</form>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>书籍编号</th>
<th>书籍名称</th>
<th>书籍数量</th>
<th>书籍详情</th>
<th>操作</th>
</tr>
</thead>
<%--书籍从数据库查询,从list集合中遍历--%>
<tbody>
<c:forEach var="book" items="${list}">
<tr>
<td>${book.bookID}</td>
<td>${book.bookName}</td>
<td>${book.bookCounts}</td>
<td>${book.detail}</td>
<td>
<a href="${pageContext.request.contextPath}/book/updateBook?id=${book.bookID}">修改</a>
|
<a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
2.7.3 增加书籍页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%--BootStrap 美化页面--%>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>新增书籍</small>
</h1>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/book/AddBooks" method="post">
<div class="form-group">
<label>书籍名称:</label>
<input type="text" name="bookName" class="form-control" required> <%--name属性必须与数据库字段一样 加required是所有添加完才提交--%>
</div>
<div class="form-group">
<label>书籍数量:</label>
<input type="text" name="bookCounts" class="form-control" required>
</div>
<div class="form-group">
<label>书籍内容:</label>
<input type="text" name="detail" class="form-control" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="添加">
</div>
</form>
</div>
</body>
</html>
2.7.4 修改书籍页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改数据</title>
<%--BootStrap 美化页面--%>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>修改书籍</small>
</h1>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/book/UpdateBooks" method="post">
<%--出现的问题提交了修改的sql请求,修改失败,首先考虑事务问题,配置完事务还是失败--%>
<%--看sql语句,sql执行失败--%>
<%--前端传递隐藏域传递id--%>
<input type="hidden" name="bookID" value="${QBook.bookID}">
<div class="form-group">
<label>书籍名称:</label>
<input type="text" name="bookName" class="form-control" value="${QBook.bookName}" required> <%--name属性必须与数据库字段一样 加required是所有添加完才提交--%>
</div>
<div class="form-group">
<label>书籍数量:</label>
<input type="text" name="bookCounts" class="form-control" value="${QBook.bookCounts}" required>
</div>
<div class="form-group">
<label>书籍内容:</label>
<input type="text" name="detail" class="form-control" value="${QBook.detail}" required>
</div>
<div class="form-group">
<input type="submit" class="form-control" value="修改">
</div>
</form>
</div>
</body>
</html>
2.8 修改删除操作需要事务支持(用aop横切)
1.导入织入包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
<scope>runtime</scope>
</dependency>
- 在spring-service.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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.liu.service"/>
<bean id="BookServiceImpl" class="com.liu.service.BookServiceImpl">
<property name="bookMapper" ref="bookMapper"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给方法配置事务-->
<!--配置事务的传播特性:new propagation-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.liu.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
2.9 界面展示
推荐一个bootstrap可视化布局,通过下载就可以得到想要的源码
Bootstrap可视化布局系统 (bootcss.com)
13、AJAX
- ajax:异步的JavaScript和XML
- 是一种无需重新加载整个网页的情况下,能够更新部分网页的技术
- 是一种用于创建更好更快以及交互性更强的web应用程序的技术,不是一种新的编程语言
在Download jQuery | jQuery下载jquery.js文件。
ajax部分参数:
- url:请求地址
- type:请求方式(get,post(1.9.0后用method)
- status:状态码(404,500,200,300)
- headers:请求头
- data:要发送的数据
- contentType:即将发送信息至服务器的内容编码类型(默认:“application/x-www-form-urlencoding”)
- async:是否异步
- timeout:设置请求超时时间
- beforeSend:发送请求前执行的函数
- complete:完成之后执行的回调函数
- success:成功之后执行的回调函数
- accepts:通过请求头发送给服务器告诉服务器当前客户端接收的数据类型
- error:失败后执行的绘图奥
- dataType:将服务器端返回的数据转换为指定类型
- “xml”:将服务器端返回的内容转换为xml格式
- “text”:转换为普通格式
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
<script>
function a() {
$.post({
url:"${pageContext.request.contextPath}/a1",
data:{"name":$("#username").val()},
success:function (data) {
alert(data);
},
error: function () {
alert("请求出错");
}
})
}
</script>
</head>
<body>
<%--失去焦点的时候发起一个请求(携带信息)到后台--%>
用户名: <input type="text" id="username" οnblur="a()">
</body>
</html>
后端发起请求:
@RestController
public class AjaxController {
@RequestMapping("/a1")
public void a1(String name, HttpServletResponse response) throws IOException {
System.out.println("a1:param=>"+name);
if ("liuxiang".equals(name)){
response.getWriter().print("true");
}else {
response.getWriter().print("false");
}
}
}
前后端分离:
13.1、ajax异步加载数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
<script>
$(function (){
$("#btn").click(function (){
/*
$.post(url,param[可以省略],success)
*/
$.post("${pageContext.request.contextPath}/a2",function (data){
// console.log(data);
var html="";
for (let i = 0; i < data.length; i++) {
html+="<tr>/" +
"<td>" + data[i].name + "</td>" +
"<td>" + data[i].age + "</td>" +
"<td>" + data[i].sex + "</td>" +
"<tr>/"
}
$("#content").html(html);
})
})
});
</script>
</head>
<body>
<%--前端--%>
<input type="button" value="加载数据" id="btn">
<table>
<tr>
<td>姓名:</td>
<td>年龄:</td>
<td>性别:</td>
</tr>
<tbody id="content">
<%--数据,后台获取,异步获取--%>
</tbody>
</table>
</body>
</html>
后端:
@RequestMapping("/a2")
public List<User> a2(){
ArrayList<User> userList = new ArrayList<>();
//添加数据
userList.add(new User(1,"刘想","男"));
userList.add(new User(2,"刘想1","男"));
userList.add(new User(3,"刘想2","男"));
//
return userList;
}
13.2、ajax异步验证登录
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
<script>
function a1(){
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{"name":$("#name").val()},
success:function (data) {
// console.log(data);
if (data.toString()=='ok'){
$("#userInfo").css("color","green");
}
$("#userInfo").html(data);
}
})
}
function a2() {
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{"password":$("#password").val()},
success:function (data) {
// console.log(data);
if (data.toString()=='ok'){
$("#passwordInfo").css("color","green");
}
$("#passwordInfo").html(data);
}
})
}
</script>
</head>
<body>
<p>
用户名:<input type="text" id="name" οnblur="a1()">
<span id="userInfo"></span>
</p>
<p>
密码:<input type="text" id="password" οnblur="a2()">
<span id="passwordInfo"></span>
</p>
</body>
</html>
后端:
@RequestMapping("/a3")
public String a3(String name,String password){
String msg= "";
if (name!=null){
if ("admin".equals(name)){
msg = "ok";
}else {
msg = "用户名有误";
}
}
if (password!=null){
if ("123456".equals(password)){
msg = "ok";
}else {
msg = "密码有误!";
}
}
return msg;
}
14、拦截器
拦截器和过滤器的区别:拦截器是AOP思想的具体应用
过滤器:
- servlet规范中的一部分,任何javaweb工程都可以使用
- 在url-pattern中配置了/*后,可以对所有要访问的资源进行拦截
拦截器(自带资源过滤):
- 拦截器是springMVC框架自己的,只有使用 了springMVC框架的工程才能使用
- 拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会被拦截的
14.1 自定义拦截器
实现HandlerInterceptor接口
1.新建一个module,添加web支持
2.配置web.xml和springmvc-servlet.xml文件
3.编写一个拦截器
package com.liu.config;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
//return true;执行下一个拦截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("==========处理前============");
return true;
}
//拦截日志
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("=========处理后=================");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("===========清理=============");
}
}
拦截器在springmvc下配置:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.liu.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
第二个拦截器:登录页面的拦截
第一次没有session在登录页面不拦截,在登陆后注销session后进行拦截
package com.liu.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
//放行,判断什么情况下登录
//登录页面放行
if (request.getRequestURI().contains("goLogin")){
return true;
}
//在提交时候登录
if (request.getRequestURI().contains("login")){
return true;
}
//有session情况
if (session.getAttribute("userLoginInfo")!=null){
return true;
}
//判断什么情况下没有登录
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<bean class="com.liu.config.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
14.2 控制层
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/user")
public class LoginController {
@RequestMapping("/goLogin")
public String login(){
return "login";
}
@RequestMapping("/login")
public String login(HttpSession session, String username, String password, Model model){
//把用户的信息存在session中
session.setAttribute("userLoginInfo",username);
model.addAttribute("username",username);
return "main";
}
@RequestMapping("/goOut")
public String goOut(HttpSession session, String username, String password, Model model){
session.removeAttribute("userLoginInfo");
return "main";
}
@RequestMapping("/main")
public String main(){
return "main";
}
}
14.3 首页、登录页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1> <a href="${pageContext.request.contextPath}/user/goLogin">登录页面</a></h1>
<h1> <a href="${pageContext.request.contextPath}/user/main">首页</a></h1>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>首页</h1>
<span>${username}</span>
<p>
<a href="${pageContext.request.contextPath}/user/goOut">注销</a>
</p>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--在web-inf下的所有页面只能通过controller或者servlet访问--%>
<h1>登录页面</h1>
<form action="${pageContext.request.contextPath}/user/login" method="post">
用户名:<input type="text" name="username">
密码:<input type="text" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
15、文件上传和下载
15.1 准备工作
springMVC中没有装配MultipartResolver,所以默认情况下不能处理文件上传工作,如果想要使用文件上传功能,需要在上下文中配置MultipartResolver。
前端表单要求:必须将表单的method设置为POST,并将enctype设置为multipart/form-data,只有在这种情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。
- application/x-www=form-urlencoded:默认方式,只处理表单域中的value属性值,采用这种编码方式的表单会将表单域中的值处理成URL编码方式。
- multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码丰富会把文件域指定文件的内容也封装到请求参数中,不会对字符编码
- text/plain:除了把空格转换为"+"号外,其他字符不作编码处理,适用 直接通过表单发送右键
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file">
<input type="submit">
</form>
后端导入文件上传的jar包:commons-fileupload
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
在springmvc-servlet.xml配置:
<!--文件上传配置-->
<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>
15.2 controller层
package com.liu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@RestController
public class FileController {
//@RequestMapping("file") 将name=file控件得到的文件封装成CommonsMultipartFile对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String fileUpLoad(@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);
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream();//文件输入流
FileOutputStream 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.TransferTo来保存上传的文件
@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";
}
15.3 文件下载
- 设置response响应头
- 读取文件InputStream
- 写出文件OutputStream
- 执行操作
- 关闭流
//下载图片方法
@RequestMapping("/downLoad")
public String downLoads(HttpServletResponse response,HttpServletRequest request) throws IOException {
//要下载的图片
String path = request.getServletContext().getRealPath("/upload");
String fileName = "基础语法.jpg";
//1.设置response响应头
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 is = new FileInputStream(file);
//3.写出文件-输出流
OutputStream fos = response.getOutputStream();
byte[] buffer = new byte[1024];
int index = 0;
while ((index = is.read(buffer))!=-1){
fos.write(buffer,0,index);
fos.flush();
}
fos.close();
is.close();
return null;
}
<a href="${pageContext.request.contextPath}/downLoad">下载图片</a>
leName = file.getOriginalFilename();
//如果文件名为空,直接回到首页
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名:"+uploadFileName);
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream();//文件输入流
FileOutputStream 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";
}
}
方法二:
```java
//采用file.TransferTo来保存上传的文件
@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";
}
15.3 文件下载
- 设置response响应头
- 读取文件InputStream
- 写出文件OutputStream
- 执行操作
- 关闭流
//下载图片方法
@RequestMapping("/downLoad")
public String downLoads(HttpServletResponse response,HttpServletRequest request) throws IOException {
//要下载的图片
String path = request.getServletContext().getRealPath("/upload");
String fileName = "基础语法.jpg";
//1.设置response响应头
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 is = new FileInputStream(file);
//3.写出文件-输出流
OutputStream fos = response.getOutputStream();
byte[] buffer = new byte[1024];
int index = 0;
while ((index = is.read(buffer))!=-1){
fos.write(buffer,0,index);
fos.flush();
}
fos.close();
is.close();
return null;
}
<a href="${pageContext.request.contextPath}/downLoad">下载图片</a>