一、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