一:Springmvc的数据响应
响应形式分类如下
- 1、页面跳转
- 直接返回字符串
- 通过ModelAndView对象返回
- 2、直接响应数据(都不用去找页面的)
- 直接返回字符串
- 返回对象或集合 (本质上还是返回字符串)
1.1:演示环境搭建
步骤:
1.使用maven骨架创建一个javaweb工程
2.导入spring-context(基础包)和spring-webmvc(DispatcherServlet)
3.在web.xml中配置DispatcherServlet
4.写Controller,然后使用@Controller标注,
5.配置spring-mvc.xml文件
6.最终使用tomcat部署,找到Deployment -> 加号 -> 选择xxx:war exploded
注:
1、其实每一步都是有关联的,就像上面为什么要导入spring-context和spring-webmvc呢?
因为spring-context是一个基础包不仅是加载spring配置文件的时候需要它,而且就算使用后面的@Controller
也是需要它的,那么spring-webmvc呢?因为第三步需要使用到DispatcherServlet,还由于使用了@controller,所以还需要在spring-mvc.xml中配置组件扫描,都是一些因为所以的关系!2、有时候你使用一个东西的时候,你脑海中始终要有这几个疑问,它是干什么的,不用它行不行,不要一上来想都没想就直接配,就想我之前一样,在使用springmvc的时候,一股脑的把 web.xml中spring和springmvc配置一起配了,其实在演示springmvc的一些功能时,不用启动spring也可以
1.2:页面跳转
1.2.1:直接返回字符串
- 情况一:没有配置
InternalResourceViewResolver
中的prefix
和suffix
参数的时候
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/mode1")
public String mode1(){
return "success.jsp";
}
}
这时默认去
webapp
找该success.jsp
页面,但是由于类上加了一个@RequestMapping("/user")
所以此时在浏览器上请求该地址的时候
https:localhost:8080/user/mode1
,服务器会找
webapp/user/success.jsp
返回给客户端,找不到资源就返回404
- 细节
1.其实视图解析器不用配置,默认就有,可以在DispatcherServlet.properties查看,而且就是InternalResourceViewResolver这个视图解析器,之所以一上来有时候就配置prefix和suffix,是为了开发的方便,但是有时候这样却导致很多人以为这东西是必须配置的,不配就不行。
2.InternalResourceViewResolver的父类中,可以查看到
public static final String REDIRECT_URL_PREFIX = "redirect:";
public static final String FORWARD_URL_PREFIX = "forward:";
private String prefix = "";
private String suffix = "";
- 情况二:直接返回字符串的时候使用
forward
和redirect
@Controller
public class UserController {
@RequestMapping("/mode1")
public String mode1(){
return "redirect:success.jsp";
}
@RequestMapping("/mode2")
public String mode2(){
return "success.jsp";
}
@RequestMapping("/mode3")
public String mode3(){
return "forward:success.jsp";
}
}
其实这里都是找webapp/success.jsp的资源,mode1使用重定向所以浏览器地址栏会变化
而model2和model3访问后地址都不会发生变化,说明model2默认就是
forward
的效果
- 情况三:指定
InternalResourceViewResolver
中的prefix
和suffix
参数后
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
@Controller
public class UserController {
@RequestMapping("/mode1")
public String mode1(){
return "success";
}
}
因为配置了前缀和后缀,所以此时访问的资源路径是
/WEB-INF/jsp/
success.jsp
1.2.2:通过ModelAndView对象返回
@Controller
public class UserController {
@RequestMapping("/mode1")
public ModelAndView mode1(){
ModelAndView mv = new ModelAndView();
mv.setViewName("success");
mv.addObject("username","wzj");
return mv;
}
@RequestMapping("/mode2")
public String mode2(ModelAndView mv){
mv.addObject("username","wzj");
return "success";
}
@RequestMapping("/mode3")
public String mode3(Model model){
model.addAttribute("username","wzj");
return "success";
}
@RequestMapping("/mode4")
public String mode4(HttpServletRequest request){
request.setAttribute("username", "wzj");
return "success";
}
}
- success页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>SUCCESS</h1>
${username}
</body>
</html>
使用了
EL表达式
,注意加上isELIgnored="false"
,或者将web.xml中的头部声明更换为3.0,或者更高!一劳永逸
- 分析
1. mode1中的mv.setViewName("success");
这里其实就是根据我们配置的视图解析的前缀和后缀去寻找的jsp
2.除了mode2,其他几个最终在页面都可以显示出${username}的值wzj
3.使用HttpServletRequest的时候需要导入servlet-api和jsp-api的
4.ModelAndView的变形写法还有很多,会一些常用的即可!
1.3:回写数据
1.3.1:直接返回字符串
@Controller
public class UserController {
@RequestMapping("/mode1")
public void mode1(HttpServletResponse response) throws IOException {
response.getWriter().println("hello world");
}
@RequestMapping("/mode2")
public String mode2(){
return "hello world";
}
@RequestMapping("/mode3")
@ResponseBody
public String mode3(){
return "hello world";
}
@RequestMapping("/mode4")
@ResponseBody
public String mode4(){
return "{\"username:wzj\",\"password:123456\"}";
}
@RequestMapping("/mode5")
@ResponseBody
public String mode5() throws JsonProcessingException {
User user = new User();
user.setUsername("wzj");
user.setPassword("123456");
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(user);
return jsonStr;
}
@RequestMapping("/mode6")
@ResponseBody
public User mode6(){
User user = new User();
user.setUsername("wzj");
user.setPassword("123456");
return user;
}
@RequestMapping("/mode7")
@ResponseBody
public List<User> mode7(){
List<User> users = new ArrayList<>();
User user1 = new User();
user1.setUsername("wzj");
user1.setPassword("123456");
User user2 = new User();
user2.setUsername("dyt");
user2.setPassword("abcdef");
users.add(user1);
users.add(user2);
return users;
}
}
- 方式一:使用HttpServletResponse
页面直接输出hello world,注意方法是无返回值类型void
- 方式二:
页面报错404,找不到
/WEB-INF/jsp/hello world.jsp
,没加@ResponseBody
,把hello world当成了一个逻辑视图名
- 方式三:使用@ResponseBody
页面输出 hello world,因为加了
@ResponseBody
注解,它告知SpringMVC框架,方法返回的字符串不是跳转是直接在http响应体中返回
- 方式四:输出json字符串
页面输出了{"username:wzj","password:123456"}
- 方式五:手动使用jackson将对象转换为json字符串输出
因为我的方法返回值是String类型,不能返回一个对象,所以我们只能将对象转换为json串,怎么转换呢?
使用我们的
jackson
当然这时需要导入jar包的!,本质上其实还是返回一个字符串,记得加@ResponseBody
注解,不然它会把你这一堆字符串,当成一个逻辑视图名去找了,到时候又是404的节奏
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
- 方式六
每次返回对象的时候,都需要转换为手动转换为json字符串这么麻烦,其实这么通用的东西,作为springmvc框架,它早就为你想好了,只需在
RequestMappingHandlerAdapter
中配置一下HttpMessageConverter
接口的实现类MappingJackson2HttpMessageConverter
消息转换器即可,就会自动将你的对象返回成json串
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter{
private List<HttpMessageConverter<?>> messageConverters;
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = messageConverters;
}
}
可以参照以上代码进行set注入等配置,RequestMappingHandlerAdapter不是自定义bean,所以一般就使用bean标签进行配置了
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
</list>
</property>
</bean>
-
方式七:将List转换成字符串
-
注意:其实可以使用
<mvc:annotation-driven/>
去代替上面配置的MappingJackson2HttpMessageConverter
<mvc:annotation-driven/>
1.<mvc:annotation-driven/>的作用:
在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。
使用<mvc:annotation-driven>自动加载 RequestMappingHandlerMapping(处理映射器)和
RequestMappingHandlerAdapter( 处 理 适 配 器 )而且默认底层就会集成jackson进行对象或集合的json格式字符串的转换
注:在这里启动服务器时抛出一个异常,Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘cacheManager’ available,最终是mvc的命名空间和约束搞错了,TMD的这个xml要不报错提示,找了半天!
最后:来自虽然帅,但是菜的cxy,创作不易,给点鼓励。