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

SpringMVC详解(二)

程序员文章站 2022-06-11 22:41:23
...

上一篇文章让我们初步的了解了Spring MVC与Servlet&JSP处理请求的不同,以及简单的学习了Spring MVC处理请求的方式。这一章我们来学习些它的常用的知识点。

常用知识点

定义Controller

@Controller
public class OwnerController {

    @GetMapping("/hello/{petId}")
    public String hello() {
        // ...
    }
}

处理请求

在Controller的方法上添加@RequestMapping注解

@RequestMapping("/hello")
    public String hello() {
        return "hello";
    }

获取请求参数

请求参数可以直接定义到方法参数里,并通过@RequestParam("key")注解修饰参数,这样SpringMVC会自动解析请求中的参数给你填充到方法参数中。

**注意:**此注解修饰的参数默认是必传的,如果请求中没有此参数会直接报错,可以通过设置此注解的required属性为false解决

@RequestMapping("/login")
    public String test(int age, String name, @RequestParam(value = "nickname", required = false) String nickName, Model model) {
        System.out.println("login, age: " + age+", name: " + name+", nickName: " + nickName);
        // 放到request作用域中,可以在前端获取
        model.addAttribute("msg", age);
        return "main";
    }

JDK1.8以后我们也可以通过添加编译参数-parameters参数告诉编译器在编译时保留方法参数名,这样如果请求中参数名与方法定义的参数名对应时,可以不用显示添加@RequestParam注解

获取请求头参数

如果想获取请求头中携带的参数,springmvc给我们提供了一个@RequestHeader注解,此注解和@RequestParam一样默认参数必传,同样可以选择使用required属性解决,使用方式如下:

@RequestMapping("/header")
public String getVarFromRequestHead(@RequestHeader(value = "sname", required = false) String sname, Model model) {
    model.addAttribute("sname", sname);
    System.out.println("sname: " + sname);
    return "hello";
}

一般请求头参数的用法测试需要用到专门的发送请求的工具,我使用的是PostMan这款软件,用法是新建请求后在Head里添加参数sname,访问地址是:http://localhost:8080/header

获取URI中的变量

这个作用通常用于restFul服务,可以通过@PathVariable注解获取到请求uri中的变量

@RequestMapping("/path_var/{sname}/{age}")
public String getVarFromUri(@PathVariable("sname") String sname, @PathVariable("age") Integer age, Model model) {
    model.addAttribute("sname", sname);
    model.addAttribute("age", age);
    System.out.println("sname: " + sname + "age: " + age);
    return "hello";
}

获取Cookie数据

Cookie中的数据同样可以获取到,只需要一个@CookieValue注解就能做到,示例如下:

@RequestMapping("/cookie/attr")
public String getAttrFromCookie(@CookieValue("sname") String sname, Model model) {
    model.addAttribute("sname", sname);
    System.out.println("sname: " + sname);
    return "hello";
}

测试我们还是选择使用刚才提到的postMan测试工具,新建请求后,添加一个Cookie后只需要修改cookie的key和value就行,访问路径:http://localhost:8080/cookie/attr

获取作用域数据

这里的作用域主要指request 作用域和session作用域,不包括application作用域

获取request作用域数据

可以使用@RequestAttribute注解获取作用域中的对应属性的值,示例:

@RequestMapping("/scope/request/attr")
public String getAttrFromScope(@RequestAttribute(value = "sname", required = false) String sname, Model model) {
    model.addAttribute("sname", sname);
    System.out.println("sname: " + sname);
    return "hello";
}

这个测试就需要在jsp页面添加一个属性到request作用域中

<% request.setAttribute("sname","张三"); %>

访问路径:http://localhost:8080/scope/request/attr

获取session作用域数据

可以使用@SessionAttribute注解获取作用域中的对应属性的值,示例:

@RequestMapping("/scope/session/attr/")
public String getAttrFromScope(@SessionAttribute(value = "sname", required = false) String sname, Model model) {
    model.addAttribute("sname", sname);
    System.out.println("sname: " + sname);
    return "hello";
}

这个测试就需要在jsp页面添加一个属性到request作用域中

<% session.setAttribute("sname","张三"); %>

访问路径:http://localhost:8080/scope/session/attr

使用提前初始化的数据

初始化数据、参数,在方法上添加@ModelAttribute注解。

/**
 * 使用一个Model中提供的Map
 */
@ModelAttribute
public Model prepareData() {
    Model model = new ConcurrentModel();
    model.asMap().put("sname", "sss");
    return model;
}
/*
或者使用一个HashMap

@ModelAttribute
public Map<String, String> prepareData() {
    Map<String, String> data = new HashMap<>();
    data.put("sname", "张四丰");
    return data;
}*/

使用当前Controller中通过@ModelAttribute注解预初始化的数据

@RequestMapping("/model/attr")
public String testModelAttr(@ModelAttribute Model model, Model modelToView) {
    modelToView.addAttribute("sname", model.asMap().get("sname"));
    System.out.println("model key: sname->" + model.asMap().get("sname"));
    return "hello";
}
/*
直接使用HashMap的方式
 
@RequestMapping("/model_attr")
public String testModelAttr(@ModelAttribute Map<String, String> data, Model model) {
    System.out.println("model key: sname ->" + data.get("sname"));
    model.addAttribute("sname", data.get("sname"));
    return "hello";
}*/

**注:**如果使用Model提供的asMap方法,则测试时的第二个Model参数不能省略,因为使用@ModelAttribute注解后Model会变成一个只具有Map功能的Model,不再具有与视图解析器传递参数的功能,因此,此时如果想把数据放到作用域中传到前端,则只能再加一个Model参数。

测试的访问路径:http://localhost:8080/model/attr

请求参数自动绑定到对象中

如果RequestMapping方法的参数中是一个自定义的对象,Spring会调用DataBinder自动将请求中的参数注入到对象的同名属性中。
使用示例:

@RequestMapping("/test/bind_obj")
    public String testBindObject(Student student, Model model) {
        System.out.println("testBindObject, student: " + student);
        model.addAttribute("msg", student);
        return "main";
}

访问地址:

http://localhost:8080/test/bind_obj?sname=张三&age=34&id=2

通用无逻辑页面跳转

如果我们有些请求只是想跳转页面,不需要来后台处理什么逻辑,我们无法在Action中写一个空方法来跳转,直接在中配置一个如下的视图跳转控制器即可(不经过Action,直接跳转页面)

<mvc:view-controller path="/" view-name="home"/>

重定向

请求处理方法返回的视图名前添加redirect前缀

内部地址:

return "redirect:/myapp/some/resource"

外部地址:

return "redirect:https://myhost.com/some/arbitrary/path"

请求处理方法返回RedirectView对象

内部地址:

return new RedirectView("/myapp/some/resource");

外部地址:

return new RedirectView("https://myhost.com/some/arbitrary/path");

请求转发

请求处理方法返回的视图名前添加forward前缀

示例:

return "forward:/WEB-INF/pages/main";

请求处理方法返回InternalResourceView对象

直接返回一个页面的名称,默认会使用forward方式通过视图解析器转发到对应的页面,示例:

return "main";

放行静态资源

默认Tomcat是可以处理静态资源的(通过DefaultServlet处理,在%tomcat_home%/conf/web.xml中),但是我们配置了SpringMVC后, 往往会将DispatcherServlet的拦截路径设置成"/",会将Tomcat中默认的DefaultServlet覆盖掉,所以静态资源也会进入DispatcherServlet中处理,而默认DispatcherServlet中是没有处理静态资源相关的逻辑, 所以访问静态资源就会报404

第一种解决方式:

<mvc:default-servlet-handler />

将静态资源交还给容器来处理(比如说Tomcat就是让DefaultServlet来处理)

  • 优点:配置简单
  • 缺点:只能访问web根目录下公开的静态文件, WEB-INF、类路径下都无法访问

第二种解决方式:

<mvc:resources mapping="/static/views/**" location="WEB-INF/views/,classpath:/static/" />

放行静态资源, mapping匹配你请求的URI; location指定静态资源相对位置,会将mapping中通配部分的内容拼到location指定的相对位置后面

到此,我们已经基本上可以处理前后端交互时的常见请求了,那么Spring MVC就这点东西了吗?当然不可能,所以下一章就是一些进阶的知识了。

--------------------------->>Spring MVC详解(三)<<-----------------------------