SpringMVC(博主转载老师讲义,只图查看方便)

Spring-MVC

一、MVC 概述

mvc是软件开发中非常常见的分层设计,目的是使程序中的代码根据负责的功能分离,便于维护,当你更新视图时,不用修改其他代码。

M: Model --  JavaBean 模型
​
V: View --  视图
​
C: Controller 控制器

二、SpringMVC

Springmvc 是spring 框架的一个模块,用于构建web应用程序,Springmvc是符合mvc设计的一个框架。

三、入门案例

  1. 准备依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
            <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
  1. 配置web.xml

     <!-- 字符集编码过滤器 -->
       <filter>
           <filter-name>CharacterEncodingFilter</filter-name>
           <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
           <init-param>
             <param-name>encoding</param-name>
             <param-value>UTF-8</param-value>
           </init-param>
           <init-param>
              <param-name>forceEncoding</param-name>
              <param-value>true</param-value>
           </init-param>
         </filter>
         <filter-mapping>
           <filter-name>CharacterEncodingFilter</filter-name>
           <url-pattern>/*</url-pattern>
         </filter-mapping>
      
      <!-- 应用程序前端控制器 -->
        <servlet>
            <servlet-name>springDispatcherServlet</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>springDispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
  2. 编写spring-mvc配置文件 ( spring-mvc.xml )

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
              <!-- 扫描控制器所在包 -->
              <context:component-scan base-package="com.xingxue.mvc.controller"/>
              <!-- 开启注解驱动 -->
              <mvc:annotation-driven/>
              <!-- 对于静态资源 请求交给容器的默认servlet处理 -->              
              <mvc:default-servlet-handler/>
              <!-- 视图解析器 -->
              <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/views/"/> <!-- -->
                <property name="suffix" value=".jsp"/>
              </bean>
    </beans>
  3. 编写控制器

    package com.xingxue.mvc.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    ​
    @Controller
    @RequestMapping("/test/")
    public class HelloController {
    ​
        @RequestMapping("/hello")
        public String test1(  ) {
            return "hello";
        }
    }
  4. 测试

四、请求映射( @RequestMapping )

1、基本请求映射

@RequestMapping("/test/")
public class HelloController {
​
    @RequestMapping("/hello")
    public String test1(  ) {
        return "hello";
    }
}

2、精准请求映射 ( value method param header 映射 Http消息 )

@RequestMapping(value="/emp",method=RequestMethod.GET)
    public void getEmp() {
        System.out.println("get one resource"+id);
    }
    @RequestMapping(value="/emps",method=RequestMethod.GET)
    public void getEmps() {
        System.out.println("get all resource");
    }
    
    
    @RequestMapping(value="/emp",method=RequestMethod.POST)
    public void save() {
        System.out.println("add one resource");
    }
    @RequestMapping(value="/emp",method=RequestMethod.DELETE)
    public void delete() {
        System.out.println("delete one resource");
    }
    @RequestMapping(value="/emp",method=RequestMethod.PUT)
    public void  update() {
        System.out.println("update one resource");
    }

3、ant请求映射

    @RequestMapping(value="/user/?bc")
    public void abc() {
        System.out.println("abc");
    }
    @RequestMapping(value="/user/*d")
    public void aaa() {
        System.out.println("aaa");
    }
    @RequestMapping(value="/user/**/sb")
    public void bbb() {
        System.out.println("bbb");
    }
    @RequestMapping(value="/user/**/?mvc*")
    public void ccc() {
        System.out.println("ccc");
    }

Ant 资源地址支持3种统配符

:资源名字中一个任意字符

* : 资源名字中的任意个字符

** : 匹配多层路径

4、@PathVariable 注解

通过 @PathVariable 可以将 URL 中占位符参数绑定到控 制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过

@PathVariable("xxx") 绑定到操作方法的入参中。

@RequestMapping(value="/emp/{id}",method=RequestMethod.GET)
    public void getEmp(@PathVariable("id") Integer id) {
        System.out.println("get one resource"+id);
}

五、RestFul风格

REST:即 Representational State Transfer。(资源)表现层状态转化。是目前 最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便, 所以正得到越来越多网站的采用

 • 资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它  可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。  可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要  获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识  别符。
​
 •  表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格  式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
​
 •  状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一  次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器  端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“  状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “  表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动  词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获  取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

API 示例:

URL HTTP Method 作用
–/order/1 GET :得到 id = 1 的 order
–/order/1 PUT :更新id = 1的 order
–/order POST :新增 order
–/order/1 DELETE :删除 id = 1的 order
-/orders/1 GET : 1号用户 全部订单

SpringMVC对RestFul支持

HiddenHttpMethodFilter:浏览器 form 表单只支持 GET  与 POST 请求,而DELETE、PUT 等 method 并不支  持,Spring3.0 添加了一个过滤器,可以将这些请求转换  为标准的 http 方法,使得支持 GET、POST、PUT 与  DELETE 请求。

配置 HiddenHttpMethodFilter

    <!--  HiddenHttpMethodFilter: 支持restful 风格请求  -->
    <filter>
        <filter-name>RestFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>RestFilter</filter-name>
         <servlet-name>SpringMVC</servlet-name>
    </filter-mapping>

六、获取请求数据

1、简单数据类型

 @RequestMapping("t1")
    public void test1(String name,int age ) {
        System.out.println("you input is "+name+ "\t" + age );
    }

测试:http://localhost;8080/spring-web/params/t1?name=admin&age=11

2、pojo数据类型(支持级联属性注入)

    @RequestMapping("t2")
    public void test2(User u) {
        System.out.println(u);
    }
----------------------------------------------------------------------------------------------
public class User {
    private String username;
    private int age;
    private Company company;
    //省略get set 
}
public class Company{
    private String cname;
    private String address;
    private String phone;
    //省略get set方法
}

测试:http://localhost;8080/spring-web/params/t2?username=admin&age=11&company.cname=baidu&company.address=beijing&company.phone=010-666666

3、@RequestParam

(此注解目的是 把请求参数绑定到入参 主要解决前后参数名字不一致的情况)

    @RequestMapping("t3")
    public void test3(@RequestParam(value="fullname",required=true)String name,@RequestParam(value="phone")String tel ) {
         System.out.println("名字:"+name);
         System.out.println("电话:"+tel);
    }

测试:http://localhost:8080/spring-mvc/params/t3?fullname=kangkang&phone=188xxxxxx

4、@RequestHeader(获得请求头信息) @CookieValue(获得Cookie信息)

@RequestMapping("t4")
    public void test4(@RequestHeader(value="connection",required=false)String header, @CookieValue(value="JSESSIONID",required=false) String sessid ) {
        System.out.println("Connection:"+header);
        System.out.println("sessionid:"+sessid);
    }

5、使用Servlet API作为入参

    @RequestMapping("t5")
    public void test5(HttpServletRequest req,HttpServletResponse resp, HttpSession session) throws IOException {
        String n=req.getParameter("name");
        resp.getWriter().write(n);
        resp.getWriter().flush();
        
    }

以下是方法支持的 类型

•HttpServletRequest

•HttpServletResponse

•HttpSession

•java.security.Principal

•Locale

•InputStream

•OutputStream

•Reader

•Writer

总结:SpringMVC控制器方法入参非常灵活

七、页面渲染

  • ModelAndView

    直接翻译为 模型和数据,其作用是保存模型和数据,最终目的是把模型数据( Model )带到视图(View)中展现

        @RequestMapping("t6")
            public ModelAndView t6() {
                ModelAndView mv = new ModelAndView();
                mv.getModel().put("company", "baidu");
                mv.getModel().put("phone", "010-666666");
                mv.setViewName("hello");
                return mv;
        }
  • Model

    直接翻译为 模型,其作用是提供数据,但是也仅仅提供数据,不参与跳转视图,跳转视图需要 return 确定,此Model不需要开发者手动创建,只需要声明在方法的入参中即可,它由框架创建和注入以及发送到视图

        @RequestMapping("t7")
        public String  t7(  Model md ) {
            md.addAttribute("company", "tengxun");
            md.addAttribute("phone", "010=888888");
            return "hello";
        }
  • ModelMap Map

    其作用和使用方法 与Model一致

        @RequestMapping("t8")
        public String  t8(ModelMap mp) {
            mp.addAttribute("company", "alibaba");
            mp.addAttribute("phone", "010-999999");
            return "hello";
        }
        
        @RequestMapping("t9")
        public String  t9(Map<String,Object> mp) {
            mp.put("company", "oralce");
            mp.put("phone", "010-555555");
            return "hello"; 
        }
     测试效果:
      
      ![1535214218514](C:\Users\ADMINI~1\AppData\Local\Temp\1535214218514.png)

八、转发和重定向

   区别:转发一次请求,浏览器上地址不变
​
        重定向两次请求,浏览器地址改变
    /*重定向到jsp*/
    @RequestMapping("/t10")
    public  String  t10(){
           return  "redirect:/static/jsp/add.jsp";
    }
    /*转发向到jsp*/
    @RequestMapping("/t10")
    public  String  t10(){
           return  "forward:/static/jsp/add.jsp";
    }
    /*重定向到controller*/
    @RequestMapping("/t11")
    public  String  t11(){
        return  "redirect:/param/t9";
    }
    /*转发到控制器controller*/
    @RequestMapping("/t12")
    public  String  t12( ){
        return  "forward:/param/t8";
    }

SpringMVC 默认采取的方式是转发

重定向: redirect:/xxx

转发:forward:/xxx

九、处理JSON数据

   当前端请求方法后不需要跳转页面,而只是需要json数据,这时可以使用@ResponseBody注解,该注解的作用是把控制器方法的返回值 通过消息转换器 HttpMessageConverter 自动把方法的返回值 添加 到HttpResponse 响应消息的body中。为此我们需要添加 json依赖
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.7</version>
</dependency>

还需要开启注解驱动 ,

 <mvc:annotation-driven/>

•<mvc:annotation-driven /> 会自动注 册RequestMappingHandlerMapping

、RequestMappingHandlerAdapter 与

ExceptionHandlerExceptionResolver 三个bean。

• 还将提供以下支持:

–支持使用 ConversionService 实例对表单参数进行类型转换

–支持使用 @NumberFormat annotation、@DateTimeFormat

注解完成数据类型的格式化

– 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证

–支持使用 @RequestBody 和 @ResponseBody 注解

    @RequestMapping("/json")
    @ResponseBody()
    public User t11() {
        
        User user = new User();
        user.setUsername("admin");
        user.setAge(10);
        
        Address  addr= new Address();
        addr.setXian("奉节县");
        addr.setXiang("石岗乡");
        addr.setSheng("重庆市");
        user.setAddr(addr );
        return user;
    }
{"username":"admin","age":10,"addr":{"sheng":"重庆市","xian":"奉节县","xiang":"石岗乡"}}

十、文件上传

依赖

    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.5</version>
    </dependency>

①准备上传html页面

<form action="/file/upload" method="post" enctype="multipart/form-data">
    <input name="file" type="file">
   <input type="submit" value="上传" />
</form>

②准备控制器接受文件

@Controller
@RequestMapping("/file")
public class FileController {
​
    @RequestMapping("/upload")
    public  String  fileUpoad(MultipartFile file, HttpServletRequest request){
        System.out.println(file);
        String path=request.getServletContext().getRealPath("/")+"upload\\";
        File f= new File(path);
        if(!f.exists()){
            f.mkdirs();
        }
        try {
            //保存文件方法   /d:/abc/mvc/upload/abc.png
            file.transferTo(  new File(f,   file.getOriginalFilename() ) );
        } catch (IOException e) {
            return "error";
        }
        System.out.println("ok...................");
        return "success";
    }
}

③sping配置

    <!--文件上传配置-->
    <bean id="multipartResolver"                                class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
                <property name="defaultEncoding" value="UTF-8"/>
                <property name="maxUploadSize" value="104857600"/>
    </bean>

十 一、拦截器

1 、什么是拦截器?

Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。要使用Spring MVC中的拦截器,就需要对拦截器类进行定义和配置。通常拦截器类可以通过两种方式来定义。通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义。

2、实现拦截器

①编写拦截器代码

以实现HandlerInterceptor接口方式为例,自定义拦截器类的代码如下:

public class CustomInterceptor implements HandlerInterceptor{
        public boolean preHandle(HttpServletRequest request, 
                                 HttpServletResponse response, Object handler)throws Exception {
            System.out.println("开始拦截....");
            return false;
        }
        public void postHandle(HttpServletRequest request, 
                               HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {
             System.out.println("结束拦截....");
            
        }
        public void afterCompletion(HttpServletRequest request,
                                    HttpServletResponse response, Object handler,
                                    Exception ex) throws Exception {
             System.out.println("整个拦截过程完成");
        }
    }
  • preHandle() 方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)。

  • postHandle()方法:该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。

  • afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。

② 注册和配置拦截器

<!--配置拦截器-->
<mvc:interceptors>
        <!-- 直接注册 interceptors 下的拦截器为全局的拦截器  -->
        <!--<bean class="com.ma.interceptor.CustomeInterceptor" />--> 
        <!--拦截器1-->
        <mvc:interceptor>
            <!--配置拦截器的作用路径-->
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path=""/>
            <!--定义在<mvc:interceptor>下面的表示匹配指定路径的请求才进行拦截-->
            <bean class="com.ma.interceptor.Intercptor1"/>
        </mvc:interceptor>
        <!--拦截器2-->
        <mvc:interceptor>
            <mvc:mapping path="/hello"/>
            <bean class="com.ma.interceptor.Interceptor2"/>
        </mvc:interceptor>
</mvc:interceptors>

上面的代码中,mvc:interceptors元素用于配置一组拦截器,基子元素<bean>中定义的是全局拦截器,它会拦截所有的请求;而mvc:interceptor元素中定义的是指定路径的拦截器,它会对指定路径下的请求生效。mvc:interceptor元素的子元素mvc:mapping用于配置拦截器作用的路径,该路径在其属性path 中定义。如上述代码中 path 的属性值“/**” 表示拦截所有路径,“/hello” 表示拦截所有以 “/hello” 结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过mvc:exclude-mapping元素进行配置。

③ 测试

3、拦截器 执行流程

请求 --> preHandle(前置处理) --> target(控制器方法) --> postHandle(后置处理) --> dispatcherServlet(渲染页面) --> afterCompletion(结束处理)

十二、异常处理

在实际开发过程中,我们通常会把应用后端分为3层来开发,Controller(控制器) Service(服务层) Dao(数据访问层),这3层都可能会有异常的发生,通常的做法是把异常,由 DAO 抛到 Service 再抛到 Controller,最后再控制其中处理异常。这样可以把异常反馈給最顶层调用者处理。但是一个系统中有若干个Controller ,若干个方法,处理异常就变得十分难受了,Springmvc提供了一种全局异常处理机制,允许我们在一个类中集中处理异常,控制器不需理会异常。

实现异常处理方式一:

  @ExceptionHandler({IOException.class,NullPointerException.class } )
  public String  excpetionHandle(){
           return "error";
  }

注解中的异常类型可以给 单个 或 多个

这种处理方式,比较局限,只能处理当前 Controller中的异常

实现全局异常处理方式一:

①实现 HandlerExceptionResolver 接口

//确保 AppGolablException 实例加入IOC容器中  可以用xml配置和注解配置
@Component
public class AppGolablException  implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //这里无论什么异常都到 error 页面去
        //当然这里可以根据实际的异常类型做 不同的响应
        ModelAndView mv = new ModelAndView("error");
        return mv;
    }
}

②抛出异常

    @RequestMapping("/ex")
    public  String  testex(){
           throw  new NullPointerException("hehe");
    }
    @RequestMapping("/ex2")
    public  String  textex2() throws  Exception{
           throw  new IOException("haha");
    }

这时请求 ex 和 ex2 方法都会跳转到 error页面

实现全局异常处理方式二: @ControllerAdvice + @ExceptionHandler

①编写异常处理代码

@ControllerAdvice
public class AppException {
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Object handleHttpMessageNotReadableException(Exception e) {
        System.out.println("------------");
        return   "50X";
     }
}

②控制器抛出异常

    @RequestMapping("/ex")
    public  String  testex(){
           throw  new NullPointerException("hehe");
    }
    @RequestMapping("/ex2")
    public  String  textex2() throws  Exception{
           throw  new IOException("haha");
    }

猜你喜欢

转载自blog.csdn.net/qq_36120342/article/details/82628310