一步一步上手SpringMVC

1. SpringMVC

1.1 SpringMVC的简介

SpringMVC底层就是的Servlet,SpringMVC就是对Servlet进行更深层次的封装。
  • SpringMVC是spring内置的MVC框架,使用简单,与Spring无缝集成
  • 解决WEB开发中常见的问题(参数接收、文件上传、表单验证、国际化、等等),实现页面代码和后台代码的分离。
  • 支持 RESTful风格的 URL 请求。
  • 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性。

1.2 MVC模式

MVC模式(Model-View-Controller)就是为了解决页面代码和后台代码的分离。

在这里插入图片描述

2. 入门案例-xml配置

2.1 相关jar包

Spring相关jar包

在这里插入图片描述

SpringMVC相关jar包

在这里插入图片描述

2.2 入门案例

配置文件 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,SpringMVC底层就是使用Servlet编写的
    -->
    <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.xml</param-value>
        </init-param>
        <!-- 初始化容器 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

</web-app>
配置文件 springmvc.xml
<!--
    name:给当前控制器取一个名字,相当于servlet中的资源名称,以便浏览器访问,必须以斜杠/开头
    建议使用name属性,不要使用id,因为早期版本id不支持特殊字符,如/斜杠
-->
<bean name="/hello.do" class="cn.xiaoxiao.springmvc01.controller.HelloController"></bean>
HelloController
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mv = new ModelAndView();
        mv.addObject("username", "林黛玉");
//        mv.setViewName("/WEB-INF/view/hello.jsp");
        mv.setViewName("/web_hello.jsp");
        return mv;
    }
}

3. SpringMVC全注解开发

3.1 Spring中IOC注解

注解说明
@Controller用于控制层注解
@RequestMapping(value="/method1")设置SpringMVC请求的映射路径,可以作用于类和方法上。
@RequestParam(“name”) String username用于获取传入参数的值
@PathVariable(“product_id”) Integer product_id用于定义路径参数值
@ResponseBody把响应的内容设为普通字符串
@ModelAttribute(“userKey”)跳转页面使用el表达式获取的对应的属性名称

3.2 相关的jar包

在这里插入图片描述

3.3 相关的配置

  • 通过注解方式注册控制器,配置扫描的根目录
<context:component-scan base-package="cn.xiaoxiao.springmvc"/>
  • 支持所有的mvc注解。支持json
<mvc:annotation-driven/>
  • 在核心类上添加@Controller
  • 在方法上添加@RequestMapping(“/hello”)注解

3.4 案例代码

springmvc.xml
<!--配置spring注解配置包的扫描位置-->
<context:component-scan base-package="cn.xiaoxiao.springmvc01"/>

<!--配置SpringMVC的注解驱动-->
<mvc:annotation-driven/>
AnnotationController
@RequestMapping("/method01")
public ModelAndView method1(){
    ModelAndView mv = new ModelAndView();
    mv.addObject("username","林黛玉");
    mv.setViewName("/WEB-INF/view/hello_annotation.jsp");
    return mv;
}

4. SpringMVC执行流程和原理

在这里插入图片描述

4.1 SpringMVC流程

  • 01、用户发送出请求到前端控制器DispatcherServlet。
  • 02、DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
  • 03、HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
  • 04、DispatcherServlet调用HandlerAdapter(处理器适配器)。
  • 05、HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。
  • 06、Controller执行完成返回ModelAndView对象。
  • 07、HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
  • 08、DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
  • 09、ViewReslover解析后返回具体View(视图)。
  • 10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
  • 11、DispatcherServlet响应用户。

4.2 涉及组件分析

  • 前端控制器DispatcherServlet(不需要程序员开发),由框架提供,在web.xml中配置。作用:接收请求,响应结果,相当于转发器,中央处理器。
  • 处理器映射器HandlerMapping(不需要程序员开发),由框架提供。作用:根据请求的url查找Handler(处理器/Controller),可以通过XML和注解方式来映射。
  • 处理器适配器HandlerAdapter(不需要程序员开发),由框架提供。作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。
  • 处理器Handler(也称之为Controller,需要工程师开发)。注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler。作用:接受用户请求信息,调用业务方法处理请求,也称之为后端控制器。
  • 视图解析器ViewResolver(不需要程序员开发),由框架提供。作用:进行视图解析,把逻辑视图名解析成真正的物理视图。SpringMVC框架支持多种View视图技术,包括:jstlView、freemarkerView、pdfView等。
  • 视图View(需要工程师开发)。作用:把数据展现给用户的页面。View是一个接口,实现类支持不同的View技术(jsp、freemarker、pdf等)。

6. SpringMVC请求响应和数据绑定

@Controller
@RequestMapping("/request")
public class AnnotationController {
    @RequestMapping("/method01")
    public ModelAndView method1(){
        ModelAndView mv = new ModelAndView();
        mv.addObject("username","林黛玉");
        mv.setViewName("/WEB-INF/view/hello_annotation.jsp");
        return mv;
    }

    /**
     * 一:请求响应
     * @RequestMapping 用于贴在控制器的类上或者方法上面
     * 如果是贴在控制器的类上面,那么在访问这个类的方法之前必须先加上类上的对应的名称
     * SpringMVC支持对请求的限制.如果不满足限制的条件,就不让访问执行方法.
     * 主要的限制有两种:(method)方法限制,参数限制
     */
    @RequestMapping("/method02")
    public ModelAndView method02() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("username","贾宝玉");
        mv.setViewName("/WEB-INF/view/hello_annotation.jsp");
        return mv;
    }


    /**
     *  方法限制
     * 就是设置请求的method类型.如果发送过来的请求与方法设置的method不一样,就不能访问执行方法.
     * 请求method : GET , POST
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ModelAndView login() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("username","林黛玉");
        mv.setViewName("/WEB-INF/view/hello_annotation.jsp");
        return mv;
    }

    /**
     * 参数限制:
     * 请求里面必须包括哪些参数,或不包括哪些哪些.
     * 1.参数必须包括:params={"username","password"}
     * 2.参数不能包括:params={"!userid"}
     * 3.参数值必须是指定的值:params={"username=xiaoxiao"})
     * 4.参数值必须不是指定的值:params={"userid!=123"})
     */
    @RequestMapping(value = "/login02", params = {"username","password"})
    public String login02() {
        System.out.println("登录");
        return "/index.jsp";
    }

    /**
     * Spring方法参数可以注入的类型
     * SpringMVC的方法默认可以注入 JavaWeb开发常用的数据共享对象
     * HttpServletRequest、HttpServletResponse、HttpSession
     * 获取这些共享对象以后,就可以向之前的Servlet一样,做任何数据共享以及页面跳转操作
     */
    @RequestMapping("/method03")
    public void method03 (HttpServletRequest request, HttpServletResponse response, HttpSession session){
        try {         request.getRequestDispatcher("/WEB-INF/view/reqandresp.jsp").forward(request,response);
        } catch (ServletException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 二:数据绑定
     * 
     * 数据绑定:传统方法
     */
    @RequestMapping("/method04" )
    public void method04 (HttpServletRequest request, HttpServletResponse response, HttpSession sessio){
        //传统方法
        String username = request.getParameter("username");
        System.out.println(username);
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        for(Map.Entry<String, String[]> entry : entries){
            System.out.println(entry.getKey() + "=>" + entry.getValue());
        }
    }
    /**
     * 数据绑定:spirng
     * 1. 方法形参与前台参数同名
     */
    @RequestMapping("/method05")
    public ModelAndView method05 (String username, String password){
        System.out.println(username);
        System.out.println(password);
        return null;
    }

    /**
     * 数据绑定:spirng
     * 2. 方法形参与前台参数不同名
     */
    @RequestMapping("/method06")
    public ModelAndView method06 (@RequestParam("name") String username, String password){
        System.out.println(username);
        System.out.println(password);
        return null;
    }

    /**
     * 数据绑定:spirng
     * 3. 接受数组
     */
    @RequestMapping("/method07")
    public ModelAndView method07 (String[] hobbys){
        System.out.println(Arrays.toString(hobbys));
        return null;
    }

    /**
     * 数据绑定:spirng
     * 4. 对象传参
     */
    @RequestMapping("/method08")
    public ModelAndView method08 (User user){
        System.out.println(user);
        return null;
    }

    /**
     * 数据绑定:spirng
     * 5. 接受参数封装成map集合
     */
    @RequestMapping("/method09")
    public ModelAndView method09 (@RequestParam Map<String, Object> map){
        System.out.println("map:" + map);
        return null;
    }
}

7. RESTful风格

7.1 RESTful风格介绍

  • ** REST(英文:Representational State Transfer,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。**
  • ** RESTful一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。**

7.2 参数传递方法GET

例如:根据商品id查询对应的商品信息(京东网站)。如果按照我们web开发应该是将商品id通过get方法跟在地址后面。
  • 普通方式 https://item.jd.com?product_id=100000287117 大型电商网站不支持
  • 大型电商网站使用的 RESTFUL风格 。RESTful风格 : https://item.jd.com/100000287117.html

7.3 案例代码

Controller类
// RESTful风格
@RequestMapping(value = "/method7/{product_id}")
public ModelAndView method7(@PathVariable("product_id") Integer product_id) {
	System.out.println(product_id);//1231323123
	return null;
}
浏览器访问地址
localhost:8080/springmvc/request/method7/1231323123.html

7.4 使用RESTful优势

可以让页面伪静态
页面访问感觉像在访问静态html页面,实际上访问时动态页面(伪静态)。
假装是静态页面,实际只是ResultFul风格的动态页面。
方便搜索引擎的SEO优化
SEO :通过技术手段对公司网站的访问地址进行优化
比如用户搜索某一个关键字,尽量排名到第一页
产品地址
  • 传统方式 : xxx?id=12312313。不利于搜索引擎收录,优化
  • RestFul风格: xxx/2312313.html。方便搜索引擎收录,优化

8. 请求中文乱码

** SpringMVC默认接受的参数是ISO-8859-1编码参数,单字节,不支持中文,Spring提供了一个过滤器可以让开发者自定义请求参数的字符编码。注意:此种方式只对post提交方式有效 **

	<!-- 统一配置SpringMVC接受请求参数的编码 -->
	<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>

** 从Tomcat8开始,默认就已经支持get方式提交中文参数.Tomcat7以及以下版本需要配置才支持中文参数。配置 tomcat/conf/server.xml 添加 URIEncoding=“UTF-8”。 **

 <Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

9. 响应传值方式

9.1 Web开发主要表现为请求和响应

  • 响应包括两方面:页面跳转、数据共享
  • 页面跳转两种方式:请求转发、重定向

9.2 案例

@Controller
@RequestMapping("/request")
public class AnnotationController {
    /**
     * 三:响应传值方式
     * 1.返回void类型和共享数据:需要共享数据,页面跳转
     */
    @RequestMapping("/method10")
    public void method10(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //共享数据
        request.setAttribute("username","林黛玉");
        //跳转页面到jsp页面显示数据,必须使用请求转发
        request.getRequestDispatcher("/response/response").forward(request, response);
    }

    /**
     * 2.返回ModelAndView类型和共享数据
     *   ModeaAndVied模型和视图
     *   Spring提供此对象可以集中管理共享数据操作和设置跳转视图的操作
     *   ModelAndView只能使用请求转发
     */
    @RequestMapping("/method11")
    public ModelAndView method11() {
        ModelAndView mv = new ModelAndView();

        //共享数据,等价于request对象共享数据的级别
        //addObject(attributeName, attributeValue)
        mv.addObject("username", "贾宝玉");

        //页面跳转,等价于request对象的请求转发
        //setViewName(viewName);
        mv.setViewName("/response/response");
        return mv;
    }
    
}

10. 文件上传

** 在web开发中一般会有文件上传的操作。一般JavaWeb开发中文件上传使用的 Apache组织的Commons FileUpload组件SpringMVC中使用 MultipartFile file对象接受上传文件,必须保证 后台参数的名称和表单提交的文件的名称一致。**

文件上传必须条件:表单必须post、表单必须有 file 文件域表单的 enctype=“multipart/form-data”。

10.1 添加相关jar包

在这里插入图片描述

10.2 准备jsp页面

<fieldset>
		<legend>单个文件上传</legend>
		<form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data">
			姓名: <input name="username"><br>
			头像: <input type="file" name="headImg"><br>
			<button type="submit">提交</button>
		</form>
	</fieldset>

10.3 后台代码

SpringMVC中使用 MultipartFile file对象接受上传文件,必须保证 后台方法MultipartFile 参数的名称和表单提交的文件的名称一致。
//SpringMVC中使用  MultipartFile file对象接受上传文件,必须保证 后台参数的名称和表单提交的文件的名称一致
	@RequestMapping("/upload")
	public String singleUpload(MultipartFile headImg,@RequestParam("username")String username) throws IOException {	
		System.out.println(headImg.getName());//获取上传文件的表单名称 
		System.out.println(headImg.getContentType());//MIME类型
		System.out.println(headImg.getSize());//文件大小
		System.out.println(headImg.getOriginalFilename());//获取上传文件的完整名称
		//获取上传文件对应的输入流
		//InputStream in = headImg.getInputStream();
		
		//创建一个磁盘目录用于保存文件
		File destFile= new File("c:/upload");
		if(!destFile.exists()) {
			destFile.mkdir();
		}
		//使用uuid作为文件随机名称
		String fileName = UUID.randomUUID().toString().replaceAll("-", "");
		//使用FileNameUtils获取上传文件名的后缀
		String extension = FilenameUtils.getExtension(headImg.getOriginalFilename());// jpg , png 等等
		//创建新的文件名称
		String newFileName = fileName + "."+extension;
		
		//创建要保存文件的File对象
		File file = new File(destFile, newFileName);
		//保存文件到本地磁盘
		headImg.transferTo(file);
		return "redirect:/upload.jsp";
	}

10.4 配置文件上传的解析器

** 配置文件上传解析器:bean的名字是固定的。使用spring表达式 #{1024*1024} **

<!-- 配置文件上传解析器:bean的名字是固定的,底层使用的名称注入 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<!-- 设置上传文件的最大尺寸为1MB -->
	<property name="maxUploadSize" value="#{1024 * 1024}"></property>
</bean>

10.5 多文件上传

页面
<fieldset>
		<legend>多个文件上传</legend>
		<form action="${pageContext.request.contextPath}/uploads.do" method="post" enctype="multipart/form-data">
			文件1: <input type="file" name="headImgs"><br>
			文件2: <input type="file" name="headImgs"><br>
			文件3: <input type="file" name="headImgs"><br>
			<button type="submit">提交</button>
		</form>
	</fieldset>
后台
@RequestMapping("/uploads")
	public String singleUploads(MultipartFile[] headImgs) throws IOException {
		

		//创建一个磁盘目录用于保存文件
		File destFile= new File("c:/upload");
		if(!destFile.exists()) {
			destFile.mkdir();
		}
		for (int i = 0; i < headImgs.length; i++) {
			MultipartFile headImg = headImgs[i];
			
			//使用uuid作为文件随机名称
			String fileName = UUID.randomUUID().toString().replaceAll("-", "");
			//使用FileNameUtils获取上传文件名的后缀
			String extension = FilenameUtils.getExtension(headImg.getOriginalFilename());// jpg , png 等等
			//创建新的文件名称
			String newFileName = fileName + "."+extension;
			
			//创建要保存文件的File对象
			File file = new File(destFile, newFileName);
			//保存文件到本地磁盘
			try {
				headImg.transferTo(file);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return "redirect:/upload.jsp";
	}

11. 文件下载

** 文件下载,SpringMVC并没有做过多的封装,还是使用原来的下载方式。JavaWeb 开发中使用 ServletOutStream 向浏览器响应数据(输出流输出数据),就是下载文件。**

package cn.zj.springmvc.controller;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class DownloadController {
	
	/*
	 * 下载思路
	 * 
	 * 1,下载前,判断是否登录,是否VIP,是否积分,是否充值
	 * 2,根据下载的资源名称,去服务器磁盘找到对应的文件形成输入流,读取到内存
	 * 3,使用HttpServletResponse的输出流,将输入流 输出到浏览器(下载)
	 * 
	 */
	
	@SuppressWarnings("resource")
	@RequestMapping("/download")
	public void download(HttpServletRequest request, HttpServletResponse response,String fileName) throws Exception {
		System.out.println(fileName);
		//TODO 代办任务 1,下载前,判断是否登录,是否VIP,是否积分,是否充值
			
		//2,根据下载的资源名称,去服务器磁盘找到对应的文件形成输入流,读取到内存
		InputStream inputStream = new FileInputStream("c:/download/"+fileName);
			
		//3.获取输出流
		ServletOutputStream outputStream = response.getOutputStream();	
		/*
		 * 浏览器主要两类 
		 * 
		 * 不同浏览器类型下载文件名称编码不一样
		 * 
		 * 1,W3C 标准浏览器(谷歌,火狐)
		 * 		使用的ISO-8859-1编码
		 * 2,IE
		 * 		UTF-8 编码
		 * 如何判断W3C还是IE类型浏览器
		 * 获取请求头User-Agent ,这个字符串中是否有 MSIE
		 */
		
		//获取请求头
		String userAgent = request.getHeader("User-Agent");
		System.out.println("userAgent :"+userAgent);
		
		//W3C标准浏览器
		if(!userAgent.contains("MSIE")) {
		
			//先将UTF-8的字符串转换成 字节数组
			byte[] bytes = fileName.getBytes("UTF-8");
			
			
			//再讲字节数组转换成ISO-8859-1 编码的字符串
			fileName = new String(bytes, "ISO-8859-1");
			
		}
				
		//4.响应的内容应该是以附件的形式响应给浏览器(设置响应头)
		response.setHeader("Content-Disposition", "attachment;filename="+fileName);
		
		/*
		 * 使用Apache commons-io 工具包中 IOUtils工具
		 */
		//5.响应数据给浏览器(下载)
		IOUtils.copy(inputStream, outputStream);
		
	}
}

12. SpringMVC的拦截器

12.1 拦截器介绍

拦截器 : Interceptor,Spring MVC 的拦截器类似于Servlet 开发中的过滤器Filter,用于对Controller进行预处理和后处理。
使用SpringMVC拦截器步骤:
  • 定义拦截器类,实现接口 org.springframework.web.servlet.HandlerInterceptor。拦截器相对Servlet开发中Filter过滤器,开发者可以在配置文件配置拦截规则,哪些方法拦截,哪些不拦截。
  • 在applicationContext.xml中配置拦截器
拦截器方法的执行时机:
  • preHandle:控制器方法执行之前执行,返回结果为true表示放行,如果返回为false,表示拦截(可以做权限拦截,登录检查拦截)。
  • postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息)。
  • afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等)。

12.2 自定义拦截器

public class CheckLoginInterceptor implements HandlerInterceptor {
	//1):preHandle:控制器方法执行之前执行,返回结果为true表示放行,如果返回为false,表示拦截(可以做权限拦截,登录检查拦截).
	// true : 放行  false :不放行
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {	
		System.out.println("拦截器执行了......");
		//从Session中获取登录信息
		String username = (String)request.getSession().getAttribute("username");
		System.out.println(username);
		
		if(username !=null) {
			//放行
			return true;
		}else {
			//跳转到登录页面去
			response.sendRedirect(request.getContextPath()+"/login.jsp");
			return false;
		}
	}
	
	//postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应息).
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	}
	
	//afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
	}
}

12.3 拦截器的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	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
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd ">
		<!-- 配置springmvc的注解驱动 -->
		<mvc:annotation-driven/>	
		<!-- 配置拦截器 :可以有多个拦截器-->
		<mvc:interceptors>
			<!--配置检查登录拦截器  -->
			<mvc:interceptor>	
				<!-- 配置拦截的规则
				    只会拦截 控制器请求,不会拦截jsp页面
					/*  
						只能拦截一级 如 : /list.do /delete.do
						如:/user/list.do , /user/delete.do 二级 不能拦截
					/** 
						可以拦截多级 无论几级都可以 如  /a/b/c/d/list.do
				 -->
				<mvc:mapping path="/**"/>				
				<!-- 排除拦截的地址,多个地址使用逗号隔开
					/user/login.do			
				 -->
				<mvc:exclude-mapping path="/user/login.do"/>		
				<!-- 拦截器的类型 -->
				<bean class="cn.zj.ssm.interceptor.CheckLoginInterceptor"/>
			</mvc:interceptor>
		</mvc:interceptors>	
</beans>

13. SpringMVC控制器Controller的生命周期

SpringMVC对象 Controller的对象的创建有两种情况。Spring 容器创建的对象默认都是单例对象。
  • Request : 在用户的一次请求中生效(用户每次请求都会创建Controller对象)多例
  • Session : Controller对象在一次会话中创建一个对象
如果控制器中有成员变量 设置或者赋值操作,必须使用 request 返回:

在这里插入图片描述

Web表现层控制器到底使用单例singleton还是request,还是session?
  • 首先看控制器有没有成员变量要并发修改,如果有,必须使用request/prototype。
  • 早期的Struts2框架使用的就是成员变量接受请求参数,对应的控制器对象必须是多例。
  • SpringMVC接受请求参数,作为方法形式参数,每次请求都会重新为没参数开辟新的内存存储这个参数,不会产生线程安全问题,所以SpringMVC使用默认的单例即可。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值