SpringMVC学习笔记

依赖

SpringMVC属于Spring框架里的web模块,因此导包时,不仅要导入SpringWeb模块的包,还要导入核心包。

配置文件

web.xml

  1. 配置DispatcherServlet,给DispatcherServlet配置springmvc配置文件的位置。如果不指定的话,会从/WEB-INF目录下寻找springmvc配置文件的位置。

springmvc.xml

  1. 开启包扫描
  2. 配置视图解析器

开始

  1. 新建一个类,打上@Controller注解,告诉SpringMVC这是一个控制器。
  2. 新建一个方法,打上@RequestMapping注解,用来处理一个url的请求。
  3. 通过return一个字符串的方式,可以转发到一个新的页面。
  4. 通过配置视图解析器,可以实现SpringMVC自动将返回值和前后缀进行拼串。
controller:
@Controller
public class MyFirstController {
    @RequestMapping("/hello")
    public String helloWorld(){
        System.out.println("收到请求,正在处理");
        return "success";
    }
}
--------------------------------------------------------------------
springmvc.xml:


    

RequestMapping

可以打在类定义上,也可以打在方法上。当打在类定义上时,表示为类中所有映射路径添加了一个基准路径。例:

@Controller
@RequestMapping("/hello")
public class RequestMappingTestController {
    @RequestMapping("/world")
    public String helloWorld(){
        System.out.println("Hello World");
        return "helloworld";
    }
}

此时要访问helloWorld方法的路径是应该"/hello/world"
PS:

  1. 这里的RequestMapping里的路径即使不加上"/",访问路径也是"/hello/world",因为类定义上的RequestMapping添加的是基准路径,而不是字符串拼接。

RequestMapping的其他属性:

  1. method:规定访问的请求方式(GET、POST等)
  2. params:规定请求的参数
  • params="param"请求参数必须带有param
  • params="!param"请求参数不能带有param
  • params="param=xxx"请求参数必须带有param,且值必须为xxx
  • params="param!=xxx"请求参数不能为xxx,不带param参数,或者param!=xx都可以
  • params={"param1=xxx","param2"}多个规则
  1. headers:规定请求头
@RequestMapping(value = "/world02",headers = "User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + 
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36")
public String testHeaders(){
    return "success";
}

这段代码规定了只接受来自谷歌浏览器的请求

ANT风格的URL

通过"?"、"*"、"**"来实现url的模糊匹配。
?:匹配任意一个字符
*:匹配0或多个字符,亦或是一层路径
**:匹配多层路径
PS:当多个url都匹配时,更加精确的优先
精确匹配 >> ?匹配 >> *匹配 >> **匹配

@PathVariable获取路径上的占位符

通过在路径上使用占位符{变量名},可以在方法的参数上打上@PathVariable来获取到占位符上的变量。

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

Rest风格的URL

以往风格的url:

  • /getBook?id=1
    查询书籍
  • /addBook
    添加书籍
  • /deleteBook?id=1
    删除书籍
  • /updateBook?id=1&info1=xxx&info2=xxx
    更新书籍

REST风格的url:

  • /book/1 get方式
    查询书籍
  • /book post方式
    添加书籍
  • /book/1 delete方式
    删除书籍
  • /book/1 put方式
    更新书籍

REST风格的特点:
以简洁的url来提交请求,以提交请求的方式来处理资源。

存在的问题:
页面只能发送get和post请求

解决方法:
在post表单中添加"_method"的参数,通过配置HiddenHttpMethodFilter过滤器,
来实现从post方式到指定方式的转化。

Controller配置:
-----------------------------------------------------------------------------
@RequestMapping(value = "/book/{id}",method = RequestMethod.GET)
public String getBook(@PathVariable("id")Integer id){
    System.out.println("查询了" + id + "号图书!");
    return "success";
}
@RequestMapping(value = "/book",method = RequestMethod.POST)
public String addBook(){
    System.out.println("添加了图书!");
    return "success";
}
@RequestMapping(value = "/book/{id}",method = RequestMethod.DELETE)
public String deleteBook(@PathVariable("id")Integer id){
    System.out.println("删除了" + id + "号图书!");
    return "success";
}
@RequestMapping(value = "/book/{id}",method = RequestMethod.PUT)
public String updateBook(@PathVariable("id")Integer id){
    System.out.println("更新了" + id + "号图书!");
    "success";
}
-----------------------------------------------------------------------------
jsp页面:
-----------------------------------------------------------------------------
查询1号图书
----------------------------------------------------------------------------- web.xml配置: ----------------------------------------------------------------------------- HiddenHttpMethodFilter org.springframework.web.filter.HiddenHttpMethodFilter HiddenHttpMethodFilter /*

PS:
高版本tomcat在将PUT或者DELETE请求转发给jsp页面时,会提示PUT和DELETE请求不支持,这时要在jsp声明添加属性isErrorPage="true"

<%@ page language="java" contentType="text/html; utf-8"
        pageEncoding="utf-8" isErrorPage="true" %>

Controller获取参数的方式

1. 直接在方法上定义名字和页面传来参数一样的入参。
public String testParam(String username){
    System.out.println("参数为:" + username);
    return "success";
}

如上的方法,能接受名为username的参数。

  • 当页面带来的参数有值时,username的值即为那个值。
  • 当页面传来的参数无值时(username=),username的值为空。
  • 当页面传来的参数不包含username时,username为null。
2. 通过@RequestParam来获取指定名字的参数。
@RequestMapping("/paramtest")
public String testParam(@RequestParam("user") String username){
    System.out.println("参数为:" + username);
    return "success";
}

如上的方法,能接受名为user的参数
@RequestParam有以下参数:

  • value:即接受的参数的名字
  • name:即value,value和name互为别名,且只能同时指定一个。
  • required:是否是必要的,默认为true,即不带指定参数时报错。
  • defaultValue:默认值,即不带user时,提供的默认值。

PS:@RequestParam和@PathVariable的区别:

  • @RequestParam:是从请求的参数里取的值
  • @PathVariable:是从请求地址的占位符里取得值
  • 两者都不能从对方的域中取值。
3. 通过@RequestHeader来获取请求头中的参数。
@RequestMapping("/headertest")
public String testHeader(@RequestHeader("User-Agent") String userAgent){
    System.out.println("使用的浏览器是" + userAgent);
    return "success";
}

如上方法可以获取请求头中User-Agent的信息。
@RequestHeader包含的参数和@RequestParam相同。

  • value:报文头中的参数
  • name:即value,value和name互为别名,且只能同时指定一个。
  • required:是否是必要的,默认为true,即不带指定参数时报错。
  • defaultValue:默认值,即不带指定参数时,提供的默认值。
4. 通过@CookieValue来获取请求头中的参数。
@RequestMapping("/cookietest")
public String testCookie(@CookieValue(value = "JSESSIONID", required = false, defaultValue = "123")String jid){
    System.out.println("Cookie中的jid为" + jid);
    return "success";
}

如上方法可以获取Cookie中JSESSIONID的值
@CookieValue参数和上面的相同。

5. 自动封装传入的参数为POJO

当设置请求的参数为POJO时,SpringMVC会尝试封装POJO的每一个属性,甚至是级联的属性,只要在表单设置好每个参数的名字,SpringMVC就能自动封装为POJO。当传入参数找不到POJO里的属性时,该属性就无法赋值。

Controller:
---------------------------------------------------------------
@RequestMapping(value = "/book",method = RequestMethod.POST)
public String addBook(Book book){
    System.out.println(book);
    return "success";
}
---------------------------------------------------------------
Book类:
---------------------------------------------------------------
public class Book {
    private String bookName;
    private String author;
    private Double price;
    private Address address;
}
---------------------------------------------------------------
Address类:
---------------------------------------------------------------
public class Address {
    private String province;
    private String city;
}
---------------------------------------------------------------
页面表单:
---------------------------------------------------------------
书名:
作者:
价格:

省份:
城市:
5. servlet原生API的使用

只要在Controller方法的入参声明了,就可以在方法内直接使用。

@RequestMapping("/originalapi")
public String usingOriginalApi(HttpServletRequest request,
                               HttpServletResponse response, HttpSession session){
    request.setAttribute("message", "this is request");
    session.setAttribute("message", "this is session");
    return "show";
}

如上,在入参声明了HttpServletRequest、HttpServletResponse、HttpSession就可以直接在方法内使用了。

6. 解决中文乱码问题
  1. get请求乱码
    通过在tomcat的server.xml配置文件中,配置URIEncoding="UTF-8"来解决get请求的乱码。

  1. post请求乱码
    其他请求因为也是从post请求包装来的,因此处理方法与post相同。解决方法如下:
    通过配置SpringMVC自带的CharacterEncodingFilter过滤器来解决乱码问题。

    CharacterEncodingFilter
    org.springframework.web.filter.CharacterEncodingFilter
    
    
        encoding
        UTF-8
    
    
    
        forceEncoding
        true
    


    CharacterEncodingFilter
    /*

源码中对这段转换的操作是这样的

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    if (this.encoding != null && (this.forceEncoding || 
                        request.getCharacterEncoding() == null)) {
        request.setCharacterEncoding(this.encoding);
        if (this.forceEncoding) {
            response.setCharacterEncoding(this.encoding);
        }
    }
    filterChain.doFilter(request, response);
}

PS:
    这里要注意的是,如果同时也配置了HiddenHttpMethodFilter,一定要将CharacterEncodingFilter配置在HiddenHttpMethodFilter前面(先对请求进行编码转换),自己配置的时候就是因为这个问题导致乱码的问题无法解决。
    我个人的理解是,在经过HiddenHttpMethodFilter包装后,被转发的不在是原本的request了,而此时对原本的request再进行编码转换是没有用的。

百度到的解释

这是因为(至少在tomcat里)

  • request对象的parameter并不是一开始就解析的,它是等你第一次调用“getParameter*等凡是 一切和获得请求参数有关的方法的时候才解析的
  • paramter一旦被解析过一次,那就不会再次被解析
  • 所以如果在CharacterEncodingFilter之前有另外一个filter,而这个filter调用了getParameter()方法,那么 就有可能使用错误的encoding来解析,从而曹成乱码问题。
    http://ju.outofmemory.cn/entry/133399

你可能感兴趣的:(SpringMVC学习笔记)