目录
1、概念
1.1、什么是SpringMVC
1.2、B/S架构
B/S架构是基于三层架构的,三层架构可分为:表现层、业务层、持久层。表现层:也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求 web 层,web 需要接收 http 请求,完成 http 响应。表现层包括展示层和控制层,控制层负责接收请求,展示层负责结果的展示。 表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。 表现层的设计一般都使用 MVC 模型。注:MVC 是表现层的设计模型,和其他层没有关系!!!
表现层:表现层就是JSP/html+ajax。JSP=html+java。虽然JSP的实现功能和html+ajax一样,但JSP在原理上还是有区别于html+ajax的。JSP本质上就是一个java的servlet类,JSP中包含了HTML代码和Java代码,JSP的编译是在服务器端进行的,服务器把JSP编译成一个Servlet,通过Java代码获取后台数据后拼接到HTML片段中,最终通过out.println()输出。
总得来说,JSP就是在服务器端对数据和html页面组装好,再将其反馈给客户端。JSP的局限性在于必须在服务器端就把数据和html页面装在完毕。而html+ajax就是通过ajax技术把数据分装成json或者xml,可以单独的分别向客户端发送数据和html页面,然后在客户进行组装。通常现在比较流行的前后端分离技术,就是html+ajax,使用ajax相关技术获取后台接口返回的数据(xml或者json格式)然后在html页面进行组装渲染,最终呈现给用户。
有关JSP的详细了解可以参考:https://zhuanlan.zhihu.com/p/42343690?utm_source=wechat_session&utm_medium=social&s_r=0#showWechatShareTip
1.3、MVC结构
1.4、Spring MVC常用名词
1、DispatcherServlet(前端控制器):用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。
2、HandlerMapping(处理器映射):HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、Handler(处理器):它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。
4、HandlAdapter(处理器适配器):通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
5、View Resolver(视图解析器):View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
6、View(视图):SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
1.5、常用注解
1、@RequestMapping
作用:@RequestMapping这个注解是出现在类上的,是请求 URL 的第一级访问目录。不写的话,就相当于应用的根目录。写的话需要以 / 开头。 它出现的目的是为了使我们的 URL 可以按照模块化管理。
属性:
value:用于指定请求的 URL。它和 path 属性的作用是一样的。
method:用于指定请求的方式。
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。
2、@RequestParam
3、@RequestBody
1.6、rest和restfull
通俗的来说,rest是一种软件架构,面向接口编程,前后端分离。使得每个模块的开发者更加专注于自己模块的功能实现,而无需花费太多的精力在各个模块直接如何相互关联上面。restful可以提供一个统一的接口规范,开发者实现了什么功能,直接将其封装成一个接口,其他系统如果要用到这个功能,直接调用这个接口,获取返回值即可。
具体可以参考:https://www.zhihu.com/question/28557115
1.7、Request和Response
Request 和Response 对象起到了服务器与客户机之间的信息传递作用。Request 对象用于接收客户端浏览器提交的数据,而 Response 对象的功能则是将服务器端的数据发送到客户端浏览器。
一、Request对象:
QueryString:用以获取客户端附在url地址后的查询字符串中的信息。
例如:stra=Request.QueryString ["strUserld"]
Form:用以获取客户端在FORM表单中所输入的信息。(表单的method属性值需要为POST)
例如:stra=Request.Form["strUserld"]
Cookies:用以获取客户端的Cookie信息。
例如:stra=Request.Cookies["strUserld"]
ServerVariables:用以获取客户端发出的HTTP请求信息中的头信息及服务器端环境变量信息。
例如:stra=Request.ServerVariables["REMOTE_ADDR"],返回客户端IP地址
ClientCertificate:用以获取客户端的身份验证信息
例如:stra=Request.ClientCertificate["VALIDFORM"],对于要求安全验证的网站,返回有效起始日期。
二、Response方法:
Write:向客户端发送浏览器能够处理的各种数据,包括:html代码,脚本程序等。
Redirect:response.redirect("url")的作用是在服务器端重定向于另一个网页。
End:用来终止脚本程序。
Clear:要说到Clear方法,就必须提到response的Buffer属性,Buffer属性用来设置服务器端是否将页面先输出到缓冲区。语法为:Response.Buffer=True/False
Flush:当Buffer的值为True时,Flush方法用于将缓冲区中的当前页面内容立刻输出到客户端。
1.7、session、model、cookie
1、session
session是服务器端的缓存,session是一个会话。什么是会话?所谓会话就是某个客户端与服务端交互通信的过程。比如:登录界面输入用户名密码进行登录,用户名密码就会发往后台,后台进行验证然后把结果反馈给登录界面,这就是一次会话。session代表服务器与浏览器的一次会话过程,这个过程是连续的,也可以时断时续的。session里放的数据可以在其他页面使用(前提是这个session会话没有断开过期,如果这个session过期了,session中的数据就没有了)。
2、model
model是request级别的,model和session一样都是服务器缓存,只是不同于session,model的数据,只能在接下来的页面使用,其他页面就不能使用。因为model只是一个请求,model的作用域只是可以作用于请求model的那个页面,其他页面无法使用。
3、cookie
cookie是浏览器缓存,是存放在客户端的。
1.7.1、session、model、cookie的使用
1.8、forward和redirect
forward和redirect的功能是一样的,都是转发请求。
forward和redirect的不同之处在于forward是直接转发而redirect是间接转发。
forward: 客户端浏览器只发出一次请求,Servlet把请求转发给Servlet、HTML、JSP或其它信息资源,由第2个信息资源响应该请求,两个信息资源共享同一个request对象。
redirect:服务器端在响应第一次请求的时候,让浏览器再向另外一个URL发出请求,从而达到转发的目的。它本质上是两次HTTP请求,对应两个request对象。
关于forward和redirect的详细信息可参考:https://www.cnblogs.com/selene/p/4518246.html#_label0
2、SpringMVC异常处理
1、不进行异常处理,Spring MVC默认的异常处理流程
2、在前端控制器设置异常处理界面,使得如果系统发生了异常,则系统异常不直接展示给用户
3、一个简单的SpringMVC异常处理demo
MyException.java
package com.springmvc.exception;
/**
* 自定义的异常类
*
* @author:wu linchun
* @date 2021年1月25日
* @time 下午4:28:47
*/
public class MyException extends Exception {
//异常信息
private String message;
public MyException(String message) {
super();
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
MyExceptionResolver.java
package com.springmvc.exception;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
/**
* 异常处理器
*
* @author:wu linchun
* @date 2021年1月25日
* @time 下午4:30:19
*/
public class MyExceptionResolver implements HandlerExceptionResolver {
/**
* 跳转到错误页面的方法
*/
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
MyException me=null;
//获取异常对象
if(ex instanceof MyException) {
me=(MyException) ex;
}else {
me=new MyException("正在建设中......");
}
ModelAndView mv=new ModelAndView();
//存入错误的提示信息
mv.addObject("message", me.getMessage());
//要跳转的jsp页面(如果出现异常,就跳转到error界面)
mv.setViewName("error");
return mv;
}
}
在springmvc.xml中添加配置异常处理器
<!-- 配置异常处理器 -->
<bean id="myExceptionResolver"
class="com.springmvc.exception.MyExceptionResolver"></bean> <!--自己定义的异常处理类MyExceptionResolver.java -->
MyController.java
@RequestMapping(value = {"/myhtml"})
public String myhtml(){
System.out.println("返回myhtml页面");
int i=1/0; //模拟系统异常情况
return "myhtml";
}
3、Spring MVC返回一个html页面
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 搜索spring控件 -->
<context:component-scan base-package="com.springmvc"></context:component-scan>
<!-- 视图页面配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/html/</value>
</property>
<property name="suffix">
<value>.html</value>
</property>
</bean>
<!-- 配置异常处理器 -->
<bean id="myExceptionResolver"
class="com.springmvc.exception.MyExceptionResolver"></bean> <!--自己定义的异常处理类MyExceptionResolver.java -->
</beans>
<?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">
<display-name>Archetype Created Web Application</display-name>
<!--配置前端控制器-->
<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:springMvc.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>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!--配置解决中文乱码的过滤器-->
<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>
</web-app>
pom.xml
<?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>org.example</groupId>
<artifactId>SpringMVC_Demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
4、SpringMVC拦截器
4.1、拦截器概述
- 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
- 拦截器是SpringMVC框架独有的。
- 过滤器配置了/*,可以拦截任何资源。
- 拦截器只会对控制器中的方法进行拦截。
- 拦截器也是AOP思想的一种实现方式
- 想要自定义拦截器,需要实现HandlerInterceptor接口。
自定义一个拦截器类实现HandlerInterceptor接口
package com.springmvc.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* 自定义拦截器
*
* @author:wu linchun
* @date 2021年1月27日
* @time 下午4:53:22
*/
public class MyInterceptor1 implements HandlerInterceptor {
/**
* 预处理,controller方法执行前
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false不放行
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("执行了拦截(前)");
response.sendRedirect("/SpringMVC_Demo/mycontroller/nopower"); //如果页面被拦截了,就会跳转到”nopower“这个界面
return false;
}
/**
* 后处理,controller类中xxx()方法执行后,返回页面之前执行
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
System.out.println("执行了拦截(后)");
}
/**
* 最终处理:返回页面之后执行,最后执行
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("执行了拦截(最终)");
}
}
在springmvc.xml新增 <mvc:interceptors> 配置
<!--配置拦截器 -->
<mvc:interceptors>
<!--配置拦截器 -->
<mvc:interceptor>
<!--要拦截的具体的方法 -->
<mvc:mapping path="/mycontroller/*" /> <!-- /mycontroller/*表示拦截mycontroller下的所有方法 --> <!-- /**表示所有方法全部拦截 -->
<!--不要拦截的方法 <mvc:exclude-mapping path=""/> -->
<mvc:exclude-mapping path="/mycontroller/nopower"/>
<!--配置拦截器对象 -->
<bean class="com.springmvc.interceptor.MyInterceptor1" />
</mvc:interceptor>
</mvc:interceptors>
5、ajax技术
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。ajax是一种异步刷新技术,ajax可以实现与服务器交换技术,并且在不更新整个网页的情况下,部分更新网页中的内容。
5.1、一个简单的ajax的demo
首先要引入jquery.js
在springmvc.xml中配置一下前端控制器对静态资源的拦截,确保js目录下的jquery.min.js可以被使用到。
<!--前端控制器,哪些静态资源不拦截-->
<!-- 静态资源获取 -->
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>
<mvc:resources location="/css/" mapping="/css/**"/>
pom.xml
<!--导入json的jar包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
<version>0.0.20131108.vaadin1</version>
<scope>compile</scope>
</dependency>
user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script type="text/javascript">
function btn1() {
var txt_val = document.getElementById("txt_val").value;
$.ajax({ //注意:写ajax时一定要先导入jquery.js
type: "post",
url: "/mycontroller/getUser",
dataType: "json", //data传递的是一个json类型的值,而不是字符串,且必须标明dataType的类型,否则会出现400错误或者其他错误。
data: {'txt_val': txt_val},
success: function (data) {
document.getElementById("txt_userName").value = data.json_userName;
document.getElementById("txt_pwd").value = data.json_pwd;
}
});
}
</script>
</head>
<body>
<table>
<tr>
<td>序号</td>
<td><input type="text" id="txt_val"></td>
</tr>
<tr>
<td>用户名</td>
<td><input type="text" id="txt_userName"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="text" id="txt_pwd"></td>
</tr>
<tr>
<td>
<button id="btn" onclick="btn1()">发送ajax的请求</button>
</td>
</tr>
</table>
</body>
</html>
getUser()方法
@RequestMapping(path = "/getUser", method = RequestMethod.POST)
public void getUser(HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException {
String val=request.getParameter("txt_val");
System.out.println("获取前台ajax"+val);
User user=new User("aaa","123456");
response.setContentType("text/html;charset=utf-8"); //解决out.print()中文乱码
PrintWriter out = response.getWriter();
JSONObject json = new JSONObject();
json.put("json_userName",user.getUname());
json.put("json_pwd",user.getPassword());
out.print(json);
//return "error";
}
演示效果:
5.2、ajax的优点
- 页面无刷新,在页面内与服务器通信,给用户的体验非常好。
- 使用异步方式与服务器通信,不需要打断用户的操作,具有更加迅速的响应能力。
- 可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。
- 基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。
5.3、ajax的缺点
-
ajax干掉了back按钮,即对浏览器后退机制的破坏。后退按钮是一个标准的web站点的重要功能,但是它没法和js进行很好的合作。这是ajax所带来的一个比较严重的问题,因为用户往往是希望能够通过后退来取消前一次操作的。简单来说就是采用ajax技术的网页,用户浏览器的“前进”,“后退”键可能失效。