SpringMVC学习笔记

SpringMVC

一、概述

1.1 三层架构

开发框架一般基于两种形式,一种为C/S架构,即客户端/服务器;另一种为B/S架构,即浏览器服务器架构。在JavaEE开发中,几乎都是B/S架构。B/S架构中,系统标准的三层架构包括:表现层、业务层、持久层。

  1. 表现层:即Web层,它负责接收客户端请求,向客户端响应结果,通常客户端使用HTTP协议请求web层,web需要接收HTTP请求,完成HTTP响应。表现成包括展示层和控制层,控制层负责接收请求,展示层负责结果的展示,表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。表现层的设计一般都使用MVC模型
  2. 业务层:即service层。它负责业务逻辑处理,和我们开发项目的需求相关。web层依赖业务层,但是业务层不依赖web层。业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务的一致性,即事务应该放在业务层控制
  3. 持久层:即dao层。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进行持久化的载体,数据访问层是业务层和持久层交互的接口,业务层需要通过数据访问层将数据持久化到数据库中。持久层就是和数据库交互,对数据库表进行增删改查

1.2 MVC

MVC即Model View Controller,是模型—视图—控制器的缩写,是一种用于设计创建Web应用程序表现层的模型

  1. Model:通常指的是我们的数据模型。作用一般用于封装数据
  2. View:通常指jsp或html,作用一般是展示数据,通常视图依据模型数据创建
  3. Controller:应用程序中处理用户交互的部分,作用一般是处理程序的逻辑

1.3 SpringMVC

  • SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于Spring FrameWork的后续产品。已经融合在Spring Web Flow里面。Spring框架提供了构建Web应用程序的全功能MVC模型。使用Spring可插入的MVC架构,从而在使用Spring进行WEB开发时,可以选择Spring的SpringMVC框架或其它MVC开发框架,如Strusts1,Struts2等
  • SpringMVC是目前主流的MVC框架之一,并且随着Spring3.0的发布,全面超越Struts2,称为最优秀的MVC框架
  • 它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无需实现任何接口

二、入门案例

2.1 环境搭建

  • 依赖

        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <!--版本锁定-->
            <spring.version>5.2.5.RELEASE</spring.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.2</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    
  • Web.xml

        <!--前端控制器配置-->
    	 <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--前端控制器加载配置文件-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
  • 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">
        <!--开启注解扫描-->
        <context:component-scan base-package="ysw.controller"></context:component-scan>
    
        <!--视图解析器-->
        <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--文件所在目录-->
            <property name="prefix" value="/WEB-INF/pages/"/>
            <!--文件后缀名-->
            <property name="suffix" value=".jsp"/>
        </bean>
        <!--开启SpringMVC框架注解支持-->
        <mvc:annotation-driven/>
    </beans>
    

2.2 工作流程

在这里插入图片描述

三、RequestMapping注解

  1. 出现的位置:
    • 类上:代表请求URL的第一级目录,若不写就相当于服务的根目录
    • 方法上:请求URL的第二级访问目录
  2. 属性:
    • value:用于指定请求的URL。和Path属性的作用一样
    • method:用于指定请求方式
    • params:用于指定限制请求参数的条件。支持简单表达式。要求请求参数的key和value必须和配置一样
    • header:用于指定限制请求消息头的条件

四、请求参数的绑定

4.1 参数传递

  1. 将参数的值赋给相应的属性

    • 可以在表单的name属性中填写相对应的属性名
  2. 将参数封装到对象

    • 在表单的name属性中填写对象.属性名
  3. 将参数封装到集合

    • 在表达name属性中填写集合.属性
  4. 代码演示

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>param</title>
    </head>
    <body>
        <a href="param/testParam?username=hehe&password=123">请求参数绑定测试</a>
        <form action="/param/saveAccount" method="post">
            <%--将参数值传递给相应属性--%>
            姓名:<input type="text" name="username"><br>
            密码:<input type="text" name="password"><br>
            金额:<input type="text" name="money"><br>
            <%--将参数封装到对象--%>
            用户姓名:<input type="text" name="user.name"><br>
            用户年龄:<input type="text" name="user.age"><br>
            <input type="submit" value="提交">
        </form>
        <form action="/param/saveAccount" method="post">
            姓名:<input type="text" name="username"><br>
            密码:<input type="text" name="password"><br>
            金额:<input type="text" name="money"><br>
            <%--将参数封装到集合--%>
            用户姓名:<input type="text" name="list[0].name"><br>
            用户年龄:<input type="text" name="list[0].age"><br>
            用户姓名:<input type="text" name="map['one'].name"><br>
            用户年龄:<input type="text" name="map['one'].age"><br>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    

4.2 自定义类型转换

public class StringToDate implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        if (s == null) {
            throw new RuntimeException("传入参数错误!!");
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return simpleDateFormat.parse(s);
        } catch (ParseException e) {
            throw new RuntimeException("格式转换错误!!");
        }
    }
}
  • 配置文件

        <!--配置自定义类型转换器-->
        <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <bean class="ysw.Utils.StringToDate"/>
                </set>
            </property>
        </bean>
    
        <!--开启SpringMVC框架注解支持-->
        <mvc:annotation-driven conversion-service="conversionService"/>
    

五、常用注解

  1. RequestParam

    • 作用:将请求中指定名称的参数给控制器中的形参赋值
    • 属性:value:请求参数中的名称;required:请求参数中必须提供此参数。默认值为True。表示必须提供
  2. RequestBody

    • 作用:获取请求体中的内容,直接使用会得到key=value
    • 属性:required:是否必须有请求体。默认为true。当取值为true时get请求会报错。如果取值为false,get请求得到null
  3. PathVariable

    • 作用:拥有绑定url中的占位符。例如“rul中有/delete/{id},{id}就是占位符
    • 属性:value:指定url中的占位符名称
    • rest父类风格的URL优点:
      • 结构清晰
      • 符合标准
      • 易于理解
      • 扩展方便
  4. RequestHeader

    • 获取请求头的值
  5. CookieValue

    • 获取Cookie的值
  6. ModelAttribute

    • 可以用于修饰方法和参数
    • 出现在方法上,表示当前方法会在控制器的方法执行前先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法
    • 出现在参数上,获取指定的数据给参数赋值
  7. SessionAttributes

    • 用于多次执行控制器方法间的参数共享
    • 属性:value:用于指定存入的属性名称;type:用于指定存入的数据类型
    • 作用在类上
    @SessionAttributes(value = {"msg"})
    @Controller
    @RequestMapping("/param")
    public class ParamController {
        @RequestMapping("/testSessionAttributes")
        public String testSessionAttributes(Model model){
            model.addAttribute("msg","hello");
            return "success";
        }
    }
    

六、响应数据和结果视图

6.1 字符串

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/testString")
    public String testString(Model model){
        System.out.println("testString!!!");
        User user = new User();
        user.setName("Tom");
        user.setPassword("1234");
        user.setAge(18);
        model.addAttribute("user",user);
        return "success";
    }
}
  • 在页面可以通过${user.name}获取到值

6.2 void

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("testVoid!!!");
        //转发
//        request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
        //重定向
//        response.sendRedirect(request.getContextPath()+"/index.jsp");
        //向页面输出数据
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html");
        response.getWriter().print("你好!!");
        return;
    }
}

6.3 ModelAndView

@Controller
@RequestMapping("/user")
public class UserController {   
    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView() {
        ModelAndView modelAndView = new ModelAndView();
        User user = new User();
        user.setAge(19);
        user.setPassword("1234");
        user.setName("Job");
        modelAndView.addObject("user", user);
        //指定跳转到某个页面
        modelAndView.setViewName("success");
        return modelAndView;
    }
}

七、转发和重定向

@Controller
@RequestMapping("/user")
public class UserController {  
    @RequestMapping("/forwardOrRedirect")
    public String forwardOrRedirect() {
        System.out.println("转发或重定向!!");

        //转发
        //return "forward:/WEB-INF/pages/success.jsp";
        //重定向
        return "redirect:/index.jsp";
    }
}

八、ResponseBody响应json数据

  • 首先需要配置哪些静态资源不需要被控制器拦截(springmvc.xml)

    <!--告诉前端控制器哪些资源不需要拦截-->
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/images/**" location="/images/"/>
    <mvc:resources mapping="/js/**" location="/js/"/>
    
  • 导入Jar包

            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.10.3</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.10.3</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.10.3</version>
            </dependency>
    
  • 测试类

    @Controller
    @RequestMapping("/user")
    public class UserController { 
        @RequestMapping("/testAjax")
        @ResponseBody
        public User testAjax(@RequestBody User user) {
            System.out.println("testAjax执行!!!");
            //客户端发送Ajax的请求,传json字符串,后端将json字符串封装到User对象中
            System.out.println(user.toString());
            user.setName("Lily");
            user.setAge(30);
            //返回json数据
            return user;
        }
    }
    

九、文件上传

9.1 普通文件上传

  • 借助第三方组件上传文件,导入依赖

            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.webjars.npm</groupId>
                <artifactId>commist</artifactId>
                <version>1.0.0</version>
            </dependency>
    
  • SpringMVC上传文件,配置文件解析器(springmvc.xml)

        <!--文件解析器-->
        <bean id="multipartResolver" 			class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!--允许上传的最大文件大小-->
            <property name="maxUploadSize" value="10485760"/>
        </bean>
    
  • 测试

    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        /**
         * @Param [req, upload]
         * @return java.lang.String
         * @Date 9:03 2020/7/4
         * @Description: //TODO
         **/
        @RequestMapping("/fileupload1")
        public String fileupload1(HttpServletRequest req, MultipartFile upload) throws IOException {
            System.out.println("文件上传!!");
            String path = req.getSession().getServletContext().getRealPath("/uploads/");
            File file = new File(path);
            if (!file.exists()) {
                //创建文件夹
                file.mkdirs();
            }
            //获取文件名称
            String filename = upload.getOriginalFilename();
            //将文件名称设置为唯一值
            String replace = UUID.randomUUID().toString().replace("-", "");
            filename = replace + "_" + filename;
            //完成文件上传
            upload.transferTo(new File(path, filename));
            return "success";
        }
    }
    

9.2 分服务器上传文件

  • 导入jar包

    <dependency>
    	<groupId>com.sun.jersey</groupId>
    	<artifactId>jersey-client</artifactId>
    	<version>1.19.4</version>
    </dependency>
    <dependency>
    	<groupId>com.sun.jersey</groupId>
    	<artifactId>jersey-core</artifactId>
    	<version>1.19.4</version>
    </dependency>
    
  • 代码演示

    @Controller
    @RequestMapping("/user")
    public class UserController {	
    	@RequestMapping("/fileupload")
        public String fileupload2(MultipartFile upload) throws IOException {
            System.out.println("文件上传!!");
            //定义上传文件服务路径
            String path = "http://localhost:xxxx/xxxx/";
            //获取文件名称
            String filename = upload.getOriginalFilename();
            //将文件名称设置为唯一值
            String replace = UUID.randomUUID().toString().replace("-", "");
            filename = replace + "_" + filename;
            //创建客户端对象
            Client client = Client.create();
            //和文件服务器进行连接
            WebResource resource = client.resource(path + filename);
            //上传文件
            resource.put(upload.getBytes());
            return "success";
        }
    }
    

十、SpringMVC异常处理

  • 异常测试
@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/testException")
    public String testException() throws SysException {
        try {
            //模拟异常
            int a = 10 / 0;
        } catch (Exception e) {
            //打印异常信息
            e.printStackTrace();
            //抛出自定义异常
            throw new SysException("出现错误!!!");
        }
        return "success";
    }
}
  • 自定义异常
public class SysExceptionResolver implements HandlerExceptionResolver {

    /**
     * @return org.springframework.web.servlet.ModelAndView
     * @Param [httpServletRequest, httpServletResponse, o, e]
     * @Date 9:48 2020/7/4
     * @Description: 处理异常
     **/
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        //获取异常对象
        SysException ex = null;
        if (e instanceof SysException) {
            ex = (SysException) e;
        } else {
            ex = new SysException("系统正在维护……");
        }
        //创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("errorMsg", ex.getMessage());
        modelAndView.setViewName("error");
        return modelAndView;
    }
}
  • 配置异常处理器
<!--配置异常处理器-->
<bean id="sysExceptionResolver" class="ysw.exception.SysExceptionResolver"/>

十一、SpringMVC中的拦截器

  • 自定义类实现HandlerInterceptor接口

    /**
     * @Description: TODO
     * @Author YunShuaiWei
     * @Date 2020/7/4 10:46
     * @Version
     **/
    public class MyInterceptor implements HandlerInterceptor {
        /**
         * @return boolean
         * true:放行,执行下一个拦截器,若没有,则执行controller中的方法
         * false:不放行
         * @Param [request, response, handler]
         * @Date 10:47 2020/7/4
         * @Description: 预处理,controller方法执行前
         **/
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("……");
            return true;
        }
    
        /**
         * @return void
         * @Param [request, response, handler, modelAndView]
         * @Date 10:58 2020/7/4
         * @Description: Controller执行后执行的方法
         **/
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle……");
            request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        }
    
        /**
         * @return void
         * @Param [request, response, handler, ex]
         * @Date 10:59 2020/7/4
         * @Description: 最后执行的方法, 即跳转到success.jsp之后会执行该方法
         **/
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion……");
        }
    }
    
  • 配置拦截器

        <!--配置拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--要拦截的具体方法-->
                <mvc:mapping path="/user/*"/>
                <!--不要拦截的方法
                <mvc:exclude-mapping path=""/>-->
                <bean class="ysw.interceptor.MyInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ysw!不将就

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值