- SpringMVC
- 1、简述
- 1.1 什么是 SpringMVC
- 1.2 为什么学习 SpringMVC
- 1.3 SpringMVC 的特点
- 2、中心控制器
- 3、SpringMVC 原理
- 4、HelloSpringMVC
- 4.1 配置版
- 4.2 注解版(*)
- 4.3 结论
- 5、注解
- 5.1 Controller
- 5.1.1 实现 Controller 接口
- 5.1.2 注解 @Controller
- 5.2 RequestMapping
- 6、RestFul 风格
- 6.1 什么是 RestFul
- 6.2 RestFul 功能
- 6.3 测试 RestFul 风格
- 6.3.1 使用 @RequestMapping
- 6.3.2 使用注解变体
- 6.4 小结
- 7、转发与重定向
- 7.1 ModelAndView
- 7.2 ServletAPI
- 7.3 SpringMVC
- 7.3.1 无视图解析器
- 7.3.2 有视图解析器
- 8、数据处理
- 8.1 处理提交数据
- 8.2 数据显示到前端
- 9、中文乱码问题
- 10、Json
- 10.1 JSON 与 Javascript
- 10.2 Controller 返回 JSON 数据
- 10.3 Controller 返回 JSON 数据代码优化
- 10.3.1 将乱码问题统一解决
- 10.3.2 统一解决返回为 json 字符串问题
- 10.4 测试集合的输出
- 10.5 测试时间对象输出
- 10.6 将重复代码抽取为工具类
- 10.7 FastJson
- 11、Ajax
- 11.1 什么是 Ajax
- 11.2 Ajax 原理
- 11.3 伪造 Ajax
- 11.4 jQuery 操作 ajax
- 11.5 原始的 HttpServletResponse 实现
- 11.6 SpringMVC 实现异步加载数据
- 11.7 注册提示效果
- 12、拦截器
- 12.1 什么是拦截器
- 12.2 自定义拦截器
- 12.3 验证用户是否登录(认证用户)
- 13、文件上传和下载
- 13.1 准备测试
- 13.2 文件上传
- 13.3 文件下载
SSM:MyBatis + Spring + SpringMVC
Spring:IOC(控制反转)、AOP(面向切面编程)
SpringMVC:SpringMVC 的执行流程
SpringMVC:SSM 框架整合
1、简述 1.1 什么是 SpringMVCSpring MVC 是 Spring framework 的一部分,是基于 Java 实现 MVC 的轻量级 Web 框架
1.2 为什么学习 SpringMVC因为 SpringMVC “简单好学”,便捷,能与 Spring 无缝集成(SpringIOC、AOP),使用约定大于配置,能够进行简单的 junit 测试,支持 Restful 风格,异常处理,本地化,国际化,数据验证,类型转换,拦截器,等等
最重要的是使用的公司多,用的人也多
1.3 SpringMVC 的特点- 简单好学
- 高效(基于请求相应的 MVC 框架)
- 与 Spring 无缝集成,兼容性好
- 约定大于配置
- 功能强大(Restful、数据验证、格式化、本地化、类型转换、等等)
- 简洁灵活
-
Spring 的 web 框架围绕 DispatcherServlet 设计。DispatcherServlet 的作用是将请求分发到不同的处理器。从 Spring 2.5 开始,使用 Java 5 或者以上版本的用户可以采用基于注解的 controller 声明方式。
-
Spring MVC 框架像许多其他 MVC 框架一样, 以请求为驱动 , 围绕一个中心 Servlet 分派请求及提供其他功能,DispatcherServlet 是一个实际的 Servlet (它继承自 HttpServlet 基类)。
SpringMVC的原理如下图所示:
- 当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。
SpringMVC 执行原理
实线表示SpringMVC框架提供的技术,不需要开发者实现,虚线表示需要开发者实现
-
DispatcherServlet 表示前置控制器,是整个 SpringMVC 的控制中心。用户发出请求,DispatcherServlet 接收请求并拦截请求。
-
我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
-
如上 url 拆分成三部分:
- http://localhost:8080 服务器域名
- SpringMVC 部署在服务器上的 web 站点
- hello 表示控制器
-
通过分析,如上 url 表示为:请求位于服务器 localhost:8080上的Spring MVC站点的 hello 控制器。
-
-
HandlerMapping 为处理器映射。DispatcherServlet 调用 HandlerMapping,HandlerMapping 根据请求 url 查找 Handler。
-
HandlerExecution 表示具体的Handler,其主要作用是根据 url 查找控制器,如上 url 被查找控制器为:hello。
-
HandlerExecution 将解析后的信息传递给 DispatcherServlet,如解析控制器映射等。
-
HandlerAdapter 表示处理器适配器,其按照特定的规则去执行 Handler。
-
Handler 让具体的 Controller 执行。
-
Controller 将具体的执行信息返回给 HandlerAdapter,如 ModelAndView。
-
HandlerAdapter 将视图逻辑名或模型传递给 DispatcherServlet。
-
DispatcherServlet 调用视图解析器(ViewResolver)来解析 HandlerAdapter 传递的逻辑视图名。
-
视图解析器将解析的逻辑视图名传给 DispatcherServlet。
-
DispatcherServlet 根据视图解析器解析的视图结果,调用具体的视图。
-
最终视图呈现给用户。
步骤:
-
新建一个 项目,添加 web 支持
-
导入 SpringMVC 的依赖
-
创建 SpringMVC 的配置文件(springmvc-service.xml)
-
配置 web.xml,注册 DispatcherServlet
@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请求 Mapspringmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc-service.xml 1 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 parameterMap = getParameterMap(); String[] values = parameterMap.get(name); if (values == null) { return null; } return values[0]; // 取回参数的第一个值 } //取所有值 @Override public String[] getParameterValues(String name) { Map parameterMap = getParameterMap(); String[] values = parameterMap.get(name); return values; } }
以上都不行可能是你的 Tomcat 没有配置好!去修改 tomcat 配置文件 :设置编码
10、Json
- JSON(Javascript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别广泛。
- 采用完全独立于编程语言的文本格式来存储和表示数据。
- 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。(前后端分离)
- 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在 Javascript 语言中,一切都是对象。因此,任何 Javascript 支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:
- 对象表示为键值对,数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
JSON 键值对是用来保存 Javascript 对象的一种方式,和 Javascript 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值( {“键” : “值”} )
JSON 是 Javascript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
JSON 和 Javascript 对象互转:
-
要实现从JSON字符串转换为Javascript 对象,使用 JSON.parse() 方法
var obj = JSON.parse('{"a": "Hello", "b": "World"}'); -
要实现从Javascript 对象转换为JSON字符串,使用 JSON.stringify() 方法
var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'
-
Jackson 应该是目前比较好的 json 解析工具了
-
当然工具不止这一个,比如还有阿里巴巴的 fastjson 等等。
-
这里使用的是 Jackson,使用它需要导入它的 jar 包;
com.fasterxml.jackson.core jackson-databind 2.13.0 -
web.xml 配置 SpringMVC 需要的配置
- servlet 注册 SpringMVC
- filter 注册字符过滤器
SpringMVC org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc-servlet.xml 1 SpringMVC / encoding org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 encoding / -
编写 springmvc-config.xml
-
编写一个实体类 User,去测试
- 需要导入 lombok 的 jar 包
//需要导入lombok @Data @AllArgsConstructor @NoArgsConstructor public class User { private String name; private int age; private String sex; } -
编写 UserController
- @ResponseBody:将 java 对象转化为 json
- ObjectMapper:创建一个 jackson 的对象映射器,用来解析数据
@Controller public class UserController { @RequestMapping("/json1") @ResponseBody public String json1() throws JsonProcessingException { //创建一个jackson的对象映射器,用来解析数据 ObjectMapper mapper = new ObjectMapper(); //创建一个对象 User user = new User("秦疆1号", 3, "男"); //将我们的对象解析成为json格式 String str = mapper.writevalueAsString(user); //由于@ResponseBody注解,这里会将str转成json格式返回;十分方便 return str; } } -
配置 Tomcat
-
配置 Artifacts
问题:乱码问题
解决办法:通过 @RequestMaping 的 produces 属性来实现
// produces:指定响应体返回类型和编码 @RequestMapping(value = "/json1",produces = "application/json;charset=utf-8")10.3 Controller 返回 JSON 数据代码优化 10.3.1 将乱码问题统一解决
上面解决乱码的方法在项目请求多的情况下就不适用了
就可以使用 Spring 配置统一指定返回类型和编码,等等
-
在 spring-mvc 的配置文件上添加一段消息
- StringHttpMessageConverter 转换配置
如果类中有所有的方法都需要返回 json 字符串,那么所有的方法都需要标识注释 @ResponseBody,这将会特别麻烦
- 所以直接在类上使用 @RestController 来标注这个类的所有方法返回的都是 json 字符串
- 这样就不用再每个方法上写 @ResponseBody
- 前后端分离开发中,一般都会使用 @RestController ,十分便捷
在 UserController 中增加一个方法来进行测试
@RequestMapping("/json2")
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List userList = new ArrayList();
userList.add(new User("大牛逼1",18,"男"));
userList.add(new User("大牛逼2",18,"男"));
userList.add(new User("大牛逼3",18,"男"));
userList.add(new User("大牛逼4",18,"男"));
userList.add(new User("大牛逼5",18,"男"));
return mapper.writevalueAsString(userList);
}
10.5 测试时间对象输出
在 UserController 中增加一个方法来进行测试
@RequestMapping("/json3")
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Date date = new Date();
// 默认的是日期格式,但是 Jackson 默认是会把时间转成 timestamps(时间戳)形式
return mapper.writevalueAsString(date);
}
默认的是日期格式,但是 Jackson 默认是会把时间转成 timestamps(时间戳)形式:
-
取消 timestamps(时间戳)形式,自定义时间格式
@RequestMapping("/json4") public String json4() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); //不使用时间戳的方式 mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); //自定义日期格式对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //指定日期格式 mapper.setDateFormat(sdf); Date date = new Date(); return mapper.writevalueAsString(date); }
如果要经常使用的话,这样是比较麻烦的,我们可以将这些代码封装到一个工具类中
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_DATES_AS_TIMESTAMPS, false);
//自定义日期格式对象
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
//指定日期格式
mapper.setDateFormat(sdf);
try {
return mapper.writevalueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
使用工具类后的代码量
@RequestMapping("/json5")
public String json5() throws JsonProcessingException {
return JsonUtils.getJson(new Date());
}
10.7 FastJson
fastjson.jar 是阿里开发的一款专门用于 Java 开发的包,可以方便的实现多种转换,最后的实现结果都是一样的。
- 实现 json 对象与 JavaBean 对象的转换
- 实现 JavaBean 对象与 json 字符串的转换
- 实现 json 对象与 json 字符串的转换。实现 son的 转换方法很多
fastjson 的 pom 依赖:
com.alibaba fastjson 1.2.78
JSonObject 代表 json 对象
- JSonObject 实现了 Map 接口, 猜想 JSonObject 底层操作是由 Map 实现的。
- JSonObject 对应 json对 象,通过各种形式的 get() 方法可以获取 json 对象中的数据,也可利用诸如 size(),isEmpty() 等方法获取"键:值"对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。
JSonArray 代表 json 对象数组
- 内部是有 List 接口中的方法来完成操作的。
JSON 代表 JSonObject 和 JSonArray 的转化
- JSON 类源码分析与使用
- 仔细观察这些方法,主要是实现 json 对象,json 对象数组,javabean 对象,json 字符串之间的相互转化。
代码测试:
@RequestMapping("/json6")
public String json6(){
//创建一个对象
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 userList = new ArrayList();
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
System.out.println("*******Java对象 转 JSON字符串*******");
String str1 = JSON.toJSONString(userList);
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);
return JSON.toJSONString(userList);
}
11、Ajax
11.1 什么是 Ajax
- AJAX(Asynchronous Javascript And XML):异步的 Javascript 和 XML。
- AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
- Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
- 在 2005 年,Google 通过其 Google Suggest 使 AJAX 变得流行起来。Google Suggest 能够自动帮你完成搜索单词。
- Google Suggest 使用 AJAX 创造出动态性极强的 web 界面:当您在谷歌的搜索框输入关键字时,Javascript 会把这些字符发送到服务器,然后服务器会返回一个搜索建议的列表。
- 就和国内百度的搜索框一样!
- 传统的网页(即不用 ajax 技术的网页),想要更新内容或者提交一个表单,都需要重新加载整个网页。
- 使用 ajax 技术的网页,通过在后台服务器进行少量的数据交换,就可以实现异步局部更新。
- 使用 Ajax,用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的 Web 用户界面。
-
新建一个项目,导入 web 支持
-
编写一个 前端页面,使用 iframe 进行测试
Title 请输入地址:
-
测试
- 使用jquery提供的,方便,有兴趣的可以自己去了解下 JS 原生 XMLHttpRequest !
- Ajax 的核心是 XMLHttpRequest 对象(XHR)。XHR 为向服务器发送请求和解析服务器响应提供了接口。能够以异步方式从服务器获取新数据。
- jQuery 提供多个与 AJAX 有关的方法。
- 通过 jQuery AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON – 同时您能够把这些外部数据直接载入网页的被选元素中。
- jQuery 不是生产者,而是大自然搬运工。
- jQuery Ajax本质就是 XMLHttpRequest,对他进行了封装,方便调用!
jQuery.ajax(...)
部分参数:
url:请求地址
type:请求方式,GET、POST(1.9.0之后用method)
headers:请求头
data:要发送的数据
contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
async:是否异步
timeout:设置请求超时时间(毫秒)
beforeSend:发送请求前执行的函数(全局)
complete:完成之后执行的回调函数(全局)
success:成功之后执行的回调函数(全局)
error:失败之后执行的回调函数(全局)
accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
dataType:将服务器端返回的数据转换成指定类型
"xml": 将服务器端返回的内容转换成xml格式
"text": 将服务器端返回的内容转换成普通文本格式
"html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含Javascript标签,则会尝试去执行。
"script": 尝试将返回值当作Javascript去执行,然后再将服务器端返回的内容转换成普通文本格式
"json": 将服务器端返回的内容转换成相应的Javascript对象
"jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数
11.5 原始的 HttpServletResponse 实现
-
配置 web.xml
springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:applicationContext.xml 1 springmvc / encoding org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 encoding @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 "success"; } -
配置 Tomcat
-
测试
步骤:
- 设置 response 响应头
- 读取文件 – InputStream
- 写出文件 – OutputStream
- 执行操作
- 关闭流 (先开后关)
Controller 类添加
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "baidu.png";
//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 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;
}
前端添加
点击下载
测试



