SpringMVC返回值类型
控制方法返回值为字符串
返回带有前缀的字符串:
转发:forward:/WEB-INF/views/index.jsp
重定向:redirect:/index.jsp
/**
* 指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/pages/success.jsp
*/
@RequestMapping("/str")
public String respStr(User user,HttpSession session){
System.out.println("aaaaaaaaaaaa");
session.setAttribute("logined",user);
return "success";
}
控制方法无返回值
Servlet原始API可以作为控制器中方法的参数,在controller方法形参上可以定义request和response,使用request或response指定响应结果:
1. 使用request转发跳转
/**
* 返回值如果是void,则方法名称作为视图名称
* 可以通过重定向和转发实现页面跳转
*
*/
@RequestMapping("/void")
public void respStr(User user, HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
System.out.println("aaaaaaaaaaaa");
request.setAttribute("logined",user);
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
}
2. 使用response重定向跳转
response.sendRedirect("testRetrunString")
需要注意的是 : 重定向不能访问到WEB-INF目录下的资源
/**
* 返回值如果是void,则方法名称作为视图名称
* 可以通过重定向和转发实现页面跳转
*/
@RequestMapping("/void")
public void respStr(User user, HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
//业务操作...
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
3. 使用response直接响应数据
/**
* 返回值如果是void,则方法名称作为视图名称
* 可以通过重定向和转发实现页面跳转
*/
@RequestMapping("/void")
public void respStr(User user, HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
//业务操作...
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
}
控制方法返回ModelAndView
ModelAndView是SpringMVC为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
他其中有二个常用方法:
方法名称 | 作用 |
---|---|
addObject(String name,Object value) | 向Model中设置值 |
setViewName(String viewName) | 设置需要跳转的视图名称 |
/**
* @return ModelAndView 可以设置数据与跳转视图
*/
@RequestMapping("/mv")
public ModelAndView mv(User user) throws ServletException, IOException {
ModelAndView mv = new ModelAndView();
//将数据保存到Model中
mv.addObject("logined", user);
//设置视图名称
mv.setViewName("success");
return mv;
}
SpringMVC页面跳转方式
controller方法在提供了String类型的返回值之后,默认就是请求转发。我们也可以写成:
转发跳转页面
/**
* 返回值如果是void,则方法名称作为视图名称
* 可以通过重定向和转发实现页面跳转
*/
@RequestMapping("/forward")
public String forward(User user,HttpSession session) throws ServletException, IOException {
//将数据保存到session中
session.setAttribute("logined", user);
return "forward:/WEB-INF/pages/success.jsp";
}
需要注意的是,如果用了formward:则路径必须写成实际视图url,不能写逻辑视图。
它相当于“request.getRequestDispatcher("url").forward(request,response)”。
使用请求转发,既可以转发到jsp,也可以转发到其他的控制器方法。
重定向跳转页面
contrller方法提供了一个String类型返回值之后,它需要在返回值里使用:redirect:
/**
* 返回值如果是void,则方法名称作为视图名称
* 可以通过重定向和转发实现页面跳转
*/
@RequestMapping("/redirect")
public String redirect(User user,HttpSession session) throws ServletException, IOException {
//将数据保存到session中
session.setAttribute("logined", user);
return "redirect:/index.jsp";
}
它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到jsp页面,则jsp页面不能写在WEB-INF目录中,否则无法找到。
SpringMVC响应JSON格式数据
添加依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
过滤静态资源
<!--配置资源目录,springMVC框架不拦截-->
<!--js目录下的所有资源不拦截-->
<mvc:resources mapping="/js/**" location="/js/**"></mvc:resources>
<!--imgs目录下的所有资源不拦截
<mvc:resources mapping="/imgs/**" location="/imgs/**"></mvc:resources>
-->
<!--css目录下的所有资源不拦截
<mvc:resources mapping="/css/**" location="/css/**"></mvc:resources>
-->
<!--开放资源的访问也可以这样配-->
<mvc:default-servlet-handler/>
发送异步请求
<h1>用户登录功能---异步ajax请求,响应json格式数据</h1>
<input id="btn" type="button" value="点击异步获取数据">
<script src="js/jquery-3.3.1.min.js"></script>
<script>
$(function(){
$("#btn").click(function () {
//发送异步请求
var url = "${pageContext.request.contextPath}/response/json";
var params = "{username:'zs',password:'123456'}";
$.ajax({
type:"POST",
url: url,
data: params,
contentType:"application/json;charset=utf-8",
dataType:"json",
success: function(data){
alert(data)
}
});
})
})
</script>
响应JSON格式数据
/**
* @RequestBody注解 可以将发送到服务器的json格式数据封装到参数中
* @ResponseBody注解 可以将响应的对象转化为json格式数据响应给客户端
* @param user
* @return
*/
@RequestMapping("/json")
public @ResponseBody User json(@RequestBody User user){
System.out.println(user);
user.setUsername("张三");
user.setPassword("456789");
return user;
}
@RequestBody注解 可以将发送到服务器的json格式数据封装到参数中
@ResponseBody注解 可以将方法返回的对象转化为json格式数据响应给客户端
SpringMVC请求参数
参数绑定机制
1. 表单提交的数据都是k=v格式的 username=haha&password=123
2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
参数绑定要求
1. 提交表单的name和参数的名称是相同的
支持的数据类型
1. 基本数据类型和字符串类型
2. 实体类型(JavaBean)
3. 集合数据类型(List、map集合等)
请求绑定基本数据类型和字符串
客户端
<h1>根据id查询用户</h1>
<a href="${pageContext.request.contextPath}/user/findById?id=1">根据id查询用户</a>
<h1>根据用户名和密码查询用户</h1>
<a href="${pageContext.request.contextPath}/user/findByUsername?username=aaa&password=123">根据id查询用户</a>
服务器
@RequestMapping("/user")
public class UserController {
@RequestMapping(path = "/findById",params = {"id"})
public String findById(Integer id){
System.out.println(id);
System.out.println("查询所有用户....");
return "success" ;
}
@RequestMapping(path = "/findByUsername")
public String findByUsername(String username,String password){
System.out.println(username+" "+password);
System.out.println("查询所有用户....");
return "success" ;
}
}
请求参数绑定实体类型
定义实体类
package com.itheima.bean;
public class User {
private String username ;
private String password ;
private int age ;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
}
客户端
<h1>添加用户</h1>
<form action="${pageContext.request.contextPath}/user/add">
用户名: <input type="text" name="username"> <br>
密 码: <input type="password" name="password"><br>
年 龄: <input type="text" name="age"><br>
<input type="submit" value="注册">
</form>
服务器
/**
* @param user 封装数据的实体对象
* @return
*/
@RequestMapping(value = "/add")
public String add(User user){
System.out.println(user);
System.out.println("添加用户....");
return "success" ;
}
注意:
- 提交表单的name和JavaBean中的属性名称需要一致
- JavaBean中的属性类型如果使用基本类型,如果没有该参数程序会报错
请求参数绑定List集合类型
创建实体类
public class Order {
private String ono ;
private Double money ;
public String getOno() {
return ono;
}
public void setOno(String ono) {
this.ono = ono;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
@Override
public String toString() {
return "Order{" +
"ono='" + ono + '\'' +
", money=" + money +
'}';
}
}
实体类型添加集合
[图片上传失败...(image-818d50-1700092477968)]
客户端
<h1>添加用户及订单</h1>
<form action="${pageContext.request.contextPath}/user/addWithOrders">
用户名: <input type="text" name="username"> <br>
密 码: <input type="password" name="password"><br>
年 龄: <input type="text" name="age"><br>
订单1编号: <input type="text" name="orders[0].ono"><br>
订单1金额: <input type="text" name="orders[0].money"><br>
订单2编号: <input type="text" name="orders[1].ono"><br>
订单2金额: <input type="text" name="orders[1].money"><br>
<input type="submit" value="注册">
</form>
服务端
@RequestMapping("/addWithOrders")
public String addWithOrders(User user){
System.out.println(user);
System.out.println(user.getOrders());
System.out.println("添加用户....");
return "success" ;
}
请求参数绑定Map集合类型
客户端
<h1>添加用户及订单</h1>
<form action="${pageContext.request.contextPath}/user/addWithOthers">
用户名: <input type="text" name="username"> <br>
密 码: <input type="password" name="password"><br>
年 龄: <input type="text" name="age"><br>
订单1编号:<input type="text" name="others[o1].ono"><br>
订单1金额: <input type="text" name="others[o1].money"><br>
订单2编号:<input type="text" name="others[o2].ono"><br>
订单2金额: <input type="text" name="others[o2].money"><br>
<input type="submit" value="注册">
</form>
服务端
@RequestMapping("/addWithOthers")
public String addWithOthers(User user){
System.out.println(user);
System.out.println(user.getOthers());
System.out.println("添加用户....");
return "success" ;
}
请求参数的中文乱码问题
如果请求参数中携带了中文会产生中文乱码问题,这个时候我们配置类乱码过滤器就可以解决POST方式的中文乱码问题.
tomcat7及以下版本需要手动解决中文乱码问题
在web.xml
中添加以下配置:
<!--解决中文乱码-->
<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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
自定义类型转换器
自定义类型转换器
在springMVC封装传递的参数有时候需要自己写一个类型转换器来实现
基本步骤
1. 创建一个类实现实现`Converter`接口
2. 实现`convert`方法,方法的参数就是传入的需要转换的数据,方法的返回值就是转换成功之后的数据
3. SpringMVC的配置文件中配置自定义转换器
4. 修改`<mvc:annotation-driven>`标签让自定义转换器生效
代码示例
1. 创建一个类实现实现Converter
接口
public class DateConverter implements Converter<String,Date> {
/**
*
* @param source 传入的需要转化的数据,例如:2018-01-01
* @return 转化之后的数据
*/
@Override
public Date convert(String source) {
return null;
}
}
2. 实现convert
方法,方法的参数就是传入的需要转换的数据,方法的返回值就是转换成功之后的数据
/**
*
* @param source 传入的需要转化的数据,例如:2018-01-01
* @return 转化之后的数据
*/
@Override
public Date convert(String source) {
if(source!=null){
DateFormat df=new SimpleDateFormat("yyyy-MM-dd");
try{
//把字符串转为日期
return df.parse(source);
}catch (Exception e){
new RuntimeException("数据类型转换失败!");
}
}else{
System.out.println("请传入数据!");
}
return null;
}
3. SpringMVC的配置文件中配置自定义转换器
<!--配置自定义转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.itheima.convert.DateConverter"></bean>
</set>
</property>
</bean>
4. 修改<mvc:annotation-driven>
标签让自定义转换器生效
<!--SpringMVC注解驱动-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
获得原生servletAPI
Spring MVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入, 常用的对象如下:
支持原始ServletAPI对象有:
HttpServletRequest
HttpServletResponse
HttpSession
InputStream
OutputStream
Reader
Writer
我们可以把上述对象,直接写在控制的方法参数中使用。
[图片上传失败...(image-4809cf-1700092477968)]
SpringMVC常用注解
1. @RequestParam
作用: 把请求中指定名称的参数给控制器中的形参赋值。
属性:
value:请求参数中的名称。
required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错。
defaultValue:给入参设置默认值
客户端
<!-- requestParams注解的使用 -->
<a href="${pageContext.request.contextPath}/user/login2?name=aaa&password=123">requestParam注解</a>
服务端
@RequestMapping("/login2")
public String login2(@RequestParam("name") String username, String password,@RequestParam(value = "age",required = false)Integer age){
System.out.println(username+" "+password);
System.out.println("用户登录....");
return "success" ;
}
2. @RequestBody
作用: 用于获取请求体内容。直接使用得到是key=value&key=value...结构的数据。 get请求方式不适用。
属性:
required:是否必须有请求体。默认值是:true。当取值为true时,get请求方式会报错。如果取值为false,get请求得到是null。
3. @PathVariable注解
作用
用于绑定url中的占位符。例如:请求url中 /delete/{id},这个{id}就是url占位符。
url支持占位符是spring3.0之后加入的。是springmvc支持rest风格URL的一个重要标志。
属性
value:指定url中的占位符名称
required:是否必须提供占位符。
restful风格的URL:请求路径一样,可以根据不同的请求方式去执行后台的不同方法
1. 结构清晰
2. 符合标准
3. 易于理解
4. 扩展方便
客户端
<h1>restfull</h1>
<a href="${pageContext.request.contextPath}/user/find/1">查询用户</a>
服务器
@RequestMapping("/find/{id}")
public String find(@PathVariable("id") Integer id){
System.out.println(id);
return "success" ;
}
REST风格URL
Restful是一种软件架构风格、设计风格, 而不是标准, 只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
Restful风格的请求是使用“url+请求方式”表示一次请求目的的, HTTP协议里面四个表示操作方式的动词如下:
GET:用于获取资源
POST:用于新建资源
PUT:用于更新资源
DELETE:用于删除资源
例如:
/user/1 GET:得到id=1的user
/user/1 DELETE:删除id=1的user
/user/1 PUT:更新id=1的user
/user POST:新增user
上述url地址/user/1中的1就是要获得的请求参数, 在Spring MVC中可以使用占位符进行参数绑定。地址/user/1可以写成/user/{id} ,占位符{id} 对应的就是1的值。在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取操作。
4. @RequestHeader注解
作用: 用于获取请求消息头。
属性:
value:提供消息头名称
required:是否必须有此消息头 注: 在实际开发中一般不怎么用。
@RequestMapping("/headers")
public String headers(@RequestHeader("User-Agent")String agent){
System.out.println(agent);
return "success" ;
}
5. @CookieValue注解
作用: 用于把指定cookie名称的值传入控制器方法参数。
属性:
value:指定cookie的名称。
required:是否必须有此cookie。
@RequestMapping("/cookies")
public String cookies(@CookieValue("JSESSIONID")String sessionID){
System.out.println(sessionID);
return "success" ;
}