SpringMVC的介绍与使用

三世轮回 提交于 2019-12-09 02:43:17


         一,MVC

           1.什么是mvc

              mvc是一种设计模式,帮助使用者更好搭建和编写项目,在b/s,c/s架构中经常使用,mvc表示全称为Model-View-controller,即模型-视图-控制三层结构,三层每层负责不同的功能,其中,model层用于封装简单的javaBean和复杂的javaBean,包括业务层,甚至dao层,只要是个javabean都属于model(注意不要狭义的以为,java仅仅只是pojo对象,他也可以是一个包含复杂逻辑的service),pojo对象的代码都是包含的,视图层主要是页面,用于返回给用户的,直观的一种可视化的界面,比如jsp,html,

,包扩c/s的等,而Controller主要到控制,并且和用户交流的作用,比如,如果你要登陆,那么控制层就会返回一个登陆的页面给你,当你提交页面后,控制层就会调用model的业务

逻辑方法来验证你的输入是否正确。这就是一个mvc简单的调用过程


        2.SpringMVC

              SpringMVC是整个spring中的一个很小的组成,准确的说他是spring WEB这个模块的下一个子模块,Spring WEB中除了有springMVC还有struts2,webWork等MVC框架。

下面,我们来看下SpringMVC的一个结构图,熟悉struts2的人,应该会很熟悉这个图

                                   



                   首先解释下各个名词的意思以及这个流程的是 怎样的

               1.用户发起请求,请求到DispatchServlet前端控制器

                DIspatcheServelt(中央调度),负责request和response,负责调用处理器映射器查找Handler,负责调用处理

               器映射器(Mapping)查找Handler,负责调用处理器适配器(Adapter)执行Handler,有了前端控制器降低了各各组件之间的耦合性,系统扩展性能得到提高。

               2.DispatcherServlet前端控制器请求处理器映射器HandlerMapping查找Handler

               根据用户请求的url,根据一定的规则去查找(比如:xml配置,注解)

              3.HandlerMapping处理器映射器将Handler返回给前端控制器

              4.DispatcherServlet前端控制器调用HandlerAdapter处理器适配器执行Handler

               程序员编写的Handler是按照适配器要求的规则去执行handler

              5.HandlerAdapter处理器适配器执行Handler

               适配器按照一定的规则去执行Handler

              6.Handler执行完成,返回ModelAndView

                ModelAndView是SpringMVC的封装对象,将model和view封装在一起

              7.HandlerAdapter处理器适配器将ModelAndView返回给前端 控制器

     

              8.前端控制器调用视图解析器,进行视图处理,解析完成给前端控制器返回View

               View是springmvc的封装对象,是一个接口,实现类包括jspView,pdfView....

             9.前端控制器调用view进行渲染

                将模型数据填充到view(将model数据填充到request)响应给用户

            10.前端控制器响应给用户


         综上所述,springmvc主要由 一个DispatcherServlet(不需要开发),三个组件:处理器映射器,处理器适配器,视图解析器(不需要开发)

       hanlder(需要开发),view(需要开发)组成


        

        二,SpringMVC和Struts2的不同

                  

                       1、 springmvc的入口是servletstrutsfilter

                       2 springmvc是基于方法开发,struts是基于类开发

                             

                action类中,一个url对应一个方法,对Handler对象,springmvc框架将一个方法封装到Handler中(只有一个method)。Strutsaction类进行实例化。

                Springmvc中的action可以使用单例也可以使用多例,建议使用单例(对相同的方法只new一个)。

Struts不能用单例,因为struts传递参数是通过成员变量。

 

                Springmvc通过形参接收参数好处:更符合软件开发的思想,和service接口类似。


                    

                       3、 Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,

               并给方法形参赋值, 将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。

              Jsp视图解析器默认使用jstl

 


          

       

      三,Spring的配置与使用

                1.准备jar包

                         


                   2.配置springmvc.xml

                                 因为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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.0.xsd 
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
		
		 <!-- 配置拦截器 -->
		  <mvc:interceptors>
		     <!--  <mvc:interceptor>
		          <mvc:mapping path="/**"/>
		          <bean class="com.itheima.springmvc.interceptor.HandlerInterceptor1"></bean>
		      </mvc:interceptor>
		       <mvc:interceptor>
		           <mvc:mapping path="/**"/>
		            <bean class="com.itheima.springmvc.interceptor.HandlerInterceptor2"></bean>
		       </mvc:interceptor> -->
		       <mvc:interceptor>
		           <mvc:mapping path="/**"/>
		            <bean class="com.itheima.springmvc.interceptor.LoginInterceptor"></bean>
		       </mvc:interceptor>
		  </mvc:interceptors>
		 <!-- 组件扫描 -->
		 <context:component-scan base-package="com.itheima.springmvc.action"></context:component-scan>
		
		 <!-- 使用<mvc:annotation-driven/>替换上边定义的处理映射器和适配器 -->
		  <mvc:annotation-driven/>
		<!-- 注解映射器 -->
		 <!--  <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->
		  
		  <!-- 注解适配器 -->
		   <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		      json转换器
		      <property name="messageConverters">
		           <list>
		              <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
		           </list>
		      </property>
		   </bean> -->
		 <!-- 
		    处理器映射器,根据u'r'l匹配bean的name,处理器映射器实现了HandlerMapping接口
		  -->
		 <!--  <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> -->
		
		 <!-- 简单的url映射 -->
		   <!--  <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		        <property name="mappings">
		           <props>
		              <prop key="/hello1.action">hello_controller</prop>
		              <prop key="/hello2.action">hello_controller</prop>
		              <prop key="/hello3.action">hello_controller3</prop>
		           </props>
		        </property>
		    </bean> -->
		     <!-- 多个处理器映射器可以共存 -->
		    <!-- 处理器适配器
		         实现了HandlerADapter接口
		     action按照适配器要求开发,规则是实现Controller接口
		       -->
		     <!--   <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> -->
		     
		     <!-- 配置HttpRequestHandlerAdapter处理器适配器 -->
		     <!--  <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/> -->
		      
		      
		      
		       <!-- 视图解析器 解析jsp视图,默认使用jstl,要求classpath下有jstljar包 -->
		        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		        
		               <!-- 视图的前缀 -->
						<property name="prefix" value="/WEB-INF/jsp/" />
						<!-- 视图的后缀 -->
						<property name="suffix" value=".jsp" />
		        </bean>

		       <!-- 配置action -->
		       <!-- <bean id ="hello_controller" name="/helloworld.action" class="com.itheima.spring.Hello1"/>
		       <bean id ="hello_controller3" class="com.itheima.spring.Hello2"/> -->
		       
		       <!-- 学生信息修改 -->
		       <!-- <bean name="/editstudentsubmit.action" class="com.itheima.spring.student.EditStudentSubmit"></bean>
		        <bean name="/editstudent.action" class="com.itheima.spring.student.EditStudent"></bean> -->
		 
		 
		
		      
		</beans>

                    由于担心截图会导致有些配置可能不清楚,所以我把所有配置都发了,现在主要说下,未注释的部分,首先,组件扫描器,使用扫描器,可以让该包下所有的类都能支持注解开发,然后配置注解映射器(RequestMappingHandlerMapping)和注解适配器(RequestMappingHandlerAdapter),其实,也可以通过配置注解驱动器如下

<mvc:annotation-driven/>就可以不用配置映射器和适配器了,我这里用的是注解驱动器,注意那个,json的配置,可以很轻松的处理json字符串的转换,好了,配置文件写好了,下面我们要让这个配置生效


          3.配置web.xml,让springmvc.xml生效

                这个配置和struts2的配置很像,可以借鉴下,配置代码如下
                   
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>SpringMVC</display-name>
  
   <!-- 前端控制器 -->
   <servlet>
       <servlet-name>springmvc</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       
          <!-- contextConfigLocation指定Springmvc的全局配置文件
                                     如果contextConfigLocation不指定,默认找配置文件名称:servlet的name+"-servlet.xml"+
           -->
          <init-param>
             <param-name>contextConfigLocation</param-name>
             <param-value>classpath:springmvc.xml</param-value>
          </init-param>
   </servlet>
   
     <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.action</url-pattern>
     </servlet-mapping>
     
     <!-- 处理post乱码 -->
      <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>
     
</web-app>
     配置DispatcherServlet,这样前端控制器,就会启用,同时指定springmvc.xml的路径,这样springmvc.xml配置文件也会生效,下面的代码是用来处理Post的乱码的,如果是
get乱码,一种可以改Tomcat配置文件(不推荐),一种是可以使用下面的代码方法(推荐)

String userName new

String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")


            

           4.编写Handler处理器

                 下面看一个Demo

                 

package com.itheima.springmvc.action;


import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.itheima.springmvc.pojo.Student;
import com.itheima.springmvc.pojo.UserModel;


/**
 * 
 * <p>Title: StudentAction</p>
 * <p>Description: 注解开发学生信息管理系统</p>
 * <p>Company: www.itcast.com</p> 
 * @author	孔旻
 * @date	2017年8月6日下午11:09:00
 * @version 1.0
 */
@Controller
@RequestMapping("/stu")
public class StudentAction {

	
	
	 //学生信息查询
	
	   @RequestMapping(value="/querystudent")
	   public String queryStudent(Model model,
			                      @RequestParam(value="groupid",required=true,defaultValue="3") String group,UserModel userModel){
		   
		   
		   System.out.println("group="+group);
		   //创建一个集合,初始化一些数据
		   List<Student> stuList = new ArrayList<Student>();
		   
		     Student s1 =new Student();
		       s1.setId(1);
		       s1.setName("张三");
		       s1.setBirthday(new Date());
		       s1.setAge(25);
		       s1.setAddress("中国江苏");
		       
		     
		       Student s2 =new Student();
		       s2.setId(2);
		       s2.setName("李四");
		       s2.setBirthday(new Date());
		       s2.setAge(24);
		       s2.setAddress("中国浙江");
		       Student s3 =new Student();
		       s3.setId(3);
		       s3.setName("王五");
		       s3.setBirthday(new Date());
		       s3.setAge(23);
		       s3.setAddress("中国江苏");
		       Student s4=new Student();
		       s4.setId(4);
		       s4.setName("赵六");
		       s4.setBirthday(new Date());
		       s4.setAge(25);
		       s4.setAddress("中国广东");
		       
		       stuList.add(s1);
		       stuList.add(s2);
		       stuList.add(s3);
		       stuList.add(s4);
		       
		       
		       model.addAttribute("stuList",stuList);
		       
		       //返回逻辑视图
		       return "student/querystudent";
		     
		      
	   }
	 //修改学生信息页面
	
	    //可以限定请求为GET/Post,或者都可以,但是这样限定后,使用别的方式提交就会无效
	  @RequestMapping(value="/editstudent/{id}.action",method=RequestMethod.GET)
	  public String editstudent(Model model,HttpServletRequest request,@PathVariable String id)throws Exception{
		
		  System.out.println("request.getParanmeter="+request.getParameter("id"));
		  System.out.println("id="+id);
		  //使用静态数据
		  Student student = new Student();
		  student.setId(1);
		  student.setName("张三");
			 student.setAge(25);
			 student.setBirthday(new Date());
		  
			model.addAttribute("student",student);
		  //返回逻辑视图名
		return "student/editstudent";
		  
		  
		  
	  }
	//学生信息查询修改提交
	   @RequestMapping(value="/editstudentsubmit",method=RequestMethod.POST)
	   public String editstudentsubmit(String id_,UserModel userModel)throws Exception{
		   
		   System.out.println(id_);
		   System.out.println(userModel.getStudent().toString());
		   
		   //返回逻辑视图(成功页面)
		   // return "success";
		   
		    //请求重定向
		   //return "redirect:querystudent.action";
		   
		   //请求转发
		    return "forward:querystudent.action";
		   
	  
	   }
	   
	   
	   
	 //注册一个属性编辑器
		//如果不实现此方法,日期类型将不能转换
		@InitBinder
		protected void initBinder(HttpServletRequest request,
				ServletRequestDataBinder binder) throws Exception {
			
			
			//将student类中的birthday属性进行日期转换,类型和birthday一致
			
			 binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
		}
	 
	   
	      @RequestMapping("/deletestu")
		public String deletestu(String[] deleteid){
	    	  System.out.println(deleteid);
	    	  return "student/querystudent";
			
		}
	      

}

        


看这几个注解,分别为Controller,requestMapping.

Controller声明该类为控制器,即是Handler处理器,requestMapping是一个处理器映射器注解,通过指定value,来决定访问这个方法的url路径,model对象用来存放值,用于返回到视图,注意,在SpringMVC中,是基于方法的访问,而不是基于类,所以如果你打算使用类似于struts的属性驱动或者模型驱动,那么就把属性和对象设置到方法的形参中,这样在实际访问这个方法时,其实就会把页面的字段封装成属性或者对象(如果可以的话),作为实参传给方法的形参,所以要保证方法形参属性名或者对象名和页面

字段或者pojo对象保持一致,下面是springmvc传递参数的图,

                                       




               requestMapping的参数介绍

                1.value:表示访问的url

                2.method=RequestMethod.GET:表示限制访问方式为get,也可指定为其他访问方式

               3.url模板映射:这个通过在方法指定注解@PathVariab,如下图

                    

    

                    这种方式让url更能被抓取,提高网站访问量

            

               4.注意这种Pojo点属性名传递参数的方式如下

                          

                     注意使用属性名.属性的方法传递参数,这种方式,在handler中需要对pojo进行封装,并且封装的pojo的名字和页面pojo的名字要一致,这个很重要


                   下面是数组和集合的参数传递,如下图

                          (1) 数组.

                                     


                      

                   (2),集合

                      *1.页面定义

                             

                            解释:

                                   

                                        Scores:包装对象中list属性的名称

                                       Coursename:包装对象中listpojo的属性名称。

                                       Score:包装对象中listpojo的属性名称。

                  如果上边下标相同的CoursenameScore设置在一个pojo中。



           *2.Action定义

                

                          Action方法定义:

           使用List<pojo>接收上边的接收,pojo中包括上边课程名称(coursename)和成绩(score)

                         

                         

 


      注意保持一致

         5.requestParam绑定单个请求参数

           value参数名字,即入参的请求参数名字,如value=studentid表示请求的参数区中的名字为studentid的参数的值将传入;

           required是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;

            defaultValue默认值,表示如果请求中没有同名参数时的默认值

    

         6.结果转发,感觉这里没什么太难的,就发图了

                    



             

          5.拦截器的配置与使用

              *1.针对某一个handlerMapping配置拦截器,配置如下

  

<bean
	class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
	<property name="interceptors">
		<list>
			<ref bean="handlerInterceptor1"/>
			<ref bean="handlerInterceptor2"/>
		</list>
	</property>
</bean>
	<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
	<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>

           2.配置全局拦截器

<!--拦截器 -->
<mvc:interceptors>
	<!--多个拦截器,顺序执行 -->
	<mvc:interceptor>
		<mvc:mapping path="/**"/>//拦截所有请求
		<bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor1"></bean>
	</mvc:interceptor>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor2"></bean>
	</mvc:interceptor>
</mvc:interceptors>


             3.编写一个拦截器

                编写一个拦截器,需要实现一个接口中的方法

                

package com.itheima.springmvc.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 HandlerInterceptor1 implements HandlerInterceptor{

	 //执行时机:Handler方法执行完成,(modelAndView已经返回)
	 //使用场景:统一异常处理,统一记录系统日志,用于action方法执行监控
	 //(在preHandle记录一个时间点,在afterCompletion记录执行结束时间点,将结束时间点减去开始时间点,得到执行时长)
	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		 System.out.println("HandlerInterceptor1--->>afeterCompletion");
		
	}

	 //执行时机:进入Handler方法之后,再返回ModelAndView之前
	 //使用场景:使用modelAndView,向页面传递通用数据,使用统一的view
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response,
			Object handler, ModelAndView modelAndView) throws Exception {
	
		 System.out.println("HandlerInterceptor1-->>postHandler1");
		
	}

	 //hanlder:springmvc根据url找到Handler(只有一个方法)
	 //执行时机:进入Handler方法之前执行,如果返回false,表示拦截,如果返回true表示放行
	 //使用场景:用于用户身份校验,用户权限拦截校验
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
			Object handler) throws Exception {
	
		 System.out.println("HandlerInterceptor1-->>preHandler1");
		return true;
	}
	
	
	 

}


   可以用这个拦截器来实现url验证,即权限管理

     四.总结

             springmvc本身就是Spring体系中的一员,所以他和Spring整合更加方便,同时设计上又是优于struts,而且Spring boot 和 Spring Cloud 变得越来越火,因此
掌握SpringMVC



          

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!