JavaWeb笔记(28)-SpringMVC基础

  1. SpringMVC:是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架
1. SpringMVC优势:
    a. 模块式开发:
        前端控制器(DispatcherServlet) 
        处理器映射器(HandlerMapping) 
        处理器适配器(HandlerAdapter) 
        视图解析器(ViewResolver) 
        处理器或页面控制器(Controller) 
        验证器( Validator) 
        命令对象(Command 请求参数绑定到的对象就叫命令对象) 
        表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)
2. SpringMVC和Struts2对比:
    a. 共同点:
        它们都是表现层框架,都是基于MVC模型编写的。 
        它们的底层都离不开原始ServletAPI。 
        它们处理请求的机制都是一个核心控制器。Struts2核心控制器为一个Filter,SpringMVC核心控制器为一个Servlet
    b. 区别:
        Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter 
        Spring MVC 是基于方法设计的,而Struts2是基于类,Struts2每次执行都会创建一个动作类。
            所以Spring MVC 会稍微比 Struts2 快些。 
        Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便
        Struts2 的OGNL 表达式使页面的开发效率相比Spring MVC 更高些,但执行效率并没有比JSTL提升,
            尤其是struts2的表单标签,远没有html执行效率高。
  1. 使用SpringMVC框架
1. 构建一个maven的webapp项目
2. 完善目录结构
3. 导入相关jar包
    spring-context.5.0.2.RELEASE.jar
    spring-web.5.0.2.RELEASE.jar
    spring-webmvc.5.0.2.RELEASE.jar
    servlet-api.jar
    jsp-api.jar
4. 配置一个前端控制器(本质为一个servlet)
    /WEB-INF/web.xml
    DispatcherServlet类,拦截路径为/,表示所以请求都会经过该控制器
    <!-- SpringMVC的核心控制器 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servletclass>
        <!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <!-- 配置servlet启动时加载对象 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
5. 环境搭建,创建配置文件
    /resource/springmvc.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
        
        <!-- 配置spring创建容器时要扫描的包 -->
        <context:component-scan base-package="cn.mysilent"></context:component-scan>
        
        <!-- 配置视图解析器 -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置视图解析器搜索文件的路径-->
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <!--配置视图解析器搜索指定后缀的文件-->
            <property name="suffix" value=".jsp"></property>
        </bean>
        
        <!--
            配置spring开启注解mvc的支持
            <mvc:annotation-driven></mvc:annotation-driven>
        -->
    </beans>
6. 定义控制类,添加注解@Controller注解表示为控制器类
    @Controller
    public class HelloController {
        /**
        * 接收请求
        * @return
        */
        @RequestMapping(path="/hello")
        public String sayHello() {
            System.out.println("Hello SpringMVC!!");
            return "success";
        }
    }
7. 使用@RequestMapping注解的path属性配置方法的访问路径
8. 创建/WEB-INF/pages/success.jsp文件
  1. SpringMVC工作流程
1. 启动服务器,加载配置文件:
    a. DispatcherServlet对象被创建
    b. springmvc.xml文件被加载
    c. 自定义控制类的对象被创建
2. 浏览器发送请求
    a. 请求到达DispatcherServlet(前端控制器)
    b. DispatcherServlet请求查找Handler,将请求资源路径交由HandlerMapping(处理器映射器)
    c. HandlerMapping由访问路径来匹配@RequestMapping中配置的资源位置
    d. HandlerMapping返回一个执行链HandlerExecutionChain给前端控制器,该链中包含了请求的执行顺序
    e. DispatcherServlet由执行链请求HandlerAdapter(处理器适配器)来适配执行的各方法的Handler
    f. Handler(Controller处理器)执行对应的方法后返回ModelAndView对象给HandlerAdapter
    g. HandlerAdapter再将ModelAndView对象返回给DispatcherServlet
    h. DispatcherServlet由ModelAndView请求ViewResolver(视图解析器)
    i. ViewResolver(视图解析器)解析后返回View给DispatcherServlet
    j. View对象到DispatcherServlet后,由不同资源加载到request域中
    k. DispatcherServlet将response返回给浏览器
3. 处理器映射器、处理器适配器、视图解析器配置:
    在SpringMVC的各个组件中,处理器映射器、处理器适配器、视图解析器称为SpringMVC的三大组件。
    在SpringMVC.xml配置文件中使用<mvc:annotation-driven>开启注解功能时将自动进行处理器和适配器的配置。
    手动在springmvc.xml中配置:
        <!-- 上面的标签mvc:annotation-driven相当于如下配置--> 
        <!-- Begin --> 
        <!-- HandlerMapping --> 
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
        </bean> 
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> 
        
        <!-- HandlerAdapter --> 
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        </bean> 
        <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean> 
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> 
        
        <!-- HadnlerExceptionResolvers --> 
        <bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
        </bean> 
        <bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver"></bean>
        <bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"></bean> 
        <!-- End -->
  1. 注解配置
1. @RequestMapping注解:
    a. 属性:
        value:用于指定请求的URL。它和path属性的作用是一样的。 
        method:用于指定请求的方式。
        params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的key和value必须和配置的一模一样。
        例如:params = {"accountName"},表示请求参数必须有accountName 
                  params = {"moeny!100"},表示请求参数中money不能是100。
        headers:用于指定限制请求消息头的条件。
  1. 请求参数的获取与绑定
1. 少量数据的获取与封装
    a. 在Controller控制类的成员方法参数列表中带上与请求参数相同键名的参数名
        SpringMVC会自动将该键对应的值赋值给参数列表中的同名变量
2. 数据封装到JavaBean中
    a. Bean对象实现Serializable序列化接口
    b. Bean对象的成员方法的属性名必须与提交数据的键名一一对应(利用反射来获取set方法来封装数据)
    c. 在Controller控制类的成员方法的参数列表中带上Bean对象的变量
        SpringMVC会自动将对于的键值封装到Bean对象对应的属性上去
3. 特殊数据类型的封装
    a. Bean对象内含有其他Bean对象的引用
        在提交的表单中,其name属性值应为其他Bean对象.其他Bean对象内部的属性名
        如Account中包含User对象的引用,则可以使用user.uname封装到User对象引用的uname属性
    b. List/Map数据类型的封装
        * List数据的封装
        在提交的表单中,其name属性值应为List变量名[索引值],如果List中为Bean对象,可以List变量名[索引].属性名
        如Account中包含List<User> list的成员变量,可以使用list[0].uname封装uname键的值到第一个User对象的uname中
        * Map数据的封装
        在提交的表单中,其name属性值应为Map变量名['键'],如果Map值中为Bean对象,可以Map变量名['键'].属性名
        如Account中包含Map(String,User)的成员变量,可以使用map("user").uname封装uname键的值到map键"user"对应的User的uname中
4. 解决中文乱码问题:
    a. 在web.xml中配置spring提供的过滤器
        <!-- 配置过滤器,解决中文乱码的问题 -->
        <filter>
            <filter-name>characterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filterclass>
            <!-- 指定字符集 -->
            <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>/*
        
5. 数据类型的转换:
    a. 页面获取的数据都为字符串,大部分数据类型转换有spring框架完成
        String -> Integer/Double/...
    b. 自定义类型的数据转化,将字符串转化为需要的数据类型和格式(如Date类型)
        yyyy/MM/dd格式可以自动转化为Date类型
        yyyy-MM-dd自定义格式无法转化
        解决方法:
            1. 自定义一个转化器类,实现Converter接口,实现接口中包含的T convert(S source)抽象方法
                source即为请求传入的字符串
                public class StringToDateConverter implements Converter{
                    //进行类型转换的方法
                    public Date convert(String source) {
                        // 判断
                        if(source == null) {
                            throw new RuntimeException("参数不能为空");
                        }
                        try {
                            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                            // 解析字符串
                            Date date = df.parse(source);
                            return date;
                        } catch (Exception e) {
                            throw new RuntimeException("类型转换错误");
                        }
                    }
                }
            2. web.xml注册自定义的类型转化器
                
                
                    
                        
                            
                        
                    
                
                
                
                
6. 获取原生Servlet的对象
    * 在方法的参数中传递HttpSerlvetRequest request可以获取到request对象
    * 在方法的参数中传递HttpSerlvetResponse response可以获取到response对象
    * 通过request.getSession()可以获取到session对象
    * 通过session.getServletContext()可以获取到servletContext对象
  1. SpringMVC常用注解
1. RequestParam注解:
    a. 用于将数据封装到与键名不同的变量上
    b. 属性:
        value:请求参数中的名称
        required:请求参数中是否必须提供此参数,默认值是true,必须提供
    c. 使用:
        @RequestMapping(path="/hello")
        public String sayHello(@RequestParam(value="username",required=false)String name) {
            /*
                添加注解后,会将该请求中键为username的值赋给name变量
                required为false表示该参数不是一定要在请求参数中存在
            */
            System.out.println("aaaa");
            System.out.println(name);
            return "success";
        }
2. @RequestBody注解:
    a. 用于获取请求体的内容(key1=value1&key2=value2...格式字符串)(注意:get方法不可以)
    b. 属性:
        required:是否必须有请求体,默认值是true
    c. 使用:更多用于获取json格式数据
        @RequestMapping(path="/hello")
        public String sayHello(@RequestBody String body) {
            /*
                添加注解后,会将请求体的数据复制给body变量
            */
            System.out.println("aaaa");
            System.out.println(body);
            return "success";
        }
3. @PathVariable注解:
    a. 拥有绑定url中的占位符的。例如:url中有/delete/{id}{id}就是占位符
    b. 属性:
        value:指定url中的占位符名称
    c. 使用:
        /tset.jsp
        <a href="user/hello/1">入门案例</a>
        /TestController.java
        /**
        * 接收请求
        * @return
        */
        @RequestMapping(path="/hello/{sid}")
        public String sayHello(@PathVariable(value="sid") String id) {
            System.out.println(id);
            return "success";
        }
3. @RequestHeader注解
    a. 用于获取请求消息头
    b. 属性:
        value:设置所需要的消息头中指定键的值
        required:是否必须要有此头
    c. 一般不使用该注解
4. @CookieVaule注解:
    a. 用于获取指定cookie的名称的值
    b. 属性:
        value:cookie的名称
    c. 使用:
        @RequestMapping(path="/hello")
        public String sayHello(@CookieValue(value="JSESSIONID") String cookieValue) {
            System.out.println(cookieValue);
            return "success";
        }
5. @ModelAttribute注解:
    a. 作用:
        1. 出现在方法上:表示当前方法会在控制器方法执行前线执行。
        2. 出现在参数上:获取指定的数据给参数赋值。
    b. 属性:
        value:获取指定数据赋值给参数
    c. 使用:
        @ModelAttribute
        public void showUser(String name,Map<String, User> map) {
            System.out.println("showUser执行了...");
            // 模拟从数据库中查询对象
            User user = new User();
            user.setName("哈哈");
            user.setPassword("123");
            user.setMoney(100d);
            map.put("abc", user);
        }
        @RequestMapping(path="/updateUser")
        public String updateUser(@ModelAttribute(value="abc") User user) {
            System.out.println(user);
            return "success";
        }
6. @SessionAttributes注解:
    a. 用于多次执行控制器方法间的参数共享
    b. 属性:
        value:指定存入属性的名称
        name:
    c. 使用:
        1. 使用Model对象存储request域中
            @RequestMapping(path="/save")
            public String save(Model model) {
                System.out.println("向request域中保存数据");
                //底层会存储到request域对象中
                model.addAttribute("username", "root");
                model.addAttribute("password", "123");
                model.addAttribute("age", 20);
                return "success";
            }
        2. 使用@SessionAttributes作用在类上,使得原本存入request域对象的数据同时存储session域对象中
            @Controller
            @RequestMapping(path="/user")
            @SessionAttributes(value= {"username","password","age"},types={String.class,Integer.class}) 
            // 把数据存入到session域对象中
            public class HelloController {
                //向request中存入值
                @RequestMapping(path="/save")
                public String save(Model model) {
                    System.out.println("向request域中保存数据");
                    model.addAttribute("username", "root");
                    model.addAttribute("password", "123");
                    model.addAttribute("age", 20);
                    return "success";
                }
                //从session中获取值
                @RequestMapping(path="/find")
                public String find(ModelMap modelMap) {
                    String username = (String) modelMap.get("username");
                    String password = (String) modelMap.get("password");
                    Integer age = (Integer) modelMap.get("age");
                    System.out.println(username + " : "+password +" : "+age);
                    return "success";
                }
                //清除值
                @RequestMapping(path="/delete")
                public String delete(SessionStatus status) {
                    status.setComplete();
                    return "success";
                }
            }

你可能感兴趣的:(JavaWeb笔记)