Spring 全家桶之 Spring Web MVC(二)- Restful

2022-08-19 16:15:43 浏览数 (1)

一、REST风格URL

创建一个新的Maven工程,导入依赖,添加Framework Support,选择Web,配置web.xml,创建Spring MVC的配置文件,点击Project Structure,在Artifacts目录下选择WEB-INF,点击创建lib文件夹,并将右侧的jar导入新建的lib文件夹下,配置Tomcat,配置项目请求地址为/,启动Tomcat

代码语言:javascript复制
@Controller
public class TeslaController {

    @RequestMapping(value = "/tesla/{name}", method = RequestMethod.GET)
    public String get(@PathVariable("name") String name){
        System.out.println("查询Tesla车型:"   name);
        return "success";
    }

    @RequestMapping(value = "/tesla", method = RequestMethod.POST)
    public String add(){
        System.out.println("增加Tesla车型");
        return "success";
    }

    @RequestMapping(value = "/tesla/{name}", method = RequestMethod.PUT)
    public String update(@PathVariable("name") String name){
        System.out.println("更新Tesla车型:"   name);
        return "success";
    }

    @RequestMapping(value = "/tesla/{name}", method = RequestMethod.DELETE)
    public String delete(@PathVariable("name") String name){
        System.out.println("删除Tesla车型:"   name);
        return "success";
    }
}

index.jsp页面

代码语言:javascript复制
<h3>查询Tesla</h3>
<a href="/tesla/cybertruck">Cybertruck</a>

<h3>增加Tesla车型</h3>
<form action="/tesla" method="post">
  <button type="submit">增加Semi Truck</button>
</form>

<h3>更新Tesla车型</h3>
<a href="/tesla/model3">更新Model 3</a>

<h3>删除Tesla车型</h3>
<a href="/tesla/roadster">删除Roadster</a>

逐个点击,查看控制台输出,其中更新和删除最终调用的是get()方法

想要从页面发起PUT和DELETE请求需要用到Spring MVC中的HiddenHttpMethodFilter,可以将普通请求转换为PUT和DELETE请求 在web.xml中配置Filter

代码语言:javascript复制
<!--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>

改造页面的请求,使用表单发起PUT和DELETE请求

代码语言:javascript复制
<h3>更新Tesla车型</h3>
<form action="/tesla/model3" method="post">
  <input type="hidden" name="_method" value="put">
  <button type="submit">更新Model 3</button>
</form>

<h3>删除Tesla车型</h3>
<form action="/tesla/roadster" method="post">
  <input type="hidden" name="_method" value="delete">
  <button type="submit">删除Roadster</button>
</form>

点击更新和删除按钮,控制台输出相应的内容

解决页面报错的问题,增加isErrorPage="true"

代码语言:javascript复制
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>

二、获取请求参数

默认方式获取请求中参数的值

  • 在方法入参中增加一个和请求中参数名相同的参数,就可以接收请求中参数的值
  • 如果请求中没有输入参数,则控制器方法中参数的值为null

新建一个ParamController

代码语言:javascript复制
@Controller
public class ParamController {

    @RequestMapping("/param")
    public String getParam(String username){
        System.out.println("请求中的传输的数据为:"   username);
        return "success";
    }
}

浏览器中输入http://localhost:8080/param?username=stark

@RequestParam注解获取请求中的参数的值

ParamsController中增加方法

代码语言:javascript复制
@RequestMapping("/param")
public String getParam(@RequestParam("user") String username){
    System.out.println("请求中的传输的数据为:"   username);
    return "success";
}

浏览器中输入http://localhost:8080/param?user=stark

@RequestParam("user")这句代码就相当于

代码语言:javascript复制
request.getParameter("user")
@RequestParam的属性
  • value:指定要获取参数的参数名
  • required:参数是否是必传的,默认为true,必传
  • defaultValue:指定参数默认值,默认为null
测试required属性

启动tomcat,浏览器输入http://localhost:8080/param, 不带user参数会报错

修改getParam方法,在@RequestParam中增加属性required=false,重启Tomcat,再次访问http://localhost:8080/param

不传user参数,页面不再报错,并且user默认的值为null

测试defaultValue属性

给getParam方法增加,defaultValue属性,defaultValue=“默认值”,浏览器输入http://localhost:8080/param, 控制台打印出设置的默认值

@RequestHeader注解获取请求头

获取请求中的Key的值,在ParamController中新增方法getHeaders

代码语言:javascript复制
@RequestMapping("/headers")
public String getHeaders(@RequestHeader(value = "User-Agent",required = false, defaultValue = "默认值") String userAgent){
    System.out.println("请求头中的Key User-Agent的值为:"   userAgent);
    return "success";
}

浏览器中输入http://localhost:8080/headers, 控制台中打印出User-Agent的值,与@RequestParam有三个同样的属性,且用法一致

@CookieValue注解获取Cookie信息

该注解用来获取Cookie中指定Key的值,在ParamController中增加getCookies方法

代码语言:javascript复制
@RequestMapping("/cookies")
public String getCookies(@CookieValue(value = "JSESSIONID",required = false, defaultValue = "默认值") String jsessionId){
    System.out.println("Cookies中的Key为JSESSIONID的值为:"   jsessionId);
    return "success";
}

浏览器中输入http://localhost:8080/cookies, 控制台打印出Cookie中的key的Value

Servlet API

Spring MVC 同样支持Servlet API,往request和session中保存数据,

代码语言:javascript复制
@RequestMapping("/servlet")
public String servletApi(HttpServletRequest request, HttpServletResponse response, HttpSession session){

    request.setAttribute("reqAttr","request中保存的数据");
    session.setAttribute("sessAttr","session中保存到数据");
    return "success";
}

取出session和request中保存的值,在success.jsp的body标签中中增加代码

代码语言:javascript复制
<h3>请求中保存的数据</h3>
<p>${requestScope.reqAttr}</p>
<h3>session中保存的数据</h3>
<p>${sessionScope.sessAttr}</p>

重启Tomcat,浏览器访问http://localhost:8080/servlet

Spring MVC 可以接收的 Servlet API参数,出了HttpServletRequest、HttpServletResponse、HttpSession外还有

  • java.security.Principal
  • Locale
  • InputStream
  • OutputStream
  • Reader
  • Writer

对象入参

增加一辆Tesla为例,前端增加输入Tesla信息的form表单,在index.jsp中改造增加Tesla表单的内容,增加Tesla信息输入框

代码语言:javascript复制
<h3>增加Tesla车型</h3>
<form action="/tesla" method="post">
  车型: <input type="text" name="name"> <br>
  价格: <input type="text" name="price"> <br>
  <hr>
  <button type="submit">增加Semi Truck</button>
</form>

新增entity包,新增一个Tesla对象,属性与表单中的填写的信息一致

代码语言:javascript复制
public class Tesla {

    private String name;
    private Double price;
    //此处省略getter/setter/toString信息
}    

修改TeslaController中的add方法

代码语言:javascript复制
@RequestMapping(value = "/tesla", method = RequestMethod.POST)
public String add(Tesla tesla){
    System.out.println("增加Tesla车型为:"   tesla);
    return "success";
}

重启tomcat,在表单中输入信息,并提交,控制台打印出提交的信息

说明请求中的属性会自动封装到POJO对象

给Tesla实体类增加一个owner属性,表示车主,并增加Owner实体类

代码语言:javascript复制
public class Owner {

    private String username;
    private Integer age;
    //省略getter/setter/toString方法
}    

表单增加owner信息输入框

代码语言:javascript复制
<h3>增加Tesla车型</h3>
<form action="/tesla" method="post">
  车型: <input type="text" name="name"> <br>
  价格: <input type="text" name="price"> <br>
  车主姓名: <input type="text" name="owner.username"> <br>
  车主年龄: <input type="text" name="owner.age">
  <hr>
  <button type="submit">增加Semi Truck</button>
</form>

重启Tomat,控制台输出Tesla级联属性Owner的信息

表单中输入中文,会出现乱码

中文乱码问题解决方法归类 请求乱码

  • GET请求乱码,修改Tomcat中的server.xml配置文件,在8080端口出增加URIEncoding="UTF-8"
  • POST请求乱码,在获取请求参数前增加request.setCharacterEncoding("UTF-8") 响应乱码
  • 代码最后增加response.setContenttype("text/html;charset=utf-8")

也可以在web.xml中配置过滤器解决乱码问题,解决乱码问题的filter一定要放在所有filter前,字符编码filter放在其他所有filter前面配置

代码语言:javascript复制
<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>

重启Tomcat,再次提交请求

三、Spring MVC 数据输出

如何将数据带到页面上?

Spring MVC出了可以通过request和session将数据带到页面上,还可以在方法处传入Map、Model、ModelMap,在这些参数中保存数据都会被放在请求域中,可以在页面获取

Map

新增一个OutputDataController,增加方法outputByMap方法

代码语言:javascript复制
@Controller
public class OutputDataController {

    @RequestMapping("/map")
    public String outputByMap(Map<String, Object> map){
        map.put("mapKey","map中保存的数据");
        return "success";
    }
}

页面获取数据

代码语言:javascript复制
<h3>Map中保存的数据</h3>
<p>从Request域中获取:${requestScope.msg}</p>
<p>从Session域中获取:${sessionScope.msg}</p>
<p>从PageContext域中获取:${pageScope.msg}</p>
<p>从Application域中获取:${applicationScope.msg}</p>

重启Tomcat,浏览器输入http://localhost:8080/map

只有从请求域中可以获取到数据

Model

新增方法outputByModel

代码语言:javascript复制
@RequestMapping("/model")
public String outputByModel(Model model){
    model.addAttribute("msg", "I am IRONMAN");
    return "success";
}

重启tomcat,浏览器访问

ModelMap

ModelMap是Model接口的实现类,也可以用作数据输出

代码语言:javascript复制
@RequestMapping("/model_map")
public String outputByModelMap(ModelMap modelMap){
    modelMap.addAttribute("msg", "I am IRONMAN");
    return "success";
}

重启tomcat,浏览器访问

在三个方法中打印map、model、modelMap的class,重启后在浏览器请求三个方法上标注的URL地址

Map、Model、ModelMap最终都是BindingAwareModelMap在实际发挥作用

Spring MVC还可以使用其他方式输出数据

  • ModelAndView:处理方法值返回类型为ModelAndView,方法可以通过该对象添加数据及返回的页面
  • @SessionAttributes:将数据存储到Session中,多个请求之间可以共享数据,不推荐使用
  • @ModelAttribute:方法如惨标注后,入参的对象就可以方法数据模型中,不常用

ModelAndView

页面和数据的合体对象,创建ModelAndView对象时传入的参数就是一个页面,也就是要返回的页面

代码语言:javascript复制
@RequestMapping("model_and_view")
public ModelAndView outputByModelAndView(){
    ModelAndView modelAndView = new ModelAndView("success");
    modelAndView.addObject("msg","I am IRONMAN");
    return modelAndView;
}

重启tomcat,浏览器输入http://localhost:8080/model_and_view

@SessionAttributes

新建一个类,增加@SessionAttributes注解,@SessionAttributes注解只能放在类上

代码语言:javascript复制
@SessionAttributes(value = "msg")
@Controller
public class SessionController {

    @RequestMapping("/session_attributes")
    public ModelAndView outputBySession(){
        ModelAndView modelAndView = new ModelAndView("success");
        modelAndView.addObject("msg","I am God of Thunder");
        return modelAndView;
    }

    @RequestMapping("/user")
    public ModelAndView getUser(){
        ModelAndView modelAndView = new ModelAndView("success");
        return modelAndView;
    }
}

先访问http://localhost:8080/session_attributes

在访问http://localhost:8080/user

都可以获取到session中保存的数据

@SessionAttributes有两个属性 value:只要保存的Key是value指定的,就将它保存在Session中 types:只要保存的是指定类型的资源,就将它保存在Session中

测试types属性

代码语言:javascript复制
@SessionAttributes(types = Tesla.class)
@Controller
public class SessionController {

    @RequestMapping("/session_attributes")
    public ModelAndView outputBySession(){
        ModelAndView modelAndView = new ModelAndView("success");
        modelAndView.addObject("msg","I am God of Thunder");
        return modelAndView;
    }

    @RequestMapping("/user")
    public ModelAndView getUser(){
        ModelAndView modelAndView = new ModelAndView("success");
        return modelAndView;
    }

    @RequestMapping("/session/tesla")
    public ModelAndView getTesla(){
        ModelAndView modelAndView = new ModelAndView("success");
        Tesla tesla = new Tesla();
        tesla.setName("Model 3");
        modelAndView.addObject("msg", tesla);
        return modelAndView;
    }
}

重启Tomcat,分被在浏览器中输入三个地址

可以看出在Session中存储的是types指定的Tesla数据类型

@SessionAttribute不推荐使用,推荐使用原生API

0 人点赞