SpringMVC原理

一、MVC设计模式:

作用:用来进行分层的结构,这样代码分离结构清晰,各层代码,各司其职,易于开发大型项目。

MVC(Model模型、View视图、Control控制层),将软件进行分层达到松耦合的效果。

在MVC设计思想中要求一个符合MVC设计思想的软件应该保证上面这三部分相互独立,互不干扰,每一个部分只负责自己擅长的部分。如果某一个模块发生变化,应该尽量做到不影响其他两个模块。提高代码的可读性,实现程序间的松耦合、提高代码复用性。

SpringMVC就是基于MVC设计模式来实现的。
我们的POJO/domain就是Model层,我们的JSP就是视图层,我们的Controller就是控制层。
现在主流基于SSM三大框架开发都是在MVC上继续演化,又分为持久层DAO,业务层Servie,控制层Controller。持久层用来和数据库读写ORM,业务层用来处理复杂的业务逻辑,控制层用来处理MVC的控制。

二、SpringMVC工作原理:

SpringMVC原理

Springmvc的五大组件:DispatcherServlet(前端控制器)、HandlerMapping(映射处理器)、controller(控制器)、ModelAndView、ViewReslover(视图解释器)

      当客户端发起请求,首先经过DispatcherServlet(前端控制器),DispatcherServlet将请求分发给HandlerMapping(映射处理器),通过HandlerMapping 根据指定的controller名字,找到对应的Controller组件处理请求,(->service->mapper )那么将得到的数据绑定在ModelAndView组件中,最后通过ViewReslover(视图解析器) 解析数据与视图 渲染到页面。

说明:

当服务器启动的时候,首先会去加载web.xml文件(可以理解问web应用程序的入口)

凡是放在WEN-INF文件夹下面的资源都是受保护的,不能通过浏览器直接访问,可以通过转发或者重定向进行访问。

三、服务器与控制层的传参方式:

1、路径传参:

    //客户端 向 服务端传参
    /*
    在浏览器地址栏使用路劲传参
    localhost:8060/t1?name='lisi'&age=10
    name和age要一致
     */
    @RequestMapping("/t1")
    public void test1(String name,Integer age){
        /*String str = "123";
        Integer strInt = Integer.parseInt(str);强制类型转换*/
        System.out.println(name);
        System.out.println(age);
    }

2、使用HttpServletRequest 请求对象 获取参数

    /*
    * 使用HttpServletRequest 请求对象 获取参数
    * 使用HttpServletRequest和HttpServletResponse时需要
    * */
    @RequestMapping("/t2")
    public void test2(HttpServletRequest request){
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        System.out.println(name);
        System.out.println(age);
    }

3、使用JSP页面的表单传参:

    //表单传参 使用表单的name属性值  作为参数传到服务端
    //服务端的参数名和表单的name 属性值一致即可
    //浏览器传入到服务器的参数都是String类型的
    //但是对于数字类型的字符串,在服务端可以使用Integer来接收。
    //因为SpringMVC框架自动完成类型转换

    /*
    * get请求和post请求的区别:
    * get请求会将表单的数据暴露在浏览器的地址栏,对于重要的数据是不安全的
    * post请求是将表单数据封装在请求行里面,数据比较安全
    * get请求提交的数据量比post的要小
    * 表单请求默认是get请求
    * */
    @RequestMapping("/doLogin")
    public void doLogin(HttpServletRequest request){
        String username = request.getParameter("username");
        String  pwd = request.getParameter("pwd");
        System.out.println(username);
        System.out.println(pwd);
    }

JSP代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>注册</h1>
<form action="/doReg" method="post">
    <p>
        用户名:<input type="text" name="username" placeholder="请输入用户名">
    </p>
    <p>
        密码:<input type="password" name="pwd" placeholder="请输入密码">
    </p>
    <p>
        联系方式:<input type="text" name="tel" placeholder="请输入联系方式">
    </p>
    <p>
        <input type="submit">
    </p>
</form>
</body>
</html>

4、表单封装实体类对象向服务端传参:

    /*
    * 表单封装实体对象 向服务端传参
    * 当表单的name属性值与实体类的属性一致的时候,
    * SpringMVC会将表单数据自动封装到实体类中,
    * 那么,可以在服务端直接传入对象即可
    * */

    //当在浏览器输入localhost:8060/reg-->reg.jsp
    /*
    * 转发和重定向:解决页面跳转的问题
    * 转发:request.getRequestDispatcher("去哪个页面").forward(request,response);
    * 重定向:response.sendRedirect("去哪个页面或路径");
    * 区别:
    * 转发只能在项目内部进行,而重定向可以跳转到项目外的任意页面
    * 转发是一次请求,重定向是两个请求
    * 转发地址栏的请求路径不会变,而重定向的地址栏会发生改变
    * */
    @RequestMapping("/reg")
    public  String toReg(){
        return "reg";
        //return "redirect:reg";默认是转发,加了redirect就是重定向
    }

    @RequestMapping("/doReg")
    public void doReg(User user){
        System.out.println(user.toString());
    }

5、利用Model获取浏览器参数:

    //跳转到t1.jsp
    @RequestMapping("/toT1")
    public String toT1page(){
        return "t1";
    }
    //接收toOrderDate请求
    @RequestMapping("/toOrderDate")
    public String toOrderDate(String name, Model model){
        //目的:将name值绑定到t2.jsp页面
        //使用model对象绑定数据
        model.addAttribute("username",name);
        return "t2";
    }

t1.jsp代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<a href="/toOrderDate?name='旺财'"> 订单中心</a>

</body>
</html>

t2.jsp代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

订单用户名:${username}
<br>
工资是:${salry}
<br>
名字是:${name}
<br>
年龄是:${age}
<br>
地址是:${address}
<br>
电话是:${tel}
<br>
email是:${email}
</body>
</html>

6、使用HttpServletRequest 对象绑定数据:

    //使用HttpServletRequest 对象绑定数据
    @RequestMapping("/t3")
    public String t3(HttpServletRequest request){
        request.setAttribute("salry",2000);
        request.setAttribute("name","旺财");
        return "t2";
    }

7、使用ModelAndView对象绑定数据

    //使用ModelAndView对象绑定数据
    @RequestMapping("/t4")
    public ModelAndView t4(ModelAndView modelAndView){
        //ModelAndView绑定数据
        modelAndView.addObject("age",100);
        //ModeAndView绑定视图
        modelAndView.setViewName("t2");
        return modelAndView;
    }

8、使用HttpSession对象绑定数据

    //使用HttpSession对象绑定数据
    @RequestMapping("/t5")
    public String t5(HttpSession session){
        //使用session绑定数据
        /*
        * session和cookie区别:
        * 记录用户的状态(数据)
        * session将数据绑定在数据端,由session绑定的数据可以实现数据共享
        * cookie将数据保存在客户端(浏览器中,不安全)
        * */
        session.setAttribute("address","湛江市");
        return "t2";
    }

9、使用ServletContext绑定数据:

    //ServletContext绑定数据
    @RequestMapping("/t6")
    public String t6(HttpServletRequest request){
        //使用请求对象request获取ServletContext对象
        ServletContext context = request.getServletContext();
        //使用ServletContext绑定数据
        context.setAttribute("tel","123597648");
        return "t2";
    }

10、使用HttpServletResponse响应对象:

    //使用HttpServletResponse响应对象
    @RequestMapping("/t7")
    public void t7(HttpServletResponse response) throws IOException {
        //告诉浏览器输出内容以及编码格式
        response.setContentType("text/html;charset=utf-8");
        //通过HttpServletResponse
        PrintWriter writer = response.getWriter();
        //使用PrintWriter写出内容
        writer.println("服务器正忙,请稍后重试!");
        writer.close();
    }

11、将方法返回的数据转成JSON字符串:

    @RequestMapping("/t8")
    @ResponseBody//将方法返回的数据转成JSON字符串
    public User t8(){
        //将数据封装到User对象中
        User user = new User();
        user.setUsername("李四");
        user.setPwd("123456");
        user.setTel("18219478028");
        /*最终返回的JSON串格式
        * "{"username":"李四","pwd"="123456","tel"="18219478028"}"
        * */

        return user;
    }

12、将List集合转成JSON字符串返回给浏览器:

    //将List集合转成JSON字符串返回给浏览器
    @RequestMapping("/t10")
    @ResponseBody
    public List<User> t10(){
        List<User> list = new ArrayList<>();
        //向集合添加元素
        User user = new User();
        user.setUsername("旺财");
        user.setPwd("125312");
        user.setTel("415664855");
        list.add(user);
        User user1 = new User();
        user1.setUsername("小花");
        user1.setPwd("125112");
        user1.setTel("4156611222");
        list.add(user1);
        return list;
    }

13、将Map集合转成JSON字符串: 

    //将Map集合转成JSON字符串
    @RequestMapping("/t11")
    @ResponseBody
    public Map<String,Object> t11(){
        Map<String,Object> map = new HashMap<>();
        //向map集合添加数据
        map.put("state",200);
        map.put("msg","手机验证码已发送");
        return map;
    }

补充:json(前后端交互时常常使用的一种数据交换格式)

四、注解 

(1)什么是注解

  1. @ 是java注解,即annotation。
  2. 可以理解为插件,是代码级别的插件,在类的方法上写:@XXX,就是在代码上插入了一个插件。

     3.Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起            到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用

(2)什么时候用?

         我们一般用不到自定义注解,框架为我们提供了很多注解,只要在代码里写明你需要的注解就可以了。只有在自己动手写类似于Hibernate框架的时候,会用到自定义注解。这也是为什么我们一般用不到java反射,因为只有在使用自定义注解的时候,才会用到java反射,而我们平时连自定义注解都用不到。

(3)​​​​​​​XML配置方式和注解方式差异

  1. Controller无需在xml中声明,加个@Controller注解即可,这样再多的Controller也不怕了。只需xml中配置一次注解驱动<mvc:annotation-driven />
  2. 原来要在xml配置bean来指明映射关系,现在只加注解@RequestMapping无需xml配置
  3. 无需返回ModelAndView对象,直接返回逻辑名即可
  4. 参数自动封装,自动类型转换

(4)常用的注解:

@Controller 标识是一个Controller,Spring包扫描创建实例

@RequestMapping 请求后的映射路径

@PathVariable 标识接收单个参数

@RespringBody 返回对象利用jackson工具类转换为json字符串

@RequestParam 参数名和请求参数名称不同时使用,可以设置默认值

上一篇:采访了900个一线大厂程序员,成就史上最强Spring常用7大注解【经典总结】


下一篇:SpringMVC(二)@RequestMapping注解