ssm:mybatis+Spring+SpringMVC MVC三层架构
什么是MVC
- MVC是模型(Model)、视图(View)、控制器(Controller)的简辱,是一种软件设计规范。
- 是将业务逻辑、数据、显示分离的方法来组织代码。
- MVC主要作用是降低了视图与业务逻辑间的双向偶合。
- MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。
Model(模型)︰数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来: Value Object(数据Dao)和服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图)︰负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
Controller(控制器)∶接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。
最经典的MVC就是JSP+Servlet+Javabean模式。
- 用户发送请求
- Servlet接受请求数据,并调用对应的业务逻辑方法
- 业务处理完毕,返回更新后的数据给Servlet
- Servlet转向到JSP,由JSP来渲染页面
- 响应给前端更新后的页面
职责分析:
Controller:控制器
- 取得表单数据
- 调用业务逻辑
- 转向指定的页面
Model:模型
- 业务逻辑
- 保存数据的状态
View:视图
- 显示页面
Model2这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。Model 1模式的实现比较简单,适用于快速开发小规模项目,Model1中JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。Model2消除了Model1的缺点。
回顾Servlet
1、新建一个Maven工程当做父工程!pom依赖!
<!--导入依赖-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.13</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>
2、建立一个Moudle:springmvc-01-servlet,添加Web app的支持
3、导入Servlet和JSP的jar依赖
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
</dependency>
</dependencies>
4、编写一个Servlet类,用来处理用户的请求
//实现Servlet接口
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);
}
}
5、编写Hello.jsp,在WEB-INF目录下新建一个jsp的文件夹,新建hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
6.在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.hzx.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>
</web-app>
7、配置Tomcat,并启动测试
- localhost:8080/user?method=add
- localhost:8080/user?method=delete
MVC框架要做哪些事情
- 将url映射到Java类或Java类的方法
- 封装用户提交的数据
- 处理请求--调用相关的业务处理--封装响应数据
- 将响应的数据进行渲染jsp/html等表示层数据
说明:
常见的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework,JSF;常见前端MVC框架: vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM等等....
MVVM: M V VM-->ViewModel:双向绑定
SpringMVC
什么是SpringMVC
SpringMVC是SpringFramework的一部分,是基于Java实现MVC的轻量级Web框架
为什么要学SpringMVC
SpringMVC的特点:
- 轻量级,简单易学
- 高效,基于请求响应的MVC框架
- 与Spring兼容性好,无缝结合
- 约定优于配置
- 功能强大:RESTful、数据验证、格式化、本地化、主题等
- 简介灵活
Spring的web框架围绕DispatcherServlet[调度Servlet ]设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;
正因为SpringMVC好,简单,便捷,易学,天生和Spring无缝集成(使用SpringloC和Aop),使用约定优于配置﹒能够进行简单的junit测试﹒支持Restful风格﹒异常处理,本地化,国际化,数据验证,类型转换,拦截器等等......所以我们要学习.
中心控制器
Spring的web框架围绕DispatcherServlet设计。DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。
Spring MVC框架像许多其他MVC框架一样,以请求为驱动,围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet(它继承自HttpServlet基类)。
SpringMVC的原理如下图所示:
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。
springMVC执行流程
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表示处理器适配器,其按照特定的规则去执行Handler。
6. Handler让具体的Controller执行。
7.Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
8.HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
9. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
10.视图解析器将解析的逻辑视图名传给DispatcherServlet。
11.DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。12.最终视图呈现给用户。
Controller和RestFul风格
Controller
控制器Controller
- 控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现
- 控制器负责解析用户的请求并将其转换为一个模型。
- 在Spring MVC中一个控制器类可以包含多个方法
- 在Spring MVC中,对于Controller的配置方式有很多种
RestFul风格
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
功能
- 资源:互联网所有的事物都可以被抽象为资源
- 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作
- 分别对应添加、删除、修改、查询
传统方式操作资源︰通过不同的参数来实现不同的效果!方法单一,post和get
- http://127.0.0.1/item/queryltem.action?id=1查询,GET
- http://127.0.0.1/item/saveltem.action新增,POST
- http://127.0.0.1/item/updateltem.action更新,POST
- http://127.0.0.1/item/deleteltem.action?id=1删除,GET或POST
使用RESTful操作资源︰可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
- http://127.0.0.校/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
结果跳转方式
ModelAndView
设置ModelAndView对象,根据view的名称,和视图解析器跳到指定的页面
页面︰{视图解析器前缀}+ viewName +{视图解析器后缀}
ServletAPI
通过设置ServletAPI,不需要视图解析器
1.通过HttpServletResponse进行输出
2.通过HttpServletResponse实现重定向
3.通过HttpServletResponse实现转发
SpringMVC
SpirngMVC重定向和转发 有无视图解析器
SpringMVC数据处理
1.提交的域名称和处理方法的参数名一致
提交数据:http://localhost:8080/hello?name=kuangshen
处理方法:
@RequestMapping("/hello")
public String hello(String name){
System.out.println(name);
return "hello";
}
后台输出:kuangshen
2.提交的域名称和处理方法的参数名不一致
提交数据:http://localhost:8080/hello?username=kuangshen
处理方式:
//@RequestParam("username") username提交的域的名称
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
System.out.println(name);
return "hello";
}
后台输出:kuangshen
3.提交的是一个对象
要求提交的表单域和对象的属性名一致,参数使用对象即可。
说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。
数据显示对比
Model只有寥寥几个方法只适合用于储存数据,简化了新手对于Nodel对象的操作和理解;
ModelMap继承了LinkedMap ,除了实现了自身的一些方法,同样的继承LinkedMap的方法和特性;
ModelAndview 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
JSON讲解
什么是JSON?
- JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交换格式,目前使用特别广泛。
- 采用完全独立于编程语言的文本格式来存储和表示数据。·简洁和清晰的层次结构使得JSON成为理想的数据交换语言。
- 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在JavaScript 语言中,一切都是对象。因此,任何JavaScript支持的类型都可以通过JSON来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:
- 对象表示为键值对,数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
JSON键值对是用来保存JavaScript对象的一种方式,和JavaScript对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号""包裹,使用冒号∶分隔,然后紧接着值:
{"name":"hzx"}
很多人搞不清楚JSON和JavaScript对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:
- JSON是JavaScript对象的字符串表示法,它使用文本表示一个JS对象的信息,本质是一个字符串。
var obj = {a:'hello',b:'world'};//这是一个对象 注意键名也是可以使用引号包裹的 var json = '{"a":"hello","b":"world"}';//这是一个JSON字符串,本质是一个字符串
JSON和JavaScript对象互转
- 要实现从JSON字符串转换为JavaScript对象,使用JSON.parse()方法:
var obj = JSON.parse('{"a":"hello","b":"world"}'); //结果是{a:'hello',b:'world'}
- 要实现从JavaScript对象转换为JSON字符串,使用JSON.stringify()方法:
var json = JSON.stringify({a:'hello',b:'world'}); // 结果是'{"a":"hello","b":"world"}'
Controller返回JSON数据
- Jackson应该是目前比较好的json解析工具了
- 当然工具不止这一个,比如还有阿里巴巴的fastjson等等
- 我们这里使用Jackson,使用它需要导入它的jar包;
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.0</version> </dependency>
Json工具类:
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;
}
}
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用户界面。
伪造Ajax
iframe
js:
- 函数:闭包
- DOM
- id,name,tag
- create,remove
- BOM
- window
- document
ES6:import require
拦截器
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。
过滤器与拦截器的区别:拦截器是AOP思想的具体应用。
过滤器
- servlet规范中的一部分,任何java web工程都可以使用
- 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截
拦截器
- 拦截器是Spring MVC框架自己的,只有使用了SpringMVC框架的工程才能使用
- 拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会进行拦截的
<!-- 拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<!-- 包括这个请求下的所有请求 -->
<mvc:mapping path="/**"/>
<bean class="com.hzx.config.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
文件上传
<!-- 文件上传配置 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 请求的编码格式 必须和jsp的pageEncoding属性一致 以便正确读取表单的内容 默认为ISO-8859-1 -->
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 上传文件大小上限 单位为字节 (10485760=10M) -->
<property name="maxUploadSize" value="10485760"></property>
<property name="maxInMemorySize" value="40960"></property>
</bean>
文件上传下载
package com.hzx.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 javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@RestController
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);
//上传路径保存设置
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";
}
/*
采用filie.Transto来保存上传的文件
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file")CommonsMultipartFile file,HttpServletRequest request) throws IOException {
//上传路径保存设置
String path = request.getSession().getServletContext().getRealPath("/upload");
//如果路径不存在 创建一个
File realPath = new File(path);
if(!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
//通过ConmmonsMultipartFile的方法直接写文件
file.transferTo(new File(realPath+"/"+file.getOriginalFilename()));
return "redirect:/index.jsp";
}
/**
* 文件下载
*/
@RequestMapping("/download")
public String downloads(HttpServletResponse response,HttpServletRequest request) throws IOException {
//要下载的图片地址
String path = request.getSession().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 inputStream = new FileInputStream(file);
//3、写出文件 输出流
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
//4、执行 写出擦欧总
while((len = inputStream.read(buffer)) != -1){
outputStream.write(buffer,0,len);
outputStream.flush();
}
outputStream.close();
inputStream.close();
return null;
}
}
学Java关注狂神说