Spring学习笔记(九)——Spring MVC篇


前提

这篇博文是这套Spring学习笔记的第九篇——Spring MVC篇,主要内容包括Spring MVC的基础知识和应用。如果需要了解有关Spring的综述信息或博文的索引信息,请移步:
《综述篇》


什么是MVC?

MVC是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。[1]

对于Model、View和Controller,我的理解是:
①Model: 模型主要用来存储数据,类似于Android中的Bundle,可以简单理解为一张<String, Object> 类型的表;
②View: 视图重定义了需要显示的元素,比如一张JSP页面或者图片、PDF等用于显示的资源;
③Controller: 控制器可以为请求找到相应的处理者,管理后端与前端的交互。


DispatcherServlet请求调度器

《配置篇》中,我们曾在web.xml中配置了DispatcherServlet。为了便于讲解,再次列出代码:

    <servlet>
        <servlet-name>dispatcher</servlet-name>  <!-- 注释① -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>  <!-- 注释② -->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>  <!-- 注释③ -->
    </servlet>

    <servlet-mapping>  <!-- 注释④ -->
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

注释:
①这里定义了Servlet的名字——dispatcher,可以根据喜好自定;
②这里定义了一个初始化参数——contextConfigLocation,即上下文配置地址,值指向了MVC的配置文件spring-mvc.xml;
③表示web容器在启动时就加载该Servlet,标签中的数值是优先级,数值越小优先级越大;
④Servlet映射,指定对dispatcher进行映射,映射模式是/,即接受任意请求。这里需要深入解释一下,/会将所有的请求放进来,后面在Controller中,我们需要对请求进行过滤,不符合要求的请求仍无法得到响应。

需要注意的是,一个web.xml中可以配置多个DispatcherServlet,通过不同的<servlet-mapping>设置,让它们处理不同的请求。


Controller

同样为了便于讲解,我们再次列出RequestController和UserController:

RequestController

@Controller  //注释①
public class RequestController {

    @RequestMapping("")  //注释②
    public ModelAndView dispatch(HttpServletRequest request, HttpServletResponse response) {
        String RequestType = request.getParameter("RequestType");  //注释③
        return new ModelAndView("forward:" + RequestType);  //注释④
    }
}

注释:
@Controller注解标识这个类为控制器,可以被Spring容器扫描到以执行控制器的功能;
@RequestMappring标识下方的函数用来处理满足括号中地址映射规则的请求。如""表示接受任何请求;
③从请求参数中取出"RequestType"请求类型,这个参数是客户端在发送请求的时候传来的;
④通过"RequestType"转发请求,如果RequestType="Login",该请求将被转发给能处理"/Login"的函数。

UserController

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("Login")  //注释①
    public void handleLoginRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {  //注释②
        try (PrintWriter out = response.getWriter()) {
            //获得请求中传来的用户名和密码
            String username = request.getParameter("UserName").trim();
            String password = request.getParameter("Password").trim();
            
            //密码验证结果
            boolean result = userService.verifyLogin(username, password);
            out.write(String.valueOf(result));  //注释③
        }
    }
}

注释:
①这个请求映射的映射规则是"Login",他就可以处理地址为/Login的请求。但不仅于此,因为映射规则支持通配符,因此"Login"对应的实际规则是/Login + /Login.* + /Login/
②这个函数是请求处理函数:
——当返回值为String或ModelAndView类型时,表示请求转发或向浏览器指定需要跳转和渲染的页面;如果仅仅像其他非浏览器客户端返回数据,则用void。
——函数的名字可以根据喜好任意取;
③向客户端打印一个简单的登录验证结果字符串。


请求处理函数中的参数绑定

在请求处理函数的函数签名(即函数头,一个函数在{前的部分)中,我们可以使用多种注解绑定参数以达到简化代码的目的。

@RequestParam

在上述RequestController中,我们手动取了参数RequestType,通过@RequestParam绑定请求中的参数,就可以省一些代码,让Spring容器帮我们自动从请求中取出来绑定到函数的参数中。

@Controller
public class RequestController {

    @RequestMapping("")
    public ModelAndView dispatch(@RequestParam("RequestType") String requestType) {  //注释
        return new ModelAndView("forward:" + requestType);
    }
}

注释:这里删除了request和response,通过@RequestParam注解定义了一个参数绑定,意为从请求参数中取出"RequestType"的值,赋给参数requestType.

@CookieValue

@CookieValue可以绑定请求中的Cookie值

@RequestMapping("")
    public ModelAndView dispatch(@CookieValue("sessionId") String sessionId) {  
        ......
    }

@RequestHeader

@RequestHeader可以绑定请求头中的值

@RequestMapping("")
    public ModelAndView dispatch(@RequestHeader("Accept-Encoding") String acceptEncoding) {  
        ......
    }

POJO自动填充

当我们的请求参数中包含与POJO类对应的属性时,可以使用这种方法将参数绑定到一个POJO类的对象上,如:
请求URL的参数部分

/?id=1001&username=Jackson&password=1234567890

请求处理函数

@RequestMapping("")
    public ModelAndView dispatch(User user) {  
        ......
    }

解释:此时,请求参数将会被自动填充到user对象中。

Servlet原生API

其实我们之前的例子已经用到了:

    RequestMapping("")  
    public ModelAndView dispatch(HttpServletRequest request, HttpServletResponse response) {
        ......
    }

解释:这里的HttpServletRequestHttpServletResponse就属于Servlet原生API,我们需要用到这类参数的时候,直接在参数里面声明就可以用了,Spring IoC容器会自动为我们注入相应的依赖。

IO对象

通过IO对象可以读取请求中的数据,也可以输出数据到响应中。

    RequestMapping("")  
    public ModelAndView dispatch(InputStream is, OutputStream os) {
        ......
    }

处理Model中的数据

上文中我们已经定义了Model,它主要用于存储数据。如何在各种情形下都可以读写Model里的数据,是Spring MVC必须解决的问题。

ModelAndView

当一个Controller中的请求处理函数的返回值为ModelAndView时,它包含了模型和视图的信息。
可以用于向模型中添加数据的函数有:
ModelAndView addObject(String attributeName, Object attributeValue)
ModelAndView addAllObjects(Map<String, ?> modelMap)

可以用来设置视图的函数有:
void setView(View view)
void setViewName(String viewName)

@ModelAttribute

需要将方法的参数写入Model时,可以使用@ModelAttribute

    @RequestMapping("/Login")
    public ModelAndView handleLoginRequest(@ModelAttribute("user") User user) {  
        ......
    }

也可以给函数冠以@ModelAttribute注解,这样,函数的返回值将被写入Model中。

    @ModelAttribute("user")
    public User getUser() { 
        User user = new User(); 
        ......
        return user;
    }

ModelMap

上文中说过,Model实际可以理解为一个Map<String, Object>表,我们可以通过ModelMap参数来读写Model中的数据。

    @RequestMapping("")
    public ModelAndView dispatcher(ModelMap modelMap) { 
        modelMap.addAttribute("sessionId", "1ESD8C26D1357F23F39D0");
        User user = (User)modelMap.get("user");
        ......
    }

@SessionAttributes

如果希望在多个请求中共享一些数据,可以使用@SessionAttribute注解

@Controller
@SessionAttributes("user")  //注释①
public class UserController {

    @RequestMapping("/Login")
    public ModelAndView handleLoginRequest(@ModelAttribute("user") User user) {  //注释②
        ......
    }
}

注释:①处标注了@SessionAttribute注解,Controller会自动把②处的user对象写入Session中。


后记

Spring框架的基础知识就到这了,如果学到了其他的进阶知识,我会续写新的博文来分享。


  1. 摘自百度百科——MVC ↩︎

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMplementist

你的鼓励,是我继续写文章的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值