SpringMVC
1 什么是SpringMVC
1.1 什么是MVC
- MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范
- Model(模型):数据模型、提供要展示的数据,因此包含数据和行为,可以认为是领域模块或JavaBean
- View(视图):负责进行模型的展示,一般就是我们见到的用户界面
- Controller(控制器):接收用户请求,委托给模型进行处理,处理完后把返回的模型数据返回给视图,由视图负责展示
- 用将业务逻辑、数据、显示分离的方法来组织代码
- MVC主要作用是降低了视图与业务逻辑间的双向耦合
- MVC是一种架构模式
1.2 SpringMVC概述
SpringMVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。
SpringMVC的特点:
- 轻量级,简洁灵活,简单易学
- 高效,基于请求响应的MVC框架
- 与Spring兼容性好,无缝结合
- 约束优于配置
- 功能强大:Restful、数据验证、格式化、本地化、主题等
SpringMVC框架围绕DispatcherServlet(调度Servlet)设计,DispatcherServlet的作用是将请求分发到不同的处理器。
1.3 SpringMVC执行原理
执行流程:
- DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
例如url为:http://localhost:8080/SpringMVC/hello- http://localhost:8080:服务器域名
- SpringMVC:部署在服务器上的web站点
- hello:控制器
- HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping。HandlerMapping根据请求的url来查找Handler。
- HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器。
- HandlerExecution将解析后的信息传递给DispatcherServlet。
- HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
- Handler让具体的Controller执行。
- Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
- HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
- DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
- 视图解析器将解析的逻辑视图名传给DispatcherServlet。
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
- 最终视图呈现给用户。
2 实现SpringMVC操作
2.1 原理版(理解)
- 导入SpringMVC、servlet、jsp等依赖包
配置web.xml,注册DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 注册DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 关联一个springMVC的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 配置启动级别:1 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--
/ 匹配所有请求,不包括.jsp文件
/* 匹配所有请求,包括.jsp文件
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
编写SpringMVC配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
添加处理映射器
<!-- 配置处理映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
添加处理器适配器
<!-- 配置处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
添加视图解析器
<!-- 配置视图解析器:DispatcherServlet给他的ModelAndView -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀:prefix -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀:suffix -->
<property name="suffix" value=".jsp"/>
</bean>
编写操作业务的Controller,实现Controller接口,需要返回一个ModelAndView,装数据,封视图
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// ModeAndView 模型和视图
ModelAndView view = new ModelAndView();
// 处理业务层代码
String message = "HelloSpringMVC";
view.addObject("msg", message);
// 跳转或重定向页面
view.setViewName("hello");
return view;
}
}
将实现了Controller接口的类注入到Spring,注册bean
<!-- 配置视图名字,即BeanNameUrlHandlerMapping需要controller类的注入 -->
<!-- Handler -->
<bean id="/hello" class="com.falshce.controller.HelloController"/>
编写跳转的jsp页面,显示存放的数据
2.1 注解版(常用)
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<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>
</web-app>
添加SpringMVC配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.falsche.controller"/>
<!-- 让SpringMVC不处理静态资源,例如html,js,css等 -->
<mvc:default-servlet-handler/>
<!--
1、支持mvc注解驱动,使springmvc的注解生效
例如:@RequestMapping,用来完成映射关系
2、annotation-driven会自动完成
DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter的注册
-->
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
- 在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。
- 让IOC的注解生效
- 静态资源过滤 :HTML . JS . CSS . 图片 , 视频 …..
- MVC的注解驱动
- 配置视图解析器
创建一个控制类,使用@Controller实现
@Controller
public class ControllerTest1 {
@RequestMapping("/h1")
public String hello(@Nullable Model model){
model.addAttribute("msg", "HelloSpringMVC_Annotation");
return "hello";
}
}
- @Controller是为了让SpringIOC容器初始化时扫描到
- @RequestMapping是为了映射请求路径
- 方法中声明Model类型的参数是为了把Action中的数据带到视图中
- 方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。
- 编写跳转的jsp页面,显示存放的数据
3 RestFul风格
POST、GET、DELETE、PUT不同的请求方式
4 数据处理
4.1 前端提交数据到后端
提交的数据名称和处理方法的参数名一致
可以直接在方法参数中定义。例如:提交数据为 http://localhost:8080/hello?name=xxx@RequestMapping("/hello")
public String hello(String name){
return "hello";
}
提交的数据名称和处理方法的参数名不一致
例如:提交数据为 http://localhost:8080/hello?username=xxx@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
return "hello";
}
提交的数据是一个对象,比如User对象
- 封装User类
- 提交数据:http://localhost:8080/mvc/user?name=xxx&id=1
- 处理方法:
@RequetMapping("/user")
public String user(User user){
return "hello";
}
4.2 数据显示到前端
- 通过该ModelAndView
- 通过ModelMap
- 通过Model
对比:
- Model是精简版。(大部分情况用Model)
- ModelMap继承了LinkedMap。
- ModelAndView可以在储存数据的同时,也可以进行设置返回的逻辑视图,进行控制展示层的跳转。(原理)
4.3 解决乱码问题
使用SpringMVC自带的过滤器,可以解决大部分乱码问题。
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
5 JSON
5.1 什么是JSON
- JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交换格式。
- 采用完全独立于编程语言的文本格式来存储和表示数据。
- 简洁和清晰的层次结构使得JSON成为理想的数据交换语言。
- 易于人阅读和编写,同时也易于机器解析和生成,有效地提升网络传输效率。
语法和格式要求:
- 对象表示为键值对,数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
5.2 JSON和JavaScript对象互转
// 把JavaScript对象转换成JSON字符串,使用JSON.stringify()方法
var json = JSON.stringify(user);
// 把JSON字符串转换为JavaScript对象,使用JSON.parse()方法
var parse = JSON.parse(json);
5.3 JSON和Java对象互转(基于fastjson)
fastjson三个主要类:
JSONObject 代表 json 对象
- JSONObject 实现了 Map 接口。
- JSONObject 对应 json 对象,通过各种形式的 get() 方法可以获取 json 对象中的数据,也可利用诸如 size() ,isEmpty() 等方法获取”键:值”对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。
JSONArray 代表 json 对象数组
- 内部是有 List 接口中的方法来完成操作的。
JSON 代表 JSONObject 和 JSONArray 的转化
- JSON 类源码分析与使用。
- 主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。
在Controller中,Java转JSON
- @Controller和@ResponseBody,使这个方法不走视图解析器
@RestController,使用这个注解就可以不用@Controller和@ResponseBody了
@RequestMapping("/json")
@ResponseBody // @ResponseBody不会走视图解析器,会直接返回一个字符串
public String json() throws JsonProcessingException {
System.out.println("*******Java对象 转 JSON字符串*******");
String str1 = JSON.toJSONString(list);
System.out.println("JSON.toJSONString(list)==>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)==>"+str2);
System.out.println("\n****** Java对象 转 JSON对象 ******");
JSONObject object = (JSONObject) JSON.toJSON(user2);
System.out.println("(JSONObject) JSON.toJSON(user2)==>" + object.getString("name"));
}
JSON转Java
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****** JSON对象 转 Java对象 ******");
User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
5.4 SpringMVC中JSON乱码问题(jackson)
<!--jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
<!-- JSON解决乱码问题 -->
<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>
6 Ajax
6.1 Ajax传值给Controller
无论Ajax以什么形式发送数据,在Controller中的接收方法都没有差异
对象 | 操作 | key/value类型 | JSON | 序列化表单 |
---|---|---|---|---|
Ajax | 发送 | data: ‘name=’+name | data: {‘name’: name} | data:$(“#form”).serialize() |
Controller | 接收 | public void receive(String name) / (User user) | public void receive(String name) / (User user) | public void receive(String name) / (User user) |
6.2 Controller返回值给Ajax
- Controller返回json类型的数据需要加@RespsonseBody注解
- Ajax的返回值data可以是任何名称 | 对象 | 操作 | JSON | JSON | | :—-: | :—-: | :—-: | :—-: | | | | pojo类型 | map类型 | | Controller | 发送 | return Msg; | return map; | | Ajax | 接收 | success:function(data){ alert(data.result) | success:function(data){ alert(data.result) |
7 拦截器
想要自定义拦截器,必须实现 HandlerInterceptor 接口。
创建一个拦截器
public class MyInterceptor implements HandlerInterceptor {
//在请求处理的方法之前执行
//如果返回true执行下一个拦截器
//如果返回false就不执行下一个拦截器
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("------------处理前------------");
return true;
}
//在请求处理方法执行之后执行
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("------------处理后------------");
}
//在dispatcherServlet处理后执行,做清理工作.
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("------------清理------------");
}
}
在springmvc的配置文件中配置拦截器
<!--关于拦截器的配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
<!--/admin/** 拦截的是/admin/下的所有-->
<mvc:mapping path="/**"/>
<!--bean配置的就是拦截器-->
<bean class="com.kuang.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
@RequestParam注解
1、可以对传入参数指定参数名
1 @RequestParam String inputStr
2 // 下面的对传入参数指定为aa,如果前端不传aa参数名,会报错
3 @RequestParam(value="aa") String inputStr
2、可以通过required=false或者true来要求@RequestParam配置的前端参数是否一定要传
1 // required=false表示不传的话,会给参数赋值为null,required=true就是必须要有
2 @RequestMapping("testRequestParam")
3 public String filesUpload(@RequestParam(value="aa", required=true) String inputStr, HttpServletRequest request)
3、如果@requestParam注解的参数是int类型,并且required=false,此时如果不传参数的话,会报错。原因是,required=false时,不传参数的话,会给参数赋值null,这样就会把null赋值给了int,因此会报错。
1 // required=false表示不传的话,会给参数赋值为null,required=true就是必须要有
2 @RequestMapping("testRequestParam")
3 public String filesUpload(@RequestParam(value="aa", required=false) int inputStr, HttpServletRequest request)
4 若是前端页面不传参的话,此处就会报错。当然可以用Integer代替int