了解SpringMvc之前先看看Mvc的工作原理
1、MVC工作原理
-
M:Model(完成业务逻辑 Service/dao/entity/)
-
V:View(完成界面渲染 jsp/html)
-
C:Controller(控制器->类似于CPU 接受请求->调用M->返回V)
-
MVC工作原理图
2、SpringMvc工作原理
1.Spring和SpringMvc的关系:
SpringMVC是一个MVC的开源框架,SpringMVC是Spring的一个后续产品,其实就是Spring在原有基础上,又提供了web应用的MVC模块,可以简单的把SpringMVC理解为是spring的一个模块(类似AOP,IOC这样的模块),底层使用Servlet实现,主要处理客户的请求和做出响应。简化web开发。
2.SpringMVC中的组件:
前端控制器(DispatcherServlet):(不需要工程师开发),由框架提供(重要)
Spring MVC 的入口函数。接收请求,响应结果,相当于转发器,中央处理器。有了 DispatcherServlet 减少了其它组件之间的耦合度。用户请求到达前端控制器,它就相当于mvc模式中的c,DispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性。
处理器映射器(HandlerMapping):根据请求的url查找Handler。HandlerMapping负责根据用户请求找到Handler即处理器(Controller),SpringMVC提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
处理器(Handler):(需要程序员去写代码处理逻辑的)controller
处理器适配器(HandlerAdapter):按照特定规则(HandlerAdapter要求的规则)去执行Handler 通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
视图解析器(ViewResovler):进行视图解析,多返回的字符串,进行处理,可以解析成对应的页面
视图View(需要工程师开发):View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)
注意:处理器Handler(也就是我们平常说的Controller控制器)以及视图层view都是需要我们自己手动开发的。其他的一些组件比如:前端控制器DispatcherServlet、处理器映射器HandlerMapping、处理器适配器HandlerAdapter等等都是框架提供给我们的,不需要自己手动开发。
3.SpringMvc工作原理图
SpringMvc工作流程
第一步:用户发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找
第三步:找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)
第四步:前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler),并处理相应的业务逻辑(也就是controller->service->dao)
第五步:处理器Handler执行完给处理器适配器返回ModelAndView对象
第六步:处理器适配器向前端控制器返回ModelAndView对象,Model 是返回的数据对象,View 是个逻辑上的 View
第七步:前端控制器请求视图解析器(ViewResolver)去进行视图解析,返最后回View对象
第八步:前端控制器对视图view进行渲染
第九步:最后前端控制器向用户响应结果
1.创建项目(springmvc实际上是web项目)
2.项目命名
3. 在WEB-INF目录下建classes和lib等目录
4,编写处理器
package com.wxz;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* TODO
*
* @author wxz
* @date 2022/2/18 20:29
*/
@Controller
public class TestController {
@RequestMapping("/testmvc.do")
public String test() {
return "index.jsp";
}
}
5.编写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/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开始相关注解配置 -->
<!-- 组件扫描 -->
<context:component-scan base-package="com.wxz"></context:component-scan>
<!-- 开启SpringMVC相关注解 -->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
6.编写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">
<!-- 配置springmvc的控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 配置SpringMVC初始化文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 项目启动时就初始化DispatcherServlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- 配置spring内置的编码过滤器 -->
<filter>
<filter-name>charset</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>charset</filter-name>
<servlet-name>springmvc</servlet-name>
</filter-mapping>
</web-app>
7.导入jiar包
8.打包
9.配置tomcat
10.放入tomcat中运行
11. 运行项目
12.页面访问
关于WEB-INF目录下面的jsp不能直接被访问问题
WEB-INF目录下的jsp文件,在浏览器中是不能直接访问的。(没有访问的权限,禁止访问) 如果将jsp文件放入WEB-INF目录下,将不能访问。
在java web项目部署到服务器的以后,项目的目录结构是WebContent下的所有文件夹。如果将jsp/html页面放到WEB-INF目录外面,可以直接请求这个页面。但是多数情况下我们会将页面放到WEB-INF目录下。
页面放在WEB-INF目录下,这样可以限制访问提高安全性。web-inf目录下的文件只能通过请求转发来访问,不能通过页面重定向访问。
WEB-INF目录下面是静态资源,不能直接被访问
index.jsp list.jsp都是可以访问的
怎么才能正常的访问WEB-INF下面的jsp呢??
第一种方式??
第二种方式:
获取页面的数据,获取客户端的数据
<%--
User:
Date: 2022/2/19
Time: 17:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!-- 普通文本数据 -->
<form action="hello/word.do" method="post">
<p>
用户名:
<input type="text" name="userName" />
</p>
<p>
年龄:
<input type="text" name="age" />
</p>
<p>
性别:
<input type="radio" name="sex" value="男" />男
<input type="radio" name="sex" value="女" />女
</p>
<p>
爱好:
<input type="checkbox" name="like" value="篮球" />篮球
<input type="checkbox" name="like" value="足球" />足球
</p>
<p>
城市:
<select name="city">
<option value="wh" >武汉</option>
<option value="sh" >上海</option>
</select>
</p>
<input type="submit" value="提交" />
</form>
</body>
</html>
无法获取到数组的值,要想获取到数组的值,只需要加注解@RequestParam
使用map接收参数
使用java对象接受参数
//使用简单java对象接收请求参数
@RequestMapping("/word3.do")
public void getParam4(User user) {
System.out.println(user);
}
视图解析器配置
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图的前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!-- 配置视图的后缀 -->
<!-- <property name="suffix" value=".jsp"></property> -->
</bean>
springmvc返回json数据
在springmvc中,所有的controller在返回的数据中,若是字符串,则默认当做视图的名称。springmvc会根据这个名称,查找视图,然后进行解析,返回给客户端。没有办法直接返回json字符串。
在springmvc中,使用@ResponseBody,标识返回的结果是一个json字符串。
使用Springmvc中支持默认自动转换
在springmvc中,springmvc默认是支持自动将对象转化为JSON字符串。且编码格式UTF-8.
但是springmvc默认支持json转化类,使用的jackson。需要主动的导入jackson的相关jar包。
1.导入jackson相关jar包
jackson-annotations-2.9.9.jar
jackson-core-2.9.9.jar
jackson-databind-2.9.9.jar
2.相关代码
@RequestMapping(value ="list.do")
@ResponseBody
public Object list2(Model model,HttpServletResponse resp,HttpServletRequest req) throws IOException {
String contentType = req.getContentType();
System.out.println(contentType);
List<User> users = userService.selectList();
//将数据转化为JSON字符串
//String jsonString = JSONObject.toJSONString(users);
//将字符串返回
return users;
}
文件上传
springmvc简化文件上传的工作,只需要导入相关的jar包,配置处理器,使用参数接收上传的文件即可。
1.导入相关jar包
commons-fileupload-1.3.1.jar
commons-io-2.4.jar
2.配置文件上传的处理器
<!-- 配置文件上传 解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
3.使用参数接收上传文件
//注意:接收上传的文件 一定要使用 MultipartFile 类型接收,当多个同名的文件时,使用数组接收
//当表单名称和方法中形式参数名不一致时,可以使用@RequestParam
@RequestMapping("upload.do")
public void upload(MultipartFile[] file,String text) throws IllegalStateException, IOException {
System.out.println(file);
for (MultipartFile multipartFile : file) {
System.out.println("form表单提交的名称"+multipartFile.getName());
System.out.println("请求数据的类型:"+multipartFile.getContentType());
System.out.println("文件名称:"+multipartFile.getOriginalFilename());
System.out.println("文件的大小"+multipartFile.getSize());
//将文件保存在物理磁盘上
//file.transferTo(new File("E:\\test.jpg"));
}
System.out.println(text);
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="upload.do" method="post" enctype="multipart/form-data">
文件:<input type="file" name="file"/><br>
<input type="submit" value="提交" />
</form>
</body>
</html>
springmvc中拦截器
在springmvc,为了更好控制处理器,spring提供了拦截器,用于介入控制器的执行。
只需要定义实现HandlerInterceptor接口,配置拦截地址即可。
1.实现HandlerInterceptor接口
package com.wxz.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class MyInterceptor implements HandlerInterceptor {
/**
* 拦截器中第一个执行的方法 : 返回值为true时 放行 为 false 则拦截
* request : HTTP请求对象
* response : HTTP响应对象
* handler : 待执行的方法
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("handler:"+handler);
System.out.println("======preHandle=========");
return true;
}
/**
* postHandle 在具体的handler执行完成后执行
* 在具体的handle执行完成后 但是 视图解析完成前
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
modelAndView.addObject("key", "我是在拦截器中放入的参数");
System.out.println("============postHandle==========");
}
/**
* afterCompletion 在具体的handler执行完成后执行
* 视图解析后
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("===========afterCompletion============");
}
}
2.配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截地址 -->
<!-- 拦截所有的路径 -->
<mvc:mapping path="/**"/>
<!-- 排除地址 -->
<mvc:exclude-mapping path="/test2.do"/>
<!-- 具体的拦截器 -->
<bean id="myInterceptor" class="com.wxz.interceptor.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
注意:
springmvc的拦截器,主要拦截Handler,由于拦截器是在DispatchServlet中执行,所以若你的url地址,根据不走DispatchServlet,那么拦截器将不会拦截。
在web项目中,一定存在filter但是未必存在HandlerInterceptor,而Filter的拦截是针对所有的请求,但是Interceptor针对的具体的Handler。