1. 简介
spring mvc是spring框架的一个组件,该组件的作用是在url访问与后台java bean之间起到访问控制,路由映射的作用,传统的是servlet + jsp + java,spring将这个流程整合为spring mvc。
模型(Model):指java bean产生的一些信息,如模型数据。
视图(View):jsp的统称,占位符,标签元素确定展示形式,可以引用前端js文件。
控制器(Controller):spring mvc主要起到路由与方法映射的作用,被映射的类称为控制器。
有两种方式配置url与控制类的映射,XML方式与java注解方式。
2. 请求流程
image.pngxml方式配置实现url映射
1)web.xml : 在web.xml中配置/与DispatcherServlet的映射,所有http请求都经过DispatcherServlet调度,DispatcherServlet将其转发到另一个具体映射类简单url处理器映射(SimpleUrlHandlerMapping),接下来流转到第二个配置文件springmvc-servlet.xml。
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2)springmvc-servlet.xml :在SimpleUrlHandlerMapping bean下配置具体url与Controller的映射,例如/index与indexController。
<bean id="simpleUrlHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/index">indexController</prop>
</props>
</property>
</bean>
<bean id="indexController" class="controller.IndexController"></bean>
3)控制器:IndexController.java : Controller会将http请求头request作为参数,此阶段可以获取url参数,经过逻辑处理后,通过模型与视图对象(ModelAndView)将模型数据与视图打包,此时的视图只是逻辑视图名index.jsp,
//@Controller//注解方式
public class IndexController {
//public class IndexController implements Controller {
//@RequestMapping("/index")// 忽略,这是注解方式映射路由,不同于xml方式
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView("index");
mav.addObject("message", "Hello Spring MVC4");
return mav;
}
}
4)后续数据流程 : 返回给DispatcherServlet,DispatcherServlet将逻辑视图与具体的视图匹配后,将数据注入到视图中,返回客户端进行渲染呈现。访问 http://127.0.0.1:8080/springmvc/index
3. 注解方式实现url映射
- web.xml不变,与xml方式配置相同。
- DispatcherServlet.xml文件中,将第二步代码注释,添加
<context:component-scan base-package = "controller"/>
指定组件扫描包,扫描的就是我们要用@Cotroller修饰的类。
- 在控制类用@Controller修饰,方法用@requestMaping(“/index”)作为路由映射
4.视图定位
1)为什么需要视图定位?
假设我们在localhost/spring/下放一些jsp文件,那么用户可以直接访问url就能获取,比如说用户通过尝试一些url,造成数据泄露
解决方法:我们在WEB-INF目录下新增page文件夹,将所有的jsp文件都放置到page目录下,使用户在不改变url:http://localhost/spring/index.jsp路径,依然能访问到资源,这种方法就是通过视图定位实现的。
做法: 在DispatcherServlet.xml文件中,增加用来控制视图定位的bean,如下
<bean id= "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name = "prefix" value= "/WEB-INF/page/"></property>
<property name = "suffix" value = ".jsp"> </property>
</bean>
还记得上一步控制类组装视图与模型数据么?ModelAndView一开始获取到的只是逻辑视图,就是一个jsp 的name,此时并没有与模型数据组合,此时返回给DispatcherSevlet,它将逻辑视图与真正的视图进行映射数据的组合,最后返回给客户端。
5. 接受表单数据
1)表单访问页
WebContent一级目录下创建addProduct.jsp页
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
//action属性相当于跳转到的目标路由
<form action = "addProduct" method = "post">
<input type = "text" name = "name" value = ""/>
<input type = "text" name = "price" value = ""/>
<input type = "submit" value = "add product"/>
</form>
2)实体类 :src/pojo/下创建Product.java作为实体类
package pojo;
public class Product {
private String name;
private float price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
3)控制类
上图为目录结构
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import pojo.Product;
@Controller
public class ProductController {
@RequestMapping("/addProduct")
public ModelAndView add(Product product) throws Exception{
ModelAndView mov = new ModelAndView("showProduct");
return mov;
}
}
解释 : addProduct.jsp 提交的name和price会自动注入到参数 product里,参数product会默认被当做值加入到ModelAndView 中,相当于mav.addObject("product",product);
4)生成新视图
创建ShowProduct.jsp用来M
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
name:${product.name}
price:${product.price}odelAndView注入数据的新视图
6.客户端跳转
相当于url重定向,访问/jump会重定向到/index
@RequestMapping("/jump")
public ModelAndView jump() {
ModelAndView moa = new ModelAndView("redirect:/index");
return moa;
}
7.用session记录回话访问次数
@RequestMapping("/check")
public ModelAndView getSession(HttpSession session) {
Integer count = (Integer)session.getAttribute("count");
if(count == null) {
count = 0;
}
count++;
session.setAttribute("count", count);
ModelAndView moa = new ModelAndView("check");
return moa;
}
- 在page下新建check.jsp视图
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
session中记录访问次数:${count}
-
访问下图url
image.png
8. 中文编码配置
在web.xml中添加如下
<!-- 中文乱码 -->
<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>
9. 上传文件
1)配置允许访问jpg文件,在web.xml中增加
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
2)DispatcherSevlet.xml中配置上传功能需要的 java bean
<!-- 上传功能支持 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<mvc:interceptors>
3)上传页面
WebContent下添加upload.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
<form action = "uploadImage" method = "post" enctype = "multipart/form-data">
<input type = "file" name = "image" accept = "image/*">
<input type = "submit" value = 上传>
</form>
4)接受图片类
pojo下新建UploadedImageFile,文件目录如下
加入如下代码
package pojo;
import org.springframework.web.multipart.MultipartFile;
public class UploadedImageFile {
MultipartFile image;
public MultipartFile getImage() {
return image;
}
public void setImage(MultipartFile image) {
this.image = image;
}
}
5)控制类 UploadController
//上传没问题,路径显示有问题
@Controller
public class UploadController {
@RequestMapping("/uploadImage")
public ModelAndView upload(HttpServletRequest request,UploadedImageFile file)
throws IllegalStateException, IOException{
String name = RandomStringUtils.randomAlphanumeric(10);
String newFileName = name + ".jpg";
File newFile = new File(request.getServletContext().getRealPath("/image"), newFileName);
newFile.getParentFile().mkdirs();
file.getImage().transferTo(newFile);
System.out.println(request.getServletContext().getRealPath("/image"));
ModelAndView mav = new ModelAndView("showUploadedFile");
mav.addObject("imageName", newFile);
return mav;
}
}
6) page下新建showUploadFile.jsp接受图片视图
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<image src = "${imageName}}"/>
7)访问http://127.0.0.1:8080/springmvc/upload.jsp
10. 拦截器
目的:拦截器的作用是访问某个url时,被映射的控制器会在被调用前访问指定方法,调用时访问指定方法,调用结束后访问指定方法。
1)DispatcherServlet.xml中配置添加拦截器bean
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path = "/index"/> //需要拦截器的路由
<bean class = "interceptor.IndexInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
2)配置拦截器类
src/interceport包下新建拦截器类
package interceptor;
public class IndexInterceptor extends HandlerInterceptorAdapter{
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object Handler) throws Exception{
System.out.println("拦截处理器被调用");
return true;
}
public void postHandle(HttpServletRequest request,HttpServletResponse response,
Object handler, ModelAndView mav) throws Exception{
mav.addObject("date",new Date());
System.out.println("postHandle(),访问路由对应控制器后,视图访问前,添加一个时间对象到视图中,拦截处理器被调用");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object obj, Exception exp)throws Exception{
System.out.println("aftercompletion()拦截处理器被调用完后执行");
}
}
3)访问配置了拦截器的地址:http://localhost:8080/springmvc/ndex
总结:直白些,spring mvc就是将所有的请求都交给了DispatcherServlet,它来调配具体url与控制类的映射,控制类调用其他java类与方法在逻辑处理后,控制类将视图与模型数据再返回给DispatcherServlet,进行视图与数据真正组合,再返回前端渲染。欢迎留言指导!!
网友评论