三大框架底层源码超详细总结 (二)SpringMVC (面试必备)

          三大框架底层源码超详细总结 (二)SpringMVC  (面试必备)


目录

          三大框架底层源码超详细总结 (二)SpringMVC  (面试必备)

SpringMVC介绍

springmvc优势

一、什么是MVC框架

二、SpringMVC执行流程 

1.服务器启动的时候做了什么

2.服务器启动完之后做了什么

3原理图

4.SpringMVC常用注解

5.SpringMVC主要组件

6.接收数据(前端)

6.1 通过设置String userName,String userPassword 传值的方式

6.2通过注解方式@RequestParam               

6.3通过JaveBean对象

6.4通过超链接传输方式 aaa

7.返回数据(客户端)

7.1通过用ModelAndView 把数据存储给Model,把view 存储给View(只能给浏览器)

7.2通过String代替View+Model参数位置任意 ,用来存储Model的数据

7.3通过String代替View+modelMap代表的是Model

7.4通过String代替View+Map代表的是Model

7.5借助jackson把java对象转换json字符串,并响应给客户端(可跨平台)

7.6程序员先把users对象转换json字符串 用response对象把json字符串响应给客户端(可跨平台)

小总结:

8过滤器和拦截器的区别

9.springmvc与struts2本质不同

10支持的数据类型


SpringMVC介绍

         首先简单介绍什么是MVC架构  三大框架很好的解释MVC架构的用法,传统的MVC模式(Model-view-controller)是软件工程中的一种软件架构,即把软件系统分为了三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

控制器(Controller) - 负责转发请求,对请求进行处理。
视图(View) - 界面设计人员进行图形界面设计。
模型(Model) -程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。
传统的MVC框架还是存在着一定的耦合性,比如模型层夹杂着业务层和数据库的访问,所以SpringMVC把传统的模型层拆分为了业务层(Service)和数据访问层(DAO,Data Access Object)。在Service下可以通过Spring的声明式事务操作数据访问层,而在业务层上还允许我们访问NoSQL,这样能满足现代互联网系统的性能。Spring MVC其最大的特点就是结构松散,耦合度较低,对各个模块进行了分离,使得各个层负责各个层的逻辑,开发起来更加清晰。

springmvc优势


1、清晰的角色划分:前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器(Controller)、验证器( Validator)、命令对象(Command 请求参数绑定到的对象就叫命令对象)、表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。 
2、分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要; 
3、由于命令对象就是一个POJO,无需继承框架特定API,可以使用命令对象直接作为业务对象; 
4、和Spring 其他框架无缝集成,是其它Web框架所不具备的; 
5、可适配,通过HandlerAdapter可以支持任意的类作为处理器; 
6、可定制性,HandlerMapping、ViewResolver等能够非常简单的定制; 
7、功能强大的数据验证、格式化、绑定机制; 
8、利用Spring提供的Mock对象能够非常简单的进行Web层单元测试; 
9、本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。 
10、强大的JSP标签库,使JSP编写更容易。 
还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配置支持等等。

 

一、什么是MVC框架

       Spring Web MVC是spring提供给Web应用的框架设计。实际上MVC框架是一个设计理念,它不仅存在于Java世界中,它的流程是各个组件的应用和改造SpringMVC的根本。所以要了解SpringMVC,首先是要了解SringMVC的流程和各个组件。

二、SpringMVC执行流程 

heihei

https://blog.csdn.net/LiuY521/article/details/90048542      我在之前博客里面有介绍  面试会问

1.服务器启动的时候做了什么


1.Tomcat启动的时候会自我检查,会自动读取本身的Web.xml文件,加载里面配置的信息,开启服务,开启引擎

2.开启引擎,并逐一扫描每一个Web项目的xml文件,并为其配置有且只有一个ServletContext

3.监听器读取Spring的配置文件,并初始化Spring容器
4.过滤器生命周期开始
5.DispatcherServlet(前端控制器)生命周期开始,<load-on-startup>1</load-on-startup>用init方法读取加载spring_mvc.xml的清单文件,实例化controller对象       内部资源试图解析器的对象,handlerMapping中的map集合中的一堆的url映射    和映射的方法       
6.tocmat启动完毕

 

2.服务器启动完之后做了什么


7.客户端发送请求,根据后缀,被DispatcherServlet拦截,进入其service方法      
8.service方法截取请求url的字符串获取有效的url,      
9.service用url去寻找spring mvc子容器handlerMpping中的map集合中的映射关系(读取方法)        返回给service     
10.service用有效的映射关系,去springmvc子容器中得到指定Controller对象,            并用HandlerAdaper反射调用映射指定的方法,把方法的返回值给service方法     
11.service接收到了Model数据和View的页面名称,把ModelAndView(视图解析器)送给内部资源视图解析器            把Model数据渲染到页面上,view值拼装响应的url,并把渲染后的数据返回service方法     
12service方法把数据响应给客户端,service调用完毕,以后循环往复.

3原理图

 

4.SpringMVC常用注解

springMVC的常用注解
@Controller   相当于<bean>
@Autowired 根据类自动注入属性
@RequestMapping 指定请求路径
@RequestParam 给方法形参赋值时指定表单参数名称
@PathVaribale 用于restful风格的请求
@ResponseBody 返回json格式的数据
@Value 读取配置的常量

......

5.SpringMVC主要组件

1.前端控制器DispatcherServlet(不需要程序员开发)。 

作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。

2.处理器映射器HandlerMapping(不需要程序员开发)。 

作用:根据请求的url查找Handler。

3.处理器适配器HandlerAdapter(不需要程序员开发)。 

作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。

4.处理器Handler(需要程序员开发)。 

注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler

5.视图解析器ViewResolver(不需要程序员开发)。 

作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)

6.视图View(需要程序员开发jsp)。 

View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

【注】:不需要程序员开发的,需要程序员自己做一下配置即可。

6.接收数据(前端)

6.1 通过设置String userName,String userPassword 传值的方式


@Controller
public class UserController {
	/**
	 * 接收客户端提交的数据
	 * 要求名称必须精确一对一匹配
	 * @param userName  <input type="text" name="userName"/>
	 * @param userPassword <input type="password" name="userPassword"/>
	 * @return
	 */
	@RequestMapping(value="user/login1.do",method=RequestMethod.POST)
	public ModelAndView login1(String userName,String userPassword){
		System.out.println(userName+"     "+userPassword);
		ModelAndView mav=new ModelAndView();
		//假设此处调用业务,此处忽略业务
		
		mav.addObject("key", "value");
		//设置一个名称,用于springmvc拼装响应的url  前缀+success+后缀
		mav.setViewName("success");
		return mav;
	}

	

6.2通过注解方式@RequestParam               

/**
	 * 
	 * @param name  @RequestParam(value="userName",required=true) String name
	 *              <input type="text" name="userName"/>
	 * @param pwd   @RequestParam("userPassword")String pwd
	 *              <input type="password" name="userPassword"/>
	 * @return
	 */
	@RequestMapping(value="user/login2.do",method=RequestMethod.POST)
	public ModelAndView login2(
			@RequestParam(value="userName",required=true) String name,
			@RequestParam("userPassword")String pwd){
		System.out.println(name+"     "+pwd);
		ModelAndView mav=new ModelAndView();
		//假设此处调用业务,此处忽略业务
		
		mav.addObject("key", "value");
		//设置一个名称,用于springmvc拼装响应的url  前缀+success+后缀
		mav.setViewName("success");
		return mav;
	}

6.3通过JaveBean对象

/**
	 * 
	 * @param user   把name="userName"   -->setUserName   去User对象中找是否此方法,有就反射调用
	 *               把name="userPassword"   -->setUserPassword   去User对象中找是否此方法,有就反射调用
	 * @return
	 */
	@RequestMapping(value="user/login3.do",method=RequestMethod.POST)
	public ModelAndView login3(User user){
		System.out.println(user.getUserName()+"     "+user.getUserPassword());
		ModelAndView mav=new ModelAndView();
		//假设此处调用业务,此处忽略业务
		
		mav.addObject("key", "value");
		//设置一个名称,用于springmvc拼装响应的url  前缀+success+后缀
		mav.setViewName("success");
		return mav;
	}

6.4通过超链接传输方式 <a href="" >aaa</a>

@RequestMapping(value="user/login4.do",method=RequestMethod.GET)
	public ModelAndView login4(String name,String pwd){
		System.out.println(name+"     "+pwd);
		ModelAndView mav=new ModelAndView();
		//假设此处调用业务,此处忽略业务
		
		mav.addObject("key", "value");
		//设置一个名称,用于springmvc拼装响应的url  前缀+success+后缀
		mav.setViewName("success");
		return mav;
	}

7.返回数据(客户端)

7.1通过用ModelAndView 把数据存储给Model,把view 存储给View(只能给浏览器)

@Controller
public class UserController2 {
	/**
	 * 用ModelAndView 把数据存储给Model,把view 存储给View
	 * @param userName
	 * @param userPassword
	 * @return  ModelAndView
	 */
	@RequestMapping(value="user2/login1.do",method=RequestMethod.POST)
	public ModelAndView login1(String userName,String userPassword){
		System.out.println(userName+"     "+userPassword);
		ModelAndView mav=new ModelAndView();
		//假设此处调用业务,此处忽略业务
		//假设业务返回的数据为一个集合
		User user1=new  User(1,"aa","aa");
		User user2=new  User(2,"bb","bb");
		User user3=new  User(3,"cc","cc");
		ArrayList<User> users=new ArrayList<User>();
		users.add(user1);
		users.add(user2);
		users.add(user3);		
		/**
		 * 把数据存储给model
		 * 此写法为转发
		 * 等同于
		 * request.setAttribure("allUsers",users);
		 * request.getRequestDispatcher("WEB-INF/pages/success.jsp").forward(request,response);
		 */		
		mav.addObject("allUsers", users);
		//设置一个名称,用于springmvc拼装响应的url  前缀+success+后缀
		mav.setViewName("success");
		return mav;
	}

7.2通过String代替View+Model参数位置任意 ,用来存储Model的数据

/**
	 * 
	 * @param userName
	 * @param userPassword
	 * @param model  参数位置任意 ,用来存储Model的数据
	 * @return   String 代表view  
	 */
	@RequestMapping(value="user2/login2.do",method=RequestMethod.POST)
	public String login2(
			String userName,
			String userPassword,
			Model model){
		System.out.println(userName+"     "+userPassword);
		String result="error";
		//假设此处调用业务,此处忽略业务
		//假设业务返回的数据为一个集合
		User user1=new  User(1,"aa","aa");
		User user2=new  User(2,"bb","bb");
		User user3=new  User(3,"cc","cc");
		ArrayList<User> users=new ArrayList<User>();
		users.add(user1);
		users.add(user2);
		users.add(user3);		
		/**
		 * 把数据存储给model
		 * 此写法为转发
		 * 等同于
		 * request.setAttribure("allUsers",users);
		 * request.getRequestDispatcher("WEB-INF/pages/success.jsp").forward(request,response);
		 */		
		model.addAttribute("allUsers", users);
		//设置一个名称,用于springmvc拼装响应的url  前缀+success+后缀
		result="success";
		return result;
	}

7.3通过String代替View+modelMap代表的是Model

/**
	 * 
	 * @param userName
	 * @param userPassword
	 * @param modelMap  代表的是Model
	 * @return  代表的view
	 */
	@RequestMapping(value="user2/login3.do",method=RequestMethod.POST)
	public String login3(
			String userName,
			String userPassword,
			ModelMap modelMap){
		System.out.println(userName+"     "+userPassword);
		String result="error";
		//假设此处调用业务,此处忽略业务
		//假设业务返回的数据为一个集合
		User user1=new  User(1,"aa","aa");
		User user2=new  User(2,"bb","bb");
		User user3=new  User(3,"cc","cc");
		ArrayList<User> users=new ArrayList<User>();
		users.add(user1);
		users.add(user2);
		users.add(user3);		
		/**
		 * 把数据存储给model
		 * 此写法为转发
		 * 等同于
		 * request.setAttribure("allUsers",users);
		 * request.getRequestDispatcher("WEB-INF/pages/success.jsp").forward(request,response);
		 */		
		modelMap.addAttribute("allUsers", users);
		//设置一个名称,用于springmvc拼装响应的url  前缀+success+后缀
		result="success";
		return result;
	}

7.4通过String代替View+Map代表的是Model

@RequestMapping(value="user2/login4.do",method=RequestMethod.POST)
	public String login4(
			String userName,
			String userPassword,
			Map map){
		System.out.println(userName+"     "+userPassword);
		String result="error";
		//假设此处调用业务,此处忽略业务
		//假设业务返回的数据为一个集合
		User user1=new  User(1,"aa","aa");
		User user2=new  User(2,"bb","bb");
		User user3=new  User(3,"cc","cc");
		ArrayList<User> users=new ArrayList<User>();
		users.add(user1);
		users.add(user2);
		users.add(user3);		
		/**
		 * 把数据存储给model
		 * 此写法为转发
		 * 等同于
		 * request.setAttribure("allUsers",users);
		 * request.getRequestDispatcher("WEB-INF/pages/success.jsp").forward(request,response);
		 */		
		map.put("allUsers", users);
		//设置一个名称,用于springmvc拼装响应的url  前缀+success+后缀
		result="success";
		return result;
	}

7.5借助jackson把java对象转换json字符串,并响应给客户端(可跨平台)

@RequestMapping(value="user2/login5.do",method=RequestMethod.GET)
	@ResponseBody//借助jackson把java对象转换json字符串,并响应给客户端
	public Result login5(
			String userName,
			String userPassword){
		System.out.println(userName+"     "+userPassword);
		Result result=new Result();
		
		//假设此处调用业务,此处忽略业务
		//假设业务返回的数据为一个集合
		User user1=new  User(1,"aa","aa");
		User user2=new  User(2,"bb","bb");
		User user3=new  User(3,"cc","cc");
		ArrayList<User> users=new ArrayList<User>();
		users.add(user1);
		users.add(user2);
		users.add(user3);		
		
		result.setStatus(1);
		result.setMessage("登录成功!!");
		result.setData(users);
		
		return result;
	}

7.6程序员先把users对象转换json字符串 用response对象把json字符串响应给客户端(可跨平台)

	@RequestMapping(value="user2/login5_1.do",method=RequestMethod.GET)
	public void login5_1(
			String userName,
			String userPassword,
			HttpServletRequest request,
			HttpServletResponse response){
		System.out.println(userName+"     "+userPassword);
		Result result=new Result();
		
		//假设此处调用业务,此处忽略业务
		//假设业务返回的数据为一个集合
		User user1=new  User(1,"aa","aa");
		User user2=new  User(2,"bb","bb");
		User user3=new  User(3,"cc","cc");
		ArrayList<User> users=new ArrayList<User>();
		users.add(user1);
		users.add(user2);
		users.add(user3);		
		
		result.setStatus(1);
		result.setMessage("登录成功!!");
		result.setData(users);
		
		//程序员自己先把users对象转换成json字符串
		//用response对象吧json字符串响应给客户端
		String jsonString=JSON.toJSONString(result);
		System.out.println("jsonString="+jsonString);
		
		try {
			//设置response响应消息头
			response.setContentType("text/json;charset=UTF-8");
			//构建响应的输出流
			PrintWriter out=response.getWriter();
			//把json字符串的内容响应给客户端
			out.println(jsonString);
			out.flush();
			out.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

小总结:

在实际开发中

接收数据 1,2,3,4

返回数据 1.2.3.4.(字符串只适合浏览器)5.6(json可跨平台)多用json

 

8过滤器和拦截器的区别

<!-- 拦截器配置 -->
<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="com.eric.cart.interceptor.LoginInterceptor"/>
	</mvc:interceptor>
</mvc:interceptors>
  • 过滤器是servlet 规范中的一部分,任何java web工程都可以使用。
  • 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
  • 过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截。
  • 拦截器它是只会拦截访问的控制器方法,如果访问的是jsp,html,css,image或者js是不会进行拦截的。

9.springmvc与struts2本质不同

        1.springmvc入口是一个servlet前端控制器(DispatcherServlet),struts2入口是一filter过滤器(StrutsPrepareAndExecuteFilter).
        2.struts2通过在action类中定义成员变量接收参数,(属性驱动和模型驱动),它只能使用多例模式管理action.
           springmvc通过在coontroller方法中定义形参接收参数,springmvc可以使用单例模式管理controller.      
        3.springmvc是基于方法开发的,注解开发中使用requestMapping将url和方法进行 映射,如果根据url找到controller类的方法生成                       一 个handler处理器对象(只包括一个method).
          struts2是基于类开发的,每个请求过来创建一个action实例,实例对象中有若干个方法.
          开发中建议使用springmvc,springmvc方法更类似service业务方法.
        4.struts2采用值栈存储请求和相应的数据,通过OGNL存取数据,springmvc通过参数绑定期将request请求内容解析,并给方法形参赋值.
        5.struts2和springmvc的速度是相当的,由于struts2的漏洞较多,跟多企业使用springmvc

       struts2:底层是Servlet,参数基于属性封装,如果配置单例,会出现线程安全问题,所以配置多例 
        springmvc:底层是Servlet,单例 
       6. 参数封装 
       struts2:基于属性封装 
       springmvc:基于方法进行封装

10支持的数据类型

  • 参数类型推荐使用包装数据类型,因为基础数据类型不可以为null 
  • 整形:Integer、int 
  • 字符串:String 
  • 单精度:Float、float 
  • 双精度:Double、double 
  • 布尔型:Boolean、boolean

 

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值