Java高级框架——SpringMVC

      北京尚学堂——基于此教育机构的视频所学习

目录

壹、SpringMVC简介

一、SpringMVC环境搭建

二、字符编码过滤器

三、传参

四、跳转方式

五、视图解析器

六、ResponseBody

七、九大内置对象和四大作用域

1、九大内置对象

2、四大作用域

3、SpringMVC作用域传值的几种方式

八、文件的上传和下载

①文件的下载

②文件上传

九、自定义拦截器

①拦截器栈

十、SpringMVC的运行原理(文字解释)

能力提升,菜单

文件的上传下载


壹、SpringMVC简介

1、SpringMVC中重要组件

  • DispatcherServlet: 前端控制器,接收所有请求(如果配置/不包含 jsp)
  • HandlerMapping: 解析请求格式的.判断希望要执行哪个具体的方法
  • HandlerAdapter: 负责调用具体的方法
  • ViewResovler:视图解析器.解析结果,准备跳转到具体的物理视图

2、关于SpringMVC的运行原理图

3、Spring容器和SpringMVC容器的关系

Spring容器和SpringMVC容器是父子容器

            SpringMVC 容器中能够调用 Spring 容器的所有内容

一、SpringMVC环境搭建

  1. 导入jar包
  2. 在 web.xml 中配置前端控制器 DispatcherServlet
    1.  如 果 不 配 置 <init-param> 会 在/WEB-INF/<servlet-name>-servlet.xml
    2.   <!-- 配置前端的控制器 -->
        <servlet>
        	<servlet-name>tk</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>tk</servlet-name>
        	<url-pattern>/</url-pattern>
        </servlet-mapping>
        
  3. 在src下新建springmvc.xml文件
    1. 导入xmlns:mvc  命名
    2. <?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
          http://www.springframework.org/schema/context/spring-context.xsd
          http://www.springframework.org/schema/mvc
          http://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
          <!-- 扫描注解 -->
          <context:component-scan base-package="com.tk.controller"></context:component-scan>
          <!-- 注解驱动 -->
          <!--org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandler Mapping --> 
          <!--org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerA dapter --> 
          <mvc:annotation-driven></mvc:annotation-driven>
          
          <!-- 静态资源 -->
          <!-- 一个*表示当前文件这一层的文件,而俩个星是当前目录下的所有文件 -->
          <mvc:resources location="/js/" mapping="/js/**"></mvc:resources>
          <mvc:resources location="/css/" mapping="/css/**"></mvc:resources>
          <mvc:resources location="/image/" mapping="/image/**"></mvc:resources>
          
       </beans>

二、字符编码过滤器

在web.xml里面配置Filter

  <!-- 配置字符编码过滤器 -->
  <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>

三、传参

  1. 把内容写到方法(HandlerMethod)参数中,SpringMVC 只要有这个内容,注入内容
  2. 基本数据类型参数
    1. 默认保证参数名称和请求中传递的参数名相同
    2. 	@RequestMapping("demo1")
      	public String demo1(String name,String password,HttpServletRequest req){
      		System.out.println(name+"---------"+password);
      		System.out.println("执行demo1");
      		if(name.equals("张三")&&password.equals("123456"))
      			return "mian.jsp";
      		else{
      			req.setAttribute("error", "账号密码错误");
      			return "index.jsp";
      		}
      	}
      	
    3. 如果请求参数名和方法参数名不对应使用@RequestParam()赋值

      1. 	
        	@RequestMapping("demo3")
        	public String demo1(@RequestParam("name1")String name,@RequestParam("password1")String password,HttpServletRequest req){
        		System.out.println(name+"---------"+password);
        		System.out.println("执行demo1");
        		if(name.equals("张三")&&password.equals("123456"))
        			return "mian.jsp";
        		else{
        			req.setAttribute("error", "账号密码错误");
        			return "index.jsp";
        		}
        	}
    4. 如果方法参数是基本数据类型(不是封装类)可以通过@RequestParam 设置默认值.

      1. 防止没有参数时 500

      2. 	@RequestMapping("demo2")
        	public String demo2(@RequestParam(defaultValue="11")String name){
        		System.out.println("执行demo2"+ name);
        		return "index.jsp";
        	}
    5. 如果强制要求必须有某个参数

      1. 	@RequestMapping("demo2")
        	public String demo2(@RequestParam(required=true)String name){
        		System.out.println("执行demo2"+ name);
        		return "index.jsp";
        	}
  3. HandlerMethod 中参数是对象类型

    1. 请求参数名和对象中属性名对应(get/set 方法)

    2. 	@RequestMapping("demo1")
      	public String demo1(User u,HttpServletRequest req){
      		System.out.println(u.getName()+"---------"+u.getPassword());
      		System.out.println("执行demo1");
      		if(u.getName().equals("张三")&&u.getPassword().equals("123456"))
      			return "mian.jsp";
      		else{
      			req.setAttribute("error", "账号密码错误");
      			return "index.jsp";
      		}
      	}
  4. 请求参数中包含多个同名参数的获取方式
    1. 复选框传递的参数就是多个同名参数
    2. 	@RequestMapping("demo4")
      	public String demo4(String name,String password,@RequestParam("hobby")List<String> hobby){
      		System.out.println("执行demo2"+ name  +"     "+password+"     "+hobby);
      		return "index.jsp";
      	}
  5. 请求参数中对象.属性格式

    1. jsp 中代码

      1. <input type="text" name="peo.name"/>
         <input type="text" name="peo.age"/>
        
    2. 新建一个类

      1. 对象名和参数中点前面名称对应

        1. public class Demo {
               private People peo;
          
    3. 控制器

      1. @RequestMapping("demo6")
        public String demo6(Demo demo){ 
            System.out.println(demo); 
            return "main.jsp"; 
        }
        
  6. 在请求参数中传递集合对象类型参数

    1. JSP中的代码
      1. <input type="text" name="peo[0].name"/>
        <input type="text" name="peo[0].age"/> 
        <input type="text" name="peo[1].name"/> 
        <input type="text" name="peo[1].age"/>
    2. 新建类
      1. public class Demo {
            private List<People> peo;
        
    3. 控制器
      1. @RequestMapping("demo6") 
        public String demo6(Demo demo){ 
            System.out.println(demo); 
            return "main.jsp"; 
        }
        
  7. restful传值方式

    1. 简化 jsp 中参数编写格式

    2. 在 jsp 中设定特定的格式

      1. <a href="demo5/田坤/123456">跳转</a>
    3. 在控制器中

      1. @RequestMapping 中一定要和请求格式对应

      2. {名称} 中名称自定义名称
      3.  @PathVariable 获取@RequestMapping 中内容,默认按照方法参数名称去寻找.

      4. @RequestMapping("demo5/{name}/{pwd}")
        public String demo5(@PathVariable String name,@PathVariable("pwd")String password){
        	System.out.println("执行demo2"+ name  +"     "+password);
        	return "/index.jsp";
        }

四、跳转方式

  1. 默认跳转方式请求转发
  2. 设置返回值字符串内容
    1. 添加 redirect:资源路径 重定向
    2. 添加 forward:资源路径 或省略 forward: 转发

五、视图解析器

  1. SpringMVC 会提供默认视图解析器.
  2. 程序员自定义视图解析器(springmvc.xml)
    1.     
          <!-- 视图解析器 -->
          <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          	<!-- 给前面加东西 -->
          	<property name="prefix" value="/"></property>
          	<!-- 给后面加东西 -->
          	<property name="suffix" value=".jsp"></property>
          </bean>
          
  3.  如果希望不执行自定义视图解析器,在方法返回值前面添加forward:或 redirect

六、ResponseBody

需要导入jackson所需要的包

  1.  在方法上只有@RequestMapping 时,无论方法返回值是什么认为需要跳转
  2. 在方法上添加@ResponseBody(恒不跳转)
    1. 如果返回值满足 key-value 形式(对象或 map)
      1. 把响应头设置为 application/json;charset=utf-8
      2. 把转换后的内容输出流的形式响应给客户端
    2. 如果返回值不满足 key-value,例如返回值为 String
      1. 把相应头设置为 text/html
      2. 把方法返回值以流的形式直接输出.
      3. 如果返回值包含中文,出现中文乱码
        1. produces 表示响应头中 Content-Type 取值
    3. @RequestMapping(value="demo12",produces="text/html; charset=utf-8")
      @ResponseBody 
      public String demo12(){ 
          return "中文";
      }
    4. @RequestMapping("demo6")
      @ResponseBody
      public User demo6(){
      	User u = new User();
      	u.setName("宋旭东");
      	u.setPassword("123456");
      	return u;
      }
  3. 底层使用Jackson进行json转换,在项目中一定要导入jackson的jar
    1. spring4.1.6 对 jackson 不支持较高版本,jackson2.7 无效.

七、九大内置对象和四大作用域

1、九大内置对象

名称 类型 含义 获取方式
request HttpSerletRequest 封装所有请求信息 方法参数
response HttpServletResponse 封装所有响应信息 方法参数
session HttpSession 封装所有会话信息 request.getSession
application ServletContext 所有信息

getServletContext()

request.getServletContext()

out PrintWriter 输出对象 response.getWriter()
exception Exception 异常对象  
page Object 当前页面对象  
pageContext pageContext 获取其他对象  
config ServletConfig 配置信息  


 

2、四大作用域

  1. page
    1. 在当前页面不会重新实例化.
  2. request
    1. 在一次请求中同一个对象,下次请求重新实例化一个
  3. session
    1. 一次会话
    2. 只要客户端Cookie中传递的Jsessionid不变,Session不会重新实力会(不超过默认时间.)
    3. 实际有效时间
      1. 浏览器关闭.Cookie 失效

      2. 默认时间.在时间范围内无任何交互.在 tomcat 的web.xml 中配置

        1. <session-config> 
              <session-timeout>30</session-timeout> 
          </session-config>
    4. application

      1. 只有在 tomcat 启动项目时菜实例化.关闭 tomcat 时销毁application

3、SpringMVC作用域传值的几种方式

  1. 使用原生 Servlet
    1. 在 HanlderMethod 参数中添加作用域对象
    2. @RequestMapping("demo1") 
      public String demo1(HttpServletRequest abc,HttpSession sessionParam){
          //request 作用域 
          abc.setAttribute("req", "req 的值"); 
          //session 作用域 
          HttpSession session = abc.getSession();
          session.setAttribute("session", "session 的值"); 
          sessionParam.setAttribute("sessionParam","sessionParam 的值"); 
          //appliaction 作用域 
          ServletContext application = abc.getServletContext();                       
          application.setAttribute("application","application 的值"); 
          return "/index.jsp"; 
      }
      
  2. 使用 Map 集合
    1. 把 map 中内容放在 request 作用域
    2. spring 会对 map 集合通过 BindingAwareModelMap 进行实例化
    3. @RequestMapping("demo2") 
      public String demo2(Map<String,Object> map){ 
          System.out.println(map.getClass());
          map.put("map","map 的值"); 
          return "/index.jsp";
      }
      
  3. 使用 SpringMVC 中 Model 接口
    1. 把内容最终放入到 request 作用域中
    2. @RequestMapping("demo3") 
      public String demo3(Model model){
          model.addAttribute("model", "model 的值"); 
          return "/index.jsp";
      }
      
  4. 使用 SpringMVC 中 ModelAndView 类
    1. @RequestMapping("demo4")
      public ModelAndView demo4(){
          //参数,跳转视图 
          ModelAndView mav = new ModelAndView("/index.jsp");
          mav.addObject("mav", "mav 的值"); 
          return mav;
      }
      

八、文件的上传和下载

①文件的下载

  1. 访问资源时相应头如果没有设置 Content-Disposition,浏览器默认按照 inline 值进行处理
    1. inline 能显示就显示,不能显示就下载.
  2. 只需要修改相应头中 Context-Disposition=”attachment;filename=文件名”
    1. attachment 下载,以附件形式下载
    2. filename=值就是下载时显示的下载文件名
  3. 实现步骤
    1. 导入 apatch 的两个 jar
    2. 在 jsp 中添加超链接,设置要下载文件
      1. 在 springmvc 中放行静态资源 files 文件夹
        1. <a href="download?fileName=jquery.chm">下载</a>
          
      2. 编写控制器方法

        1. @RequestMapping("demo")
          private void download(String fileName,HttpServletRequest req,HttpServletResponse resp) throws IOException {
          	
          	//设置响应流中文件进行下载
          	resp.setHeader("Content-Disposition", "attachment;filename="+fileName);
          	//   resp.getWriter().wait();  文本流
          	//把二进制流放入到响应中
          	ServletOutputStream os = resp.getOutputStream();
          	FILE_PATH = req.getServletContext().getRealPath("files");
          	System.out.println(FILE_PATH);
          	File file = new File(FILE_PATH, fileName);
          	byte[] bytes = FileUtils.readFileToByteArray(file);
          	os.write(bytes);
          	os.flush();
          	os.close();
          }

②文件上传

  1. 基于 apache 的 commons-fileupload.jar 完成文件上传
  2. MultipartResovler 作用
    1. 把客户端上传的文件流转换成 MutipartFile 封装类
    2. 通过 MutipartFile 封装类获取到文件流
  3. 表单数据类型分类
    1. 在<form>的 enctype 属性控制表单类型
    2. 默认值 application/x-www-form-urlencoded,普通表单数据.(少量文字信息)
    3. text/plain 大文字量时使用的类型.邮件,论文
    4. multipart/form-data 表单中包含二进制文件内容
  4. 实现步骤:
    1. 导入 springmvc 包和 apache 文件上传 commons-fileupload commons-io 两个 jar
    2. 编写 JSP 页面
      1. <form action="upload" method="post" enctype="multipart/form-data">
            <input type="file"  name="file"><br>
            <input type="submit" value="提交">
        </form>
    3. 配置springmvc.xml

      1.  <!-- MutipartResovler的解析器 -->
            <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            	<!-- 上传文件的最大  单位字节 -->
            	<property name="maxUploadSize" value="500"></property>
            </bean>
            
            <!-- 异常解析类 -->
            <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
            	<property name="exceptionMappings">
            		<props>
            			<!-- 文件如果超过指定大小报异常,  让其跳转到error.jsp页面里 -->
            			<prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">/error.jsp</prop>
            		</props>
            	</property>
            </bean>
    4. 编写控制器类

      1. MultipartFile 对象名必须和<inputtype=”file”/>的 name 属性值相同

      2. 	@RequestMapping("upload")
        	public String upload(MultipartFile file,String name) throws IOException{
        		String filename = file.getOriginalFilename();
        		//获取后缀名
        		String suffix = filename.substring(filename.lastIndexOf("."));
        		//随机产生一个字符串
        		String uuid = UUID.randomUUID().toString();
        		FileUtils.copyInputStreamToFile(file.getInputStream(), new File("C:/aaa/other/"+uuid+suffix));
        		return "/mian.jsp";
        	}

九、自定义拦截器

  1. 跟过滤器比较像的技术
  2. 发送请求时被拦截器拦截,在控制器的前后添加额外功能
    1. 拦截器,请求的拦截.针对点是控制器方法.(对 Controller)
    2. AOP 区分开.AOP 在特定方法前后扩充(对 ServiceImpl)
  3. SpringMVC 拦截器和 Filter 的区别
    1. 拦截器只能拦截器 Controller
    2. Filter 可以拦截任何请求.
  4. 实现自定义拦截器的步骤
    1. 新建类实现 HandlerInterceptor
      1. package com.tk.intercerpter;
        
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        
        import org.springframework.web.servlet.HandlerInterceptor;
        import org.springframework.web.servlet.ModelAndView;
        
        /**
         * 自定义拦截器
         * @data :2019-4-17上午9:43:07
         * @author :田坤
         */
        public class MyIntercerpter implements HandlerInterceptor{
        
        	//jsp 执行完成后执行
        	//记录执行过程中出现的异常.
        	//可以把异常记录到日志中 
        	@Override
        	public void afterCompletion(HttpServletRequest arg0,
        			HttpServletResponse arg1, Object arg2, Exception arg3)
        			throws Exception {
        		// TODO Auto-generated method stub
        		
        	}
        
        	//控制器执行完成,进入到 jsp 之前执行.
        	//日志记录. 
        	//敏感词语过滤 
        	@Override
        	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
        			Object arg2, ModelAndView arg3) throws Exception {
        		System.out.println("往"+arg3.getViewName()+"跳转");
        		System.out.println("model 的值 "+arg3.getModel().get("model")); 
        		//敏感词过滤
        		String word = arg3.getModel().get("model").toString();
        		String newWord = word.replaceAll("祖国", "**"); 
        		arg3.getModel().put("model", newWord);
        		
        	}
        
        	//在进入控制器之前执行
        	//如果返回值为 false,阻止进入控制器
        	//控制代码 
        	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
        			Object arg2) throws Exception {
        		return true;
        	}
        
        }
        
    2. 在 springmvc.xml 配置拦截器需要拦截哪些控制器

      1. 	<!-- 配置拦截器 -->
        	<mvc:interceptors>
        		<!-- 拦截全部的控制器 -->
        		<bean class="com.tk.intercerpter.MyIntercerpter"></bean>
        		<!-- 拦截特定地址的控制器 -->
        		<mvc:interceptor>
        			<mvc:mapping path="/demo"/>
        			<bean class="com.tk.intercerpter.MyIntercerpter"></bean>
        		</mvc:interceptor>
        	</mvc:interceptors>

①拦截器栈

  1. 多个拦截器同时生效时,组成了拦截器栈
  2. 顺序:先进后出
  3. 执行顺序和在 springmvc.xml 中配置顺序有关
  4. 设置先配置拦截器 A 在配置拦截器 B 执行顺序为
    preHandle(A)--> preHandle(B)--> 控制器方法 -->postHandle(B)
    -->postHanle(A)-->JSP-->afterCompletion(B)-->afterCompletion(A)

十、SpringMVC的运行原理(文字解释)

如果在 web.xml 中设置 DispatcherServlet 的<url-pattern>为 / 时,当用户发 起 请 求 , 请 求 一 个 控 制 器 , 首 先 会 执 行DispatcherServlet. 由DispatcherServlet 调 用 HandlerMapping 的DefaultAnnotationHandlerMapping 解 析 URL, 解 析 后 调 用HandlerAdatper 组 件 的 AnnotationMethodHandlerAdapter 调 用Controller 中的 HandlerMethod.当 HandlerMethod 执行完成后会返回View,会被 ViewResovler 进行视图解析,解析后调用 jsp 对应的.class 文件并运行,最终把运行.class 文件的结果响应给客户端.
以上就是 springmvc 运行原理(给面试官说的)

 

能力提升,菜单

文件的上传下载

猜你喜欢

转载自blog.csdn.net/qq_41965731/article/details/89302234