Spring MVC起步

1. MVC概念

1.1 前端控制器       

   

1.2 MVC概念                MVC的核心思想---业务数据抽取 与 业务数据呈现 相分离

View:视图层,为用户提供UI,重点关注数据的呈现;
Model:模型层,业务数据的信息表示,关注支撑业务地信息构成,通常是多个业务实体的组合;
Cotroller:控制层,调用业务逻辑产生合适的数据,传递数据给视图层用于呈现;

MVC是什么?
1、MVC是一种架构模式,是程序分成,分工合作,既相互独立,有协同工作。
2、MVC是一种思考方式,模型层思考为用户展现什么,在视图层思考如何布局,在控制层思考调用那些业务逻辑。

2. Spring MVC概念

2.1  Spring MVC 基本概念
1、DispatcherServlet:  前端控制器
2、Controller: 调用业务逻辑生成model的地方
3、HandlerAdapter:处理器适配器DispatcherServlet通过HandlerAdapter调用controller
4、HandlerInterceptor:处理器拦截器 该接口提供after postHandle preHandle 三个方法,调用controller前后使用
5、HandlerMapping:前端控制器与controller映射关系的类
6、HandlerExecutionChain: preHandle->Controller method->postHandle->afterCompletion的执行链
7、ModelAndView:model的具体表现
8、ViewResolver:视图解析器,决定需要用哪个视图来进行视图的呈现。

2.2 架构流程图

2.3  架构流程

       1、 用户发送请求至前端控制器DispatcherServlet

   2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

       3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。

     4、 DispatcherServlet通过HandlerAdapter处理器适配器调用处理器

   5、 执行处理器(Controller,也叫后端控制器)。

   6、 Controller执行完成返回ModelAndView

   7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet

   8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器

   9、 ViewReslover解析后返回具体View

   10、 DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中) 

   11、 DispatcherServlet响应用户

3. 应用maven工具,管理springMVC

 3.1  maven的三个重要概念:配置pom.xml,依赖dependency, 坐标coordinates(groupId,artifactId,version,packaging)

 3.2 maven配置     setting.xml配置镜像仓库:用UK的镜像仓库可以提高访问成功率

镜像配置,每次访问Maven时候都先访问配置的这个库,下载所需要的软件包,这样可以降低中心仓库的负载,中心仓库为了避免大量访问造成的服务问题有时会拒绝
我们的访问。

 3.3 Maven创建项目

3.3.1.  添加Maven  在继承Maven的eclipse中,windows--->prefrences---->Maven--->Installation--->将新下载的maven文件add进去,确保在user Setings中配置文件的路径是之前配置了mirror的配置文件setting.xml

3.3.2.  运行命令行创建项目 注意:需要在命令行中进入指定创建项目的路径  例如:cd C:UsersWorkspacesEclipse 

命令: mvn archetype:generate -DgroupId=imooc-arthur -DartifactId=spring-mvc-study -DarchetypeArtifactId=maven-archetype-webapp

参数解释:   archetype:generate 调用插件

      groupId:坐标

      artifactId:坐标的一个元素,目录结构的根目录名称

      archetypeArtifactId:目录类型的一个类型,此为webapp的类型

3.3.3  搭建Spring MVC基础框架

  1.导入项目 import-->Maven(ExistingMaven Projects)-->刚创建的文件目录spring-mvc-study

  2.缺失Java目录时,手动添加Java目录 右键main-->folder-->java

  3.pom.xml 添加各种依赖包

  4.web.xml文件 配置 DispatcherServlet -- Spring MVC的核心

    如果不配置<init-param>,那么将会默认读取WEB-INF目录下的%servlet-name%-servlet.xml配置文件,配置init-param后将读取这里配置的文件

            

  5.mvc-dispatcher-servlet.xml 启用Spring基于annotation的DI 配置DispatcherServlet上下文, 只管理@Controller类型的bean, 忽略其他型的bean, 如@Service 扩充了注解驱动,可以将请求参数绑定到控制器参数 配置ViewResolver;可以用多个ViewResolver;使用order属性排序;InternalResourceViewResolver放在最后。

  6.创建Controller类

  7.创建home.jsp

  8.运行jetty(在配置文件中配置的jetty插件为我们提供了一个运行的容器环境),访问

4. 在具体项目中实现springMVC

4.1 配置文件

4.1.1  在web.xml文件中如此配置

 <!-- Spring应用上下文, 理解层次化的ApplicationContext -->
  <context-param>
         <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/configs/spring/applicationContext*.xml</param-value>
  </context-param>
<!-- DispatcherServlet对应的上下文配置, 默认为/WEB-INF/$servlet-name$-servlet.xml
         -->
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/configs/spring/mvc-dispatcher-servlet.xml</param-value>
        </init-param>

        

 通过使用不同的dispatcher-servlet来做不同的分发,可以更好的服务不同来源的请求。

4.1.2  配置名为mvc-dispatcher的DispatcherServlet,为其提供spring MVC配置  

mvc-dispatcher-servlet.xml文件中
<beans>
   xmlns=········
············································省略..
<!-- 本配置文件是供名为mvc-dispatcher的DispatcherServlet使用, 提供其相关的Spring MVC配置 -->

    <!-- 启用Spring基于annotation的DI, 使用户可以在Spring MVC中使用Spring的强大功能。 激活 @Required 
        @Autowired,JSR 250's @PostConstruct, @PreDestroy and @Resource 等标注 -->
    <context:annotation-config />

    <!-- DispatcherServlet上下文, 只管理@Controller类型的bean, 忽略其他型的bean, 如@Service -->
    <context:component-scan base-package="com.zang.mvcdemo">
        <context:include-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!-- HandlerMapping, 无需配置, Spring MVC可以默认启动。 DefaultAnnotationHandlerMapping 
        annotation-driven HandlerMapping -->

    <!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 -->
    <mvc:annotation-driven />

    <!-- 静态资源处理, css, js, imgs -->
    <mvc:resources mapping="/resources/**" location="/resources/" />


    <!-- 配置ViewResolver。 
      可以用多个ViewResolver。 
      使用order属性排序。 
     InternalResourceViewResolver放在最后。 -->
    <bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="order" value="1" />
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
                <entry key="xml" value="application/xml" />
                <entry key="htm" value="text/html" />
            </map>
        </property>

        <property name="defaultViews">
            <list>
                <!-- JSON View -->
                <bean
                    class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
                </bean>
            </list>
        </property>
        <property name="ignoreAcceptHeader" value="true" />
    </bean>

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsps/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

4.1.3 配置applicationContext.xml

    <context:annotation-config />

    <context:component-scan base-package="com.zang.mvcdemo">
    <!-- context:exclude-filter:不需要管理Controller了     -->
        <context:exclude-filter type="annotation"
            expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

4.2 Controller代码

@Controller声明了一个Controller
@RequestMapping对应到具体的请求
@RequestParam 和@PathVariable绑定了请求中的参数
也可以使用HttpServletRequest 或HttpSession请求响应
@Controller
@RequestMapping("/courses")
// /courses/**
public class CourseController {
    
    private static Logger log = LoggerFactory.getLogger(CourseController.class);

    private CourseService courseService;

    @Autowired
    public void setCourseService(CourseService courseService) {
        this.courseService = courseService;
    }

    
    //本方法将处理 /courses/view?courseId=123 形式的URL
    @RequestMapping(value="/view", method=RequestMethod.GET)
    public String viewCourse(@RequestParam("courseId") Integer courseId,
            Model model) {
        
        
        log.debug("In viewCourse, courseId = {}", courseId);
        Course course = courseService.getCoursebyId(courseId);
        model.addAttribute(course);
        return "course_overview";
    }
    
    //本方法将处理 /courses/view2/123 形式的URL
    @RequestMapping("/view2/{courseId}")
    public String viewCourse2(@PathVariable("courseId") Integer courseId,
            Map<String, Object> model) {
        
        log.debug("In viewCourse2, courseId = {}", courseId);
        Course course = courseService.getCoursebyId(courseId);
        model.put("course",course);
        return "course_overview";
    }

    //本方法将处理 /courses/view3?courseId=123 形式的URL
    @RequestMapping("/view3")
    public String viewCourse3(HttpServletRequest request) {
        
        Integer courseId = Integer.valueOf(request.getParameter("courseId"));        
        Course course = courseService.getCoursebyId(courseId);
        request.setAttribute("course",course);
        
        return "course_overview";
    }   }
4.3 Binding——绑定(将请求中的字段按照名字匹配的原则填入模型对象))
@RequestMapping中也可以添加params="add"属性,表示带add参数的请求才可以进来;返回字符串可以加/来进行相对目录的指定。
@ModelAttribute可以用于绑定对象,返回值加上"redirect:XXXX"就可以重定向 方法级别数据绑定@ModelAttribute注释一个方法的参数
1.从Model中获取
   2.从Form表单或URL参数中获取(实际上,不做此注释也能拿到user对象)
redirect(重定向)/forward(请求转发)
@RequestMapping(value="/admin", method = RequestMethod.GET, params = "add")
    public String createCourse(){
        return "course_admin/edit";
    }
    
    @RequestMapping(value="/save", method = RequestMethod.POST)
    public String  doSave(@ModelAttribute Course course){        
        
        log.debug("Info of Course:");
        log.debug(ReflectionToStringBuilder.toString(course));
        
        //在此进行业务操作,比如数据库持久化
        course.setCourseId(123);
        return "redirect:view2/"+course.getCourseId();
    }

4.4 fileUpload 单文件上传

①注册使用到的类:CommonsMultipartReslover类,这个类需要在spring的配置文件中进行配置,并设置一些必要的属性,比如是否延迟加载,上传文件的大小等等。
②注意form表单中,对应的表单的name值应该和controller中参数Multipart file的名称一致,另外注意表单提交方式为post,MIME编码为multipart/form-data
③在controller中通过传入的参数类型为Multipart file并且使用@Requestparam注解,完成参数的绑定,这样表单中的file就被复制到参数对象中。然后通过Multipart的一些方法,
获取文件的名字信息并得到文件流对象,然后使用FileUtils类的copyInputStreamToFile(文件流,文件)完成文件的上传。
4.4.1 mvc-dispatcher-servlet.xml文件中加入如下bean配置
    <!--200*1024*1024即200M resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="209715200" />
        <property name="defaultEncoding" value="UTF-8" />
        <property name="resolveLazily" value="true" />
    </bean>

4.4.2 pom.xml文件里配置相关jar包依赖

4.4.3 Controller

    @RequestMapping(value="/upload", method=RequestMethod.GET)
    public String showUploadPage(@RequestParam(value= "multi", required = false) Boolean multi){    
        if(multi != null && multi){
            return "course_admin/multifile";    
        }
        return "course_admin/file";        
    }
    
    @RequestMapping(value="/doUpload", method=RequestMethod.POST)
    public String doUploadFile(@RequestParam("file") MultipartFile file) throws IOException{
        
        if(!file.isEmpty()){
            log.debug("Process file: {}", file.getOriginalFilename());
            FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\temp\imooc\", System.currentTimeMillis()+ 
     file.getOriginalFilename())); }
return "success"; } @RequestMapping(value="/doUpload2", method=RequestMethod.POST) public String doUploadFile2(MultipartHttpServletRequest multiRequest) throws IOException{ Iterator<String> filesNames = multiRequest.getFileNames(); while(filesNames.hasNext()){ String fileName =filesNames.next(); MultipartFile file = multiRequest.getFile(fileName); if(!file.isEmpty()){ log.debug("Process file: {}", file.getOriginalFilename()); FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\temp\imooc\", System.currentTimeMillis()+
       file.getOriginalFilename())); } }
return "success"; }

4.5 JSON(一种轻量级的数据交换的格式)

springMVC使用viewResovler来处理含义相同格式不同(json xml html)的数据
4.5.1 mvc-dispatcher-servlet.xml文件中(记得加入依赖)
 <!-- 配置ViewResolver。  可以用多个ViewResolver。      使用order属性排序。    InternalResourceViewResolver放在最后。 -->
    <bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="order" value="1" />
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
                <entry key="xml" value="application/xml" />
                <entry key="htm" value="text/html" />
            </map>
        </property>

        <property name="defaultViews">
            <list>
                <!-- JSON View -->
                <bean
                    class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
                </bean>
            </list>
        </property>
        <property name="ignoreAcceptHeader" value="true" />
    </bean>

Controller

     @RequestMapping(value="/{courseId}",method=RequestMethod.GET)
    public @ResponseBody Course getCourseInJson(@PathVariable Integer courseId){
        return  courseService.getCoursebyId(courseId);
    }
       
     @RequestMapping(value="/jsontype/{courseId}",method=RequestMethod.GET)
    public  ResponseEntity<Course> getCourseInJson2(@PathVariable Integer courseId){
        Course course =   courseService.getCoursebyId(courseId);        
        return new ResponseEntity<Course>(course, HttpStatus.OK);
    }

4.5.2 在前端使用ajax异步处理,触发请求,在请求的url中传入id,到后台之后,后台根据url,分解出pathVariable ,调用service方法,获得数据对象,然后返回@ResponseBody,此时,前台的ajax正在监听服务端的状态,如果是成功状态,将触发回调函数,函数中封装了对数据的逻辑,也就是使用js技术把数据对号入座,并且美化,展示页面。请求路径是一种restful风格。

前台异步获取数据

<script>
jQuery(function($){
    var urlStr = "<%=request.getContextPath()%>/courses/<%=request.getParameter("courseId")%>";
    //alert("Before Call:"+urlStr);
    $.ajax({
        method: "GET",
        url: urlStr,
        success:function(data,status,jqXHR){
            //alert("Success:"+data);
            var course = data;
            var path = "<%=request.getContextPath()%>/";    
            $(".course-title").html(course.title);
            $(".course_video").attr("src", path+course.imgPath);
            $("#learningNum").text(course.learningNum);
            $("#duration").text(course.duration);
            $("#levelDesc").text(course.levelDesc);
            $(".course_shortdecription").html(course.descr);
            
            var chapterList = course.chapterList;
            var chapter;
            
            for(var i = 0;i<chapterList.length;i++){
                chapter = chapterList[i];    
                
                var liObj = $("li",$("#chapterTemplate")).clone();                 
                $(".outline_name", liObj).text(chapter.title);
                $(".outline_descr", liObj).text(chapter.descr);                
                liObj.appendTo("#couList");                
            }// ~ end for            
        }
    }); // end ajax
});
</script>

4.5.3 Json view的三种方式

   ContentNegotiatingViewResolver 决定返回的数据是以Json还是jsp格式展示

   ResponseEntity将返回的数据包裹在其中,便可以以Json格式返回

   @ResponseBody/@ResquestBody 可以将请求值和返回值变成Json格式传输

5. summary

原文地址:https://www.cnblogs.com/zjfjava/p/6746704.html