SpringMVC开发流程

作者: CoderZS | 来源:发表于2017-08-18 02:50 被阅读248次

    要点

    • SpringMVC简介
    • 搭建环境入门程序
    • 全注解
      • J2EE三层使用的注解
      • 使用步骤
      • 对静态资源的处理
    • 传参方式
      • 原始方式request.getParameter()
      • 方法形参与前台参数同名
      • 对象传参
      • 地址栏传参
      • 中文乱码处理
    • 传值方式
      • 通过request.setAttribute()
      • addObject()的方式
      • 直接返回对象
      • 配置视图解析器
      • forward方式
      • redirect方式
      • 通过Model方式
    • 文件上传/下载
      • 文件上传
      • 配置文件上传解析器
      • 上传方法参数MultipartFile
      • 文件下载
    • 拦截器
      • preHandle方法
      • postHandle方法
      • afterCompletion方法
    • 返回JSON格式数据
    • 日期处理
      • 前台往后台传参
      • 后台往前台回显值(JSON)

    1.SpringMVC简介

    SpringMVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1,Struts2等,在这里暂时就不分析SpringMVC与Struts2的比较了.

    2.搭建环境入门程序

    需要的jar包(需要什么包添加什么包就不一下全部添加进去了 )
    1)添加Spring的核心包


    图片.png
    com.springsource.org.apache.commons.logging-1.1.1.jar
    spring-beans-4.0.0.RELEASE.jar
    spring-context-4.0.0.RELEASE.jar
    spring-core-4.0.0.RELEASE.jar
    spring-expression-4.0.0.RELEASE.jar
    

    添加web.xml文件,使用3.0或以上的版本,3.0以下的对el表达式不是很智能,需要配置isELIgnored="false"
    配置前端控制器

     <!--前端控制器/请求分发器-->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:application-mvc.xml</param-value>
        </init-param>
        <!--设置优先级-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    图片.png

    创建自定义的Controller类,实现Controller接口.复写handleRequest方法

    public class HelloWorldController implements Controller {
    
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
      //创建自定义Controller类,实现contrller接口复写handleRequest方法
       request.setAttribute("msg","hello!");
       request.getRequestDispatcher("/hello.jsp").forward(request,response);
        return null;
    }
    }
    
    图片.png

    配置Controller的映射路径,并且交给spring来管理bean

     <!--name请求的映射路径 class:该路径处理类-->
    <bean name="/index" class="com.jd.controller.HelloWorldController"></bean>
    

    图片.png

    让框架去找我们自定义的文件名与路径

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:application-mvc.xml</param-value>
        </init-param>
    
    图片.png

    第一次访问的时候才去加载框架
    如果类很多,那么第一次访问就会很慢

     <!--设置优先级-->
     <load-on-startup>1</load-on-startup>
    

    3.使用注解的方式

    1.在类打上@Controller注解
    2.在方法上添加@RequestMapping注解
    3.在springmvc的配置文件上开启注解扫描

    public class EmployeeController  {
    @RequestMapping("/employee")
    public void employee(HttpServletRequest requst, HttpServletResponse response) throws Exception {
        //方法中需要什么对象就写到形参上
        requst.setAttribute("msg","employee!!!!!!!!");
        requst.getRequestDispatcher("/hello.jsp").forward(requst,response);
    }
    
    图片.png

    必须开启注解扫描

    <!--开启注解扫描-->
    <context:component-scan base-package="com.jd.controller"></context:component-scan>
    

    @RequestMapping可以打在类上也可以打在方法上
    如果是打在类上,必须先加类上的映射,再加方法的映射

    图片.png

    4.静态资源处理

    1./和/的区别
    /: 会匹配到url路径(/index),静态资源(
    .html,.js等),但是不会匹配到.jsp
    /: 会匹配到url路径(/index),静态资源(.html,.js等),也会匹配到.jsp

    2.为什么springmvc不能使用/*
    Struts2里面是有自定义标签 s:form,jsp文件必须要交有struts2来解析, 所以才会用到/*
    SpringMVC是没有自定义标签的,也不能处理jsp文件,所以jsp文件必须交回tomcat来处理,所以才会用/,不过滤jsp文件

    3.springmvc匹配到静态资源的时候出现的重定向错误问题
    当我们在浏览器访问http://localhost/dept.html,此时的dept.html路径就会被当做url的映射路径来匹配
    就会去找@RequestMapping有没有匹配到的路径,如果有的话就把dept.html当做url路径来访问(/dept.???) ?是不会加进去匹配的
    也就是说访问dept.html时,只要有dept的路径就可以匹配到

    解决方案:
    方案 1 交由tomcat来处理,tomcat中的default本来就是处理静态资源的

    图片.png

    方案2. 配置springmvc处理静态资源(先匹配url是否有相同的路径,如果有就交由方法处理,如果没有才当做静态资源处理)(推荐使用)

     <!--springMVC的静态资源处理配置-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>
    
    图片.png

    5.前台往后台传参的方式

    @Controller
    public class ParamController {
    
    @RequestMapping("/login")
      public void login(HttpServletRequest request){
    // 1.原始方式 使用request来获取参数
     System.out.println(request.getParameter("username"));
     System.out.println(request.getParameter("password"));
    }
    

    2.使用同名匹配的方式

    @RequestMapping("/login")
    public void login(String username,String password){
    System.out.println(("username"));
    System.out.println(("password"));
    }
    

    // 3.使用对象的方式

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

    //4.地址栏传参

     @RequestMapping("/delete/{id}")
     public void delete(@PathVariable("id") Long id){
     System.out.print(id);
     }
    
    图片.png

    6.解决中文乱码问题(post)

    <!--编码过滤器 只对post请求有效-->
    <filter>
        <filter-name>characterEncoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>endoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    图片.png

    7.后台往前台传值

    //后台往前台传值
    public class ValueController {
    //1.使用原始方式传值
    @RequestMapping("/value")
    public void value(HttpServletRequest requst, HttpServletResponse response) throws Exception {
        //方法中需要什么对象就写到形参上
        requst.setAttribute("msg", "value!!!!!!!!");
        requst.getRequestDispatcher("/hello.jsp").forward(requst, response);
    }
    
    //2.使用ModelAndView对象
    @RequestMapping("value1")
    public ModelAndView value() throws Exception {
        ModelAndView mv = new ModelAndView();
        //设置属性
        mv.addObject("name", "CoderZS");
        mv.addObject("password", "123");
        User user = new User("zhangsan", "1234");
        mv.addObject("user", user);
        //mv.addObject(user);
        mv.addObject("maYun");//设置默认key为当前对象类型(小写开头)
        mv.addObject("hahaha");//后面设置相同类型的值会覆盖之前的值
    
        Map map = new HashMap<>();
        map.put("name1", "laowang");
        map.put("password", "12344");
        mv.addAllObjects(map);
    
        //设置视图
        mv.setViewName("/hello.jsp");
        return mv;
    }
    
    //3.直接返回对象
    //此时会寻找视图解析器中[前缀+value2+后缀]的页面/WEB-INF/views/value2.jsp
    @RequestMapping("/value2")
    public User getUser() {
        return new User("CoderZS", "1234");
    }
    
    //注意返回String的时候会当做视图解析(推荐使用)
    //如果返回的类型是String就会把返回值当做使徒的一部分
    //最终去寻找的路径[前缀+返回的值+后缀]
    //WEB-INF/views/vvv.jsp
    @RequestMapping("/value3")
    public String getString(Model model) {
        model.addAttribute("name", "coderZS");
        return "vvv";
    }
    
    //4.访问其他路径的文件,不需要用到前后缀
    @RequestMapping("/value4")
    public String getString() {
        //希望访问其他路径的文件,就不需要用到前缀后缀
        //forward:login.html //请求转发
        return "redirect:login.html";//重定向
    }
    }
    

    8.文件上传

    表单.png
     //文件上传
    @RequestMapping("/upload")
    //  在方法形参上添加MultipartFile对象来接收(不能使用File来接收了)
    public void upload(MultipartFile file) throws Exception {
        System.out.println(file.getName());//提交表单的文件的参数名
        System.out.println(file.getContentType());//文件类型
        System.out.println(file.getOriginalFilename());//提交的文件名
        System.out.println(file.getSize());//文件大小
        //拷贝文件
        FileOutputStream outputStream = new FileOutputStream("/Users/zhangshuai/Desktop/file" + file.getOriginalFilename());
        IOUtils.copy(file.getInputStream(), outputStream);
        //关闭输出流
        outputStream.close();
    }
    
    图片.png

    添加文件上传解析器

     <!--文件上传解析器-->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为1MB -->
        <property name="maxUploadSize">
            <value>1048576</value>
        </property>
    </bean>
    
    图片.png

    9.文件下载

       //文件下载
    @RequestMapping("/download")
    public  void download(HttpServletResponse response) throws Exception {
        System.out.println("---下载-----");
        //设置下载响应头
        response.setHeader("Content-Disposition","attachment;filename=a.jpg");
        //读取文件
        FileInputStream inputStream=new FileInputStream("/Users/zhangshuai/Desktop/file/1.jpg");
        IOUtils.copy(inputStream, response.getOutputStream());
        //关闭输入流
        inputStream.close();
    }
    
    图片.png

    10.注册拦截器

    1. 创建自定义的拦截器类,实现HandlerInterceptor接口
    图片.png

    2.注册拦截器

     <!--注册拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <!--排除拦截的路径-->
            <mvc:exclude-mapping path="/login"/>
            <!--拦截处理类-->
            <bean class="com.jd.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    
    图片.png

    11.返回json格式

    在方法的返回值上直接声明要返回的类型,并且加上@ResponseBody注解

    需要添加json解析依赖包

    图片.png
    //返回json格式
    // 1.在方法的返回值上直接声明要返回的类型,并且加上@ResponseBody注解
     @Controller
    public class JsonController {
    @RequestMapping("/json")
    @ResponseBody
    public User json() {
        User user = new User("CoderZS", "1234");
        return user;
    }
    
    @RequestMapping("/json1")
    @ResponseBody
    public List<User> json1() {
        User user = new User("CoderZS", "1234",new Date());
        List list = new ArrayList<>();
        list.add(user);
        return list;
    }
    
    //2.使用ObjectMapper
    public static void main(String[] args) throws Exception {
        User user = new User("CoderZS", "1234");
        //转成json字符串的工具
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(user);
        System.out.println(json);
    }
    }
    

    12.日期处理

    后台往前台传json值时(包含日期)

    默认输出的是毫秒值,需要使用特定的格式

    解决方案:
    方案1:在属性上添加@JsonFormat注解,注意要添加时区

    图片.png
    方案2: 在总配置文件添加相关配置
      <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <property name="dateFormat">
                            <bean class="java.text.SimpleDateFormat">
                                <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss"/>
                            </bean>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    
    前台往后台传参时(包含日期)

    1.在日期参数上添加@DateTimeFormat注解

    图片.png

    2.在Controller上添加initBinder方法

     @InitBinder
    public void initBinder(WebDataBinder binder){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
    }
    

    如果两种都有,会使用initBinder方法

    13.图解SpringMVC执行流程

    执行流程.png SpringMVC执行流程.png

    点击查看--->SpringMVC执行流程及原理

    相关文章

      网友评论

      • 红色咖啡豆:第一次访问的时候才去加载框架
        如果类很多,那么第一次访问就会很慢
        你好, 我想问下, 我现在想通过在启动的把所有都加载了, 解决第一次访问很慢的问题. 有什么好的方法吗
        CoderZS:@红色咖啡豆 这个不是问题 可能跟电脑配置有关系
      • 58830dc5be5f:很详细,挺好的
        CoderZS:@长胖 谢谢关注 希望对你有帮助

      本文标题:SpringMVC开发流程

      本文链接:https://www.haomeiwen.com/subject/gndorxtx.html