zoukankan      html  css  js  c++  java
  • SpringMVC初学

      

           Spring MVC,即 Spring Model-View-Controller,是一个实现了通用开发模式(模型-视图-控制器)的Web框架,它通过一个DispatcherServlet处理HTTP请求、完成资源映射、递交请求给控制器完成业务逻辑,相应数据则通过Model传递给视图解析器解析为相应的页面或数据流返回给客户端。

        这里,我们可以通过Spring官方给出的图示大致了解其内部的工作机制:

             

         DispatcherServlet作为前端控制器(Front Controller)过滤所有客户端发来的请求,检查请求路径并根据配置好的映射规则,将请求提交给指定的控制器(Controller),完成业务逻辑处理(比如,数据库访问),生成数据模型(model),传递给指定视图解析器(Spring内部已为我们定义好的一系列模板,拿来用即可)解析为相应的视图数据,最后返回客户端响应。

            其实,好比我们最初学习Java Web开发一样,首先要在web.xml文件中配置DispatcherServlet:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     <!-- Spring Dispatcher Servlet-->
     <servlet>
         <servlet-name>SpringDispatcher</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>classpath:config/springDispatcher.xml</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
     </servlet>
     <servlet-mapping>
         <servlet-name>SpringDispatcher</servlet-name>
         <url-pattern>/</url-pattern>
     </servlet-mapping>

        这里配置了名为SpringDispatcher的Servlet,处理所有客户端的请求,contextConfigLocation参数指明了同时要加载的Spring MVC配置信息。 

        既然SpringDispatcher会过滤所有的请求,那如果请求的是静态资源的话,我们这样做就有点得不偿失了。不过不用担心,Spring MVC为我们提供了处理静态资源的解决办法:

        在springDispatcher.xml文件中,引入spring mvc标记,并添加<mvc:resource>标签即可:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?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"
        xsi:schemaLocation="
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd>
        <!-- Handle requests for static resources -->
        <mvc:resources mapping="/resources/**"  location="/resources/"/>
    </beans>

        如上所配置,<mvc:resources>会将所有直接返回以/resources/开始的静态资源请求,而不会通过SpringDispatcher进行处理。 

        DispatcherServlet配置好后,接下来就需要创建我们的控制器类了,Spring MVC里我们可以通过组件扫描来注册我们所写的控制器,自动织入所需的bean:

    1
    2
    3
    4
    5
    6
    7
    8
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd>
     
    <!-- Enable annotation-driven features -->
    <mvc:annotation-driven/>
     
    <!-- Enable component-scan features -->
    <context:component-scan base-package="com.alan"/>

         控制器类如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @Controller
    @RequestMapping("/user")
    public class UserController {
     
        private final UserService userService;
         
        @Autowired
        public UserController(UserService userService) {
            this.userService = userService;
        }
         
        @RequestMapping("/queryAll")
        public String queryAll(@RequestParam("type") int type, Model model) {
            if(type == 1) {
                List<User> users = userService.findAll();
                model.addAttribute("users", users);
            }
            return "UserList";
        }
    }

        通过注解技术,我们可以很方便的将我们的业务类注册给控制器,在初始化时由Spring容器帮我们完成依赖注入。其中@RequestMapping注解则告诉Spring所有以“/user”开始的请求将由UserController来处理,而"/user/queryAll"则交由queryAll方法处理。@RequestParam则会接收URL请求参数,这里为type,并且自动转化为对应的参数类型。Model即为数据模型,由Spring提供,我们可以将处理后的结果数据绑定到Model上,返回Model给指定视图解析器。queryAll方法最后的return "UserList"意思是告诉视图解析器返回哪一个页面。这里我们需要再增加视图解析器的配置到springDsipatcher.xml中:

    1
    2
    3
    4
    5
    6
    <!-- Configure view resolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

        以上XML配置表明,我们使用JstlView视图(支持JSTL),并且返回“/WEB-INF/views/”下面所有以“.jsp”为后缀的文件。本例中,即为“ /WEB-INF/views/UserList.jsp ”。 

        是不是很easy呢?不过,可能有的同学要问了,如果我不想返回页面,而是直接返回字符串或者IO流怎么办。好吧,Spring框架当然也想到了。我们可以在方法上增加@ResponseBody标记以表明直接返回响应内容,而不是转交视图解析器处理,就像下面这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @RequestMapping("/queryAll2")
    @ResponseBody
    public String queryAll2(@RequestParam("type") int type) {
        JSONObject jsonObj = new JSONObject();
        if(type == 2) {
            List<User> users = userService.findAll();
            jsonObj.put("users", users);
        }
        return jsonObj.toString();
    }

        我们即可很轻松的返回字符串数据,比如返回JSON字符串。

        InternalResourceViewResolver通常使用转发的方式返回页面数据。如果我们需要重定向到某个页面,则可以在方法返回的时候增加“redirect:”标记即可:

    1
    return "redirect:/UserList";

        当然,如果需要转发至某个Controller的方法也很方便:

    1
    return "forward:/user/queryAll2?type=2"

        此外,经常使用Struts的同学也比较喜欢表单数据绑定到Model的功能以减轻自己获取所有请求参数的繁琐工作,Spring亦有提供实现。即可通过@ModelAttribute标记获取表单参数(这需要Spring MVC所提供的form tag库的支持):

    1
    2
    3
    4
    5
    6
    7
    8
    @Controller 
    public class HelloWorldController { 
       
        @RequestMapping(value = "/helloWorld", method=RequestMethod.POST) 
        public String helloWorld(@ModelAttribute User user) { 
            return "helloWorld"
        
    }

        好像还少了点什么对不对?是的,我如果要在Controller里获得ServletContext对象呢?别担心,只要我们implements ServletContext即可,这样我们就可以在Controller里获取Servlet上下文,因而什么request、response都不在话下了,这里给出一个上传JPG图片的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    @Controller
    @RequestMapping("/upload")
    public class FileUploadController implements ServletContextAware {
     
        private ServletContext servletContext;
         
        public void setServletContext(ServletContext servletContext) {
            this.servletContext = servletContext;
        }
         
        @RequestMapping("/jpg")
        public String uploadJPG(@RequestParam("image") MultipartFile image, Model model) {
            try {
                if(!image.isEmpty()) {
                    validateImage(image, "image/jpeg");
                    saveImage(image);
                    model.addAttribute("img", "resources/upload" + File.separator + image.getName());
                }
            } catch (UploadImageException e) {
                model.addAttribute("msg", e.getMessage());
                return "uploadError";
            }
            return "images";
        }
     
        private void saveImage(MultipartFile image) throws UploadImageException {
            String name = image.getName();
            try {
                File file = new File(servletContext.getRealPath("/resources/upload") + File.separator + name);
                FileUtils.writeByteArrayToFile(file, image.getBytes());
            } catch (IOException e) {
                throw new UploadImageException("保存图片出错!");
            }
             
        }
     
        private void validateImage(MultipartFile image, String type) throws UploadImageException {
            if(!image.getContentType().equals(type)) {
                throw new UploadImageException("只接受JPG格式的文件!");
            }
        }
     
    }

        还有,还有,记得我们经常会用到Session来保存一些共享数据,Spring MVC里可以在Controller上加上@SessionAttributes标记来完成这个功能: 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Controller
    @RequestMapping("/user")
    @SessionAttributes("user")
    public class UserController {
     
        private final UserService userService;
         
        @Autowired
        public UserController(UserService userService) {
            this.userService = userService;
        }
            /**
        .......
            */
    }

        

    转自:http://my.oschina.net/moson/blog/146808#

    那一汪清眸,那一瞥青涩的目光,那一段青春岁月。我一直在寻找,寻找一个属于我的婆娑世界,寻找那一年的自己,再也回不去了……
  • 相关阅读:
    [Leetcode][动态规划] 零钱兑换
    [Linux][函数]flock函数的用法
    [Leetcode][动态规划] 买卖股票的最佳时机IV
    [C++] 类的设计(2)——拷贝控制(1)
    [C++] C++中的常用库
    Python 爬虫学习笔记2
    Python 爬虫学习笔记1
    Tableau学习笔记:join
    可视化文摘:multifaceted data and story
    可视化学习笔记8:一般设计技巧
  • 原文地址:https://www.cnblogs.com/feiger/p/3923812.html
Copyright © 2011-2022 走看看