欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springMVC基于注解开发

程序员文章站 2022-07-12 23:07:52
...

一.springMVC配置文件

DispatcherServlet-servlet.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"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

        <!--
            Spring MVC主要由DispatcherServlet、
            处理器映射【找控制器】、
            适配器【调用控制器的方法】、
            控制器【业务】、
            视图解析器、
            视图组成。
        -->

        <!--如果web.xml中的DispatcherServlet拦截的是 /*  需要在这里设置 对静态资源文件的访问-->
        <!--<mvc:resources mapping="/js/*" location="/js/" />-->
        <!-- 配置 注解扫描位置 在编写的Controller中添加Controller注解即可-->
        <context:component-scan base-package="com.miracle.web.controller"/>
        <!--   如果写了下面这个,那么 处理器映射器,处理器适配器 就可以不用配置    -->
        <!--<mvc:annotation-driven/>-->
        <!-- 配置 处理器映射器-->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>

     <!-- 配置 注解处理器适配器来执行控制器的方法 -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <!--配置json转换器,告诉springMVC使用jackson来转换数据-->
            <property name="messageConverters">
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
            </property>
        </bean>

        <!-- 配置 资源视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <!-- 前缀 -->
              <property name="prefix" value="/WEB-INF/views/"></property>
              <!-- 后缀 -->
              <property name="suffix" value=".jsp"></property>
        </bean>

</beans>

二.controller编写

1 @RequestMapping 除了可以使用请求URL映射请求外,还可以使用请求方法,请求参数以及请求头映射请求

@RequestMapping的value,method,params以及heads分别表示请求URL,请求方法,请求参数以及请求头的映射条件,他们之间是与的关系,联合使用多个条件可以让请求映射更加精确化。
示例:

// 表示映射url为testMethod路径,接受的方式是post方法
@RequestMapping(value = "/testMethod", method = RequestMethod.POST)

params 和 headers 支持简单的表达式:
param1:表示请求必须包含名为param1的请求参数
!param1:表示请求不能包含名为param1的请求参数
param1!=value1:表示请求包含名为param1的请求参数,但其值不能为value1
{"param1=value1", "param2"}:请求必须包含名为param1 和 param2的两个请求参数,且param1参数的值必须为value1

// 表示请求路径是testParamsAndHeaders,必须有username参数,且age参数不为10,请求头必须含有参数Accept-Language
@RequestMapping(value = "/testParamsAndHeaders", params = {"username", "age!=10"}, headers = {"Accept-Language"})
2 @RequestMapping url映射还支持Ant风格的URL

Ant 风格资源地址支持3种匹配符:

  • ?:匹配文件名中的一个字符
  • *:匹配文件名中的任意字符
  • **:**匹配多层路径

示例:
/user/*/createUser:匹配 /user/aaa/creatUser,/user/bbb/createUser 等URL
/user/**/createUser:匹配 /user/createUser,/user/aaa/bbb/createUser 等URL
/user/createUser??:匹配 /user/createUseraa,/user/createUserbb 等URL

3 @PathVariable 获取URL路径参数(使得springMVC支持REST风格)
REST风格介绍
REST:即 Representational State Transfer。资源表现层状态转化。是目前流行的一种互联网软件架构。它结构清晰,符合标准,
易于理解,扩展方便所以正得到越来越多网站的采用

资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本,一张图片,一首歌曲,一种服务,
总之就是一个具体的存在。可以用一个URL(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源(统一资源定位
符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URL就可以,因此URI即为每个资源的独一无二的标识符。

表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层,比如,文本可以用txt格式表现,也可以用HTML格式,
XML格式,JSON格式表现,甚至可以采用二进制格式。

状态转化(State Transfer):,每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有
的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"。二这种转化是建立
在表现成之上的,所以就是"表现成状态转化"。具体说,就是HTTP协议里面,四个表示操作方式的动词:GET,POST,PUT,
DELETE。他们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源

示例:
/order/1 HTTP GET:得到id = 1 的order
/order/1 HTTP DELETE:删除id = 1 的order
/order/1 HTTP PUT:更新id = 1 的order
/order HTTP POST:新增order

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

如何发送PUT请求和DELETE请求?
1.在xml中配置HiddenHttpMethodFilter过滤器
2.前端需要发送POST请求是,携带一个name="_method"的隐藏域,值为DELETE 或 PUT
3.在controller中 定义相应的方法,接收对应的请求(GET,POST,PUT,DELETE)

示例:
1.web.xml

<!--配置 org.springframework.web.filter.HiddenHttpMethodFilter
    可以把POST请求转为 DELETE 或 PUT 请求,使SpringMVC支持REST风格
-->
<filter>
  <filter-name>HiddenHttpMethodFilter</filter-name>
  <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>HiddenHttpMethodFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

2.前端页面通过提交隐藏域告诉后台请求类型

<br>

    <form action="/springmvc/testRest/1.do" method="post">
        <input type="hidden" name="_method" value="PUT">
        <input type="submit" value="TestRest PUT">
    </form>

<br>

    <form action="/springmvc/testRest/1.do" method="post">
        <input type="hidden" name="_method" value="DELETE">
        <input type="submit" value="TestRest DELETE">
    </form>

<br>

    <form action="/springmvc/testRest.do" method="post">
        <input type="submit" value="TestRest POST">
    </form>

<br>

    <a href="/springmvc/testRest/1.do">Test Rest Get</a>

<br>

3.controller

package com.miracle.springmvc.handlers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {

    private static final String SUCCESS = "success";

    @RequestMapping(value = "/testRest/{id}", method = RequestMethod.PUT)
    public String testRestPut(@PathVariable("id") Integer id){
        System.out.println("testRestPut" + id);
        return SUCCESS;
    }

    @RequestMapping(value = "/testRest/{id}", method = RequestMethod.DELETE)
    public String testRestDelete(@PathVariable("id") Integer id){
        System.out.println("testRestDelete" + id);
        return SUCCESS;
    }

    @RequestMapping(value = "/testRest", method = RequestMethod.POST)
    public String testRestPost(){
        System.out.println("testRestPost");
        return SUCCESS;
    }

    @RequestMapping(value = "/testRest/{id}", method = RequestMethod.GET)
    public String testRestGet(@PathVariable("id") Integer id){
        System.out.println("testRestGet" + id);
        return SUCCESS;
    }
}
通过注解 @PathVariable 可以将URL中路径参数绑定到控制器方法的参数中

例如

@RequestMapping("testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id){
    System.out.println(id);
    return SUCCESS;
}

UserController

package com.miracle.web.controller;

import com.miracle.model.User;
import com.miracle.model.UserExt;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@SuppressWarnings("all")
@Controller // 声明这个Controller 相当于spring中配置一个bean
@RequestMapping("/user") // 绑定路径1
public class UserController{

    /**
     * RequestMapping 参数的写法
     *
     * RequestMapping(“list”)
     * RequestMapping(“/list.do”)
     * RequestMapping(value=”/list.do”)
     * RequestMapping(value = "/list3",method=RequestMethod.POST) 只能使用POST方法访问
     * RequestMapping(value = "/list3",method=RequestMethod.Get) 只能使用GET方法访问
     */

    @RequestMapping("/list") // 绑定路径2   最终浏览器访问的路径是:绑定路径1 + 绑定路径2
    public String list(Model model){ // 参数model用来存储数据返回给页面
        List<User> userList = new ArrayList<>();
        User user1 = new User("11", "11");
        User user2 = new User("22", "22");
        User user3 = new User("33", "33");
        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        model.addAttribute("userList", userList);
        // 返回的字符串为服务器资源路径(返回字符串还要拼接 资源视图解析器 配置的前缀和后缀)
        return "user/userlist";
    }

    @RequestMapping("/toRegister")
    public String toRegister(){
        return "user/register";
    }

    /**
     * 第一种接收表单参数的方式
     * 在方法中定义参数接收表单提交的数据,要求表单提交的name属性和参数名一致
     * @return
     */
    @RequestMapping("/register1")
    public String register1(String username, String password, String gender, int age, Date birthday, String[] hobbysIds ){
        // 在方法中定义参数用来接收前台传入的参数
        /*
            可以接收get请求 通过?username=aaa,password=bbb
            也可以接收post请求的参数
        */

        // 当请求是restful风格的url时,如 edit/5
        /*
            此时要想接收参数
            注解的写法       @RequestMapping("/edit/{id}")
            方法参数的写法    public String edit(@PathVariable int id){

                           }
        */
        System.out.println(username);
        System.out.println(password);
        System.out.println(gender);
        System.out.println(age);
        System.out.println(birthday);
        System.out.println(Arrays.toString(hobbysIds));
        return "user/info";
    }

    /**
     * 第二种接收表单参数的方式
     * 在方法中定义POJO接收表单提交的数据,要求表单提交的name属性和POJO字段名一致
     * @return
     */
    @RequestMapping("/register2")
    public String register2(User user){
        System.out.println(user);
        return "user/info";
    }

    /**
     * 第三种接收表单参数的方式(JavaBean嵌套JavaBean)
     * 在方法中定义POJO接收表单提交的数据,要求表单提交的name属性和POJO字段名一致
     * @return
     */
    @RequestMapping("/register3")
    public String register3(UserExt userExt){
        // 这里前端name属性为 user.username user.password
        System.out.println(userExt);
        return "user/info";
    }

    /**
     * 第四种接收表单参数的方式(用List接收form数据)
     * @return
     */
    @RequestMapping("/register4")
    public String register4(UserExt userExt){
        // 这里前端name属性为 user.username user.password
        System.out.println(userExt.getUserList());
        return "user/info";
    }

    /**
     * 第五种接收表单参数的方式(用map接收form数据)
     * @return
     */
    @RequestMapping("/register5")
    public String register5(UserExt userExt){
        // 这里前端name属性为 user.username user.password
        System.out.println(userExt.getMap());
        return "user/info";
    }

    /**
     * restful风格请求处理    以及     springMVC请求转发,重定向
     * @return
     */
    @RequestMapping("/edit/{id}")
    public String restful(@PathVariable int id, Model model){
        System.out.println("id:"+id);
        model.addAttribute("id", id);
        // 重定向:forward + path
        // 请求转发:redirect + path
        return "forward:/user/forwardDemo.do";
//        return "redirect:/user/redirectDemo.do";
    }

    @RequestMapping("/forwardDemo")
    public String forward(){
        return "user/forward";
    }

    @RequestMapping("/redirectDemo")
    public String redirect(){
        return "user/redirect";
    }

    /**
     *  对方法参数进行一些说明 RequestParam
     *  value:参数名称
     *  defaultValue:默认值
     *  required:参数是否必须有值,如果为true,参数又为空,会报错
     */
    @RequestMapping("/requestParamDemo")
    public String requestParamDemo(@RequestParam(value = "id", required = true, defaultValue = "30") int id){
        System.out.println(id);
        return "user/info";
    }
	
    /*
       SpringMVC还可以接收请求头参数
       通过注解 @RequestHeader
       用法同上
     */
    @RequestMapping("/testRequestHeader")
    public String testRequestHeader(@RequestHeader(value = "Accept-Language") String al){
        System.out.println(al);
        return SUCCESS;
    }
}

StudentController

package com.miracle.web.controller;

import com.miracle.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@SuppressWarnings("all")
@Controller // 声明这个Controller 相当于spring中配置一个bean
@RequestMapping("/student") // 绑定路径1
public class StudentController {

    @RequestMapping("/reg")
    public String reg(){
        return "student/add";
    }

    /**
     * 接收,返回json数据
     * @RequestBody:告诉框架把接收到的json数据转换成JavaBean对象(注意RequestBody后面只能跟javaBean)
     * RequestMapping:将对象转换成json字符串返回
     * @return
     */
    @RequestMapping("/save")
    @ResponseBody
    public Student save(@RequestBody Student student){
        System.out.println(student);
        return student;
    }
}
4 除了上述接收前端表单的传参,SpringMVC中controller类中的方法可以传入一些ServletAPI

例如:HttpServletRequest,HttpServletResponse,HttpSession等

@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request, HttpServletResponse response){
    System.out.println(request);
    System.out.println(response);
    return SUCCESS;
}
5 SpringMVC提供了以下几种途径向前端页面返回数据
  • 1.ModelAndView

原理:SpringMVC会把ModelAndView中的mode的数据放到request域对象中,数据在单个请求中有效

controller写法

@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
    // 构造方法中指定视图名字
    ModelAndView modelAndView = new ModelAndView(SUCCESS);
    // 添加模型数据到modelAndView中
    modelAndView.addObject("time", new Date());
    return modelAndView;
}

jsp写法

time:${time}
  • 2.在controller方法的参数中添加Map或Model参数

原理:SpringMVC会把Map,Model中的数据放到request域对象中,数据在单个请求中有效
传Map和Model的用法相同

@RequestMapping("/testMapAndModel")
public String testMapAndModel(Model model){
    model.addAttribute("names", Arrays.asList("Tom", "Jerry", "Mike"));
    return SUCCESS;
}
  • 3.使用 @SessionAttributes 注解,将数据放到session域对象中

原理:SpringMVC会把Map,Model中的数据同时放到request和session域对象中,数据在整个session中有效

/*
    [email protected]注解只能修饰类
    2.value = {"user"} 属性指定了下面模型中哪些key是同时放到request和session中的
    3.types = {Date.class} 属性指定了下面模型中哪些value是同时放到request和session中的
 */
@SessionAttributes(value = {"user"},types = {Date.class})
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {

    private static final String SUCCESS = "success";

    @RequestMapping("/testSessionAttributes")
    public String testSessionAttributes(Model model){
        User user = new User("username", "password", "email", "age");
        // 通过 @SessionAttributes 注解指定key,将user同时放到request和session域中
        model.addAttribute("user", user);
        // 通过 @SessionAttributes 注解指定value的类型,将time的值同时放到request和session域中
        model.addAttribute("time", new Date());
        // 由于没有指定,所以name的值只是方法request域中
        model.addAttribute("name", "miracle");
        return SUCCESS;
    }
}