springMVC整理03--处理数据模型 & 试图解析器 & @ResponseBody & HttpEntity
2021-07-03 11:05
标签:entity 测试 manage user onclick prefix 创建 convert Fix SpringMVC 中的模型数据是非常重要的,因为 MVC 中的控制(C)请求处理业务逻辑来生成数据模型(M),而视图(V)就是为了渲染数据模型的数据。当有一个查询的请求,控制器(C)会把请求拦截下来,然后把根据请求的内容对它进行分配适合的处理方法,在处理方法上进行处理查询的业务逻辑,得到了数据,再把数据封装成数据模型对象,最后把数据模型(M)对象传给了视图(V),让视图去渲染数据模型。SpringMVC 提供了以下几种途径输出模型数据: 1.1 Map 和 和 Model 入参 测试页面: 运行结果:访问 map.html 或 model.html 的时候,页面上显示:name=aaa id=123 1.2ModelAndView ModelAndView 既包含数据模型,又包含视图信息 1.3 @SessionAttributes 若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes,SpringMVC 将在模型中对应的属性暂存到 HttpSession 中。 – @SessionAttributes(types=Dept.class) 会将隐含模型中所有类型为 Dept.class 的属性添加到session 中。 测试方法: 测试页面: 运行效果: 可以看到模型中的属性都放到了request的域中。@SessionAttributes中没有声明other,所以 session 中的 other 是空的。 1.4 @ModelAttribute 1.4.1 方法参数上使用@ ModelAttribute 在参数前使用@ModelAttribute,在进去方法时可以通过参数给对象赋值,如下面的代码,当请求/model1.html?id=1 的时候,会给 dept 的 id 属性赋值。在方法中可以对 dept 做进一步的处理。@ModelAttribute 可以自动将被注解的对象作为数据模型返回给页面。 测试页面 model.jsp,使用 EL 表达式取值 : 运行结果 1.4.2 定义方法时使用@ ModelAttribute 在方法上使用@ModelAttribute 后,执行这个 Controller 的任意一个方法之前,都会调用这个方法给对象赋值。 对于Controller的目标方法,无论其返回值是String、View、ModelMap或是ModelAndView,SpringMVC 都会在内部将它们封装为一个 ModelAndView 对象进行返回。 View ---View 接口表示一个响应给用户的视图,例如 jsp 文件,pdf 文件,html 文件等。 2.1 ViewResolver 2.1.1 InternalResourceViewResolver 如果配置了上面的解析器,Controller中返回字符串就不需要写/index.jsp了,直接返回“index”,就会按照/index.jsp 去解析 2.1.2 MappingJackson2JsonView 2.1.3 FreeMarkViewResolver 使用 FreeMarker 模板生成静态网页,需要在 springMVC-servlet.xml 中配置: 在 WEB-INF/ftl 下创建模板文件 hello.ftl: 通过模板生成静态网页: 在 F 盘下就能看到 spring-freemark.html 文件了 以上是生成静态网页的配置。 order 越小,视图解析器的优先级就越高。 运行结果: 2.1.4 BeanNameViewResolver 自定义一个视图,然后声明成 bean,Controller 中返回这个 bean 的名字,就可以显示当前的视图: springMVC-servlet.xml 中配置: Controller 运行结果: 2.2 自定义 View 处理 json 数据需要 json 的 jar 包 测试代码: 如果是 map 中的值是其它对象类型的,传给 ModelAndView 的数据必须有一个 modelName 2.3 转发和重定向 该注解用于将 Controller 的方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 Response 对象的 body 数据区。使用时机:返回的数据不是 html 标签的页面,而是其他某种格式的数据时(如 json、xml 等)使用。 3.1 返回 json 数据 处理 json 数据需要 json 的 jar 包 返回 json 类型的数据,需要在 spring 配置文件中加入如下配置: 测试 favorPathExtension 请求后缀分别是.xml 和.json 在 测试类: 测试结果: 3.2 实现 RESTFUL 通过 postman 可以测试请求(ajax 方式无法测试 PUT 和 DELETE)。测试 put 的时候,请求的 body 设置为 raw,Headers 的 ContentType=application/json,否则会报 415: 注意类名上方的@RestController,相当于在类中每个方法上都添加了@ReponseBody。deleteDept 方法返回了一句 String 类型的提示信息,默认的 String 类型的返回值,编码是ISO-8859-1,中文会乱码,解决方案是在配置文件中修改编码: 修改 HttpEntity 和@RequestBody 和@ResponseBody 类似,除了可以得到 request 和 response的 body 以外,还可以操作 header。 测试的页面: springMVC整理03--处理数据模型 & 试图解析器 & @ResponseBody & HttpEntity 标签:entity 测试 manage user onclick prefix 创建 convert Fix 原文地址:https://www.cnblogs.com/sueyyyy/p/9623586.html1.处理模型数据
1 /**
2 * 当参数为 Map 时
3 * SpirngMVC 会传入 一个 BindingAwareModelMap
4 * 往 BindingAwareModelMap 里面存入的值 会在后面存入 request 域中
5 * 相当于在方法返回前执行了一个 request.setAttribute 的操作
6 */
7 @RequestMapping("/map.html")
8 public String map(Map
1 name=${name}br/>
2 id=${id}br/>
1 @RequestMapping("/modelandview.html")
2 public ModelAndView testModeAndView(){
3 ModelAndView modelAndView = new ModelAndView();
4 //将 Model 数据作为 request.attribute Foward 到下一个页面。
5 modelAndView.addObject("id",123);
6 modelAndView.addObject("name","abc");
7 modelAndView.setViewName("/model.jsp");//设置要返回的页面
8 return modelAndView;
9 }
@SessionAttributes 只能标注在类上。
@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中.
– @SessionAttributes(value={“user”,”admin”})会将模型中名为 user 和 admin 的属性添加到session 中
– @SessionAttributes(types={Dept.class, Employee.class})会将模型中所有类型为 Dept 和Employee 的属性添加到 session 中
– @SessionAttributes(value={“user”,”admin”}, types={Dept.class})会将模型中名为 user和 admin和类型为 Dept 的对象放到 session 中。
在类上添加 @SessionAttributes 注解1 @SessionAttributes(types = Dept.class, value = {"user", "admin"})
2 @Controller
3 public class ModelController {
1 @RequestMapping("/session.html")
2 public ModelAndView testSettion(Map
1 request 中的属性:br/>
2 admin:${requestScope.admin}br/>
3 user:${requestScope.user}br/>
4 dept.name:${requestScope.dept.name}br/>
5 other:${requestScope.other}br/>
6 session 中的属性:br/>
7 admin:${sessionScope.admin}br/>
8 user:${sessionScope.user}br/>
9 dept.name:${sessionScope.dept.name}br/>
10 other:${sessionScope.other}br/>
1 @RequestMapping("/model1.html")
2 public String testModelAttribute(@ModelAttribute Dept dept) {
3 dept.setId(123);
4 dept.setName("test");
5 //使用@ModelAttribute 注解 dept
6 //相当于执行了 request.setAttribute("dept",dept);
7 //页面上可以直接取数据
8 return "/model.jsp";
9 }
1 body>
2 dept.id=${dept.id}br/>
3 dept.name=${dept.name}
4 body
1 /**
2 * 在方法上使用@ModelAttribute,调用这个 Controller 任意一个方法之前
3 * 都会执行这个方法给模型赋值
4 */
5 @ModelAttribute("dept")
6 public Dept getDept() {
7 Dept dept = new Dept();
8 dept.setId(456);
9 dept.setName("name");
10 return dept;
11 }
12 /**
13 * 在调用这个方法前,会执行 getDept()
14 * 如果请求中有参数,会覆盖掉 getDept()的值
15 * dept 会作为数据模型返回到页面上
16 */
17 @RequestMapping("/model2.html")
18 public String testModelAttribute2(@ModelAttribute Dept dept) {
19 System. out .println(dept.getId());
20 System. out .println(dept.getName());
21 return "/model.jsp";
22 }
2. 视图和视图解析器
Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP 也可是 Excell、 JFreeChart 等各种表现形式的视图。
视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。
为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口。
视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题。所谓视图是无状态的,是指对于每一个请求,都会创建一个 View 对象。
JSP 是最常见的视图技术。
ViewResolver 的主要作用是把一个逻辑上的视图名称解析为一个真正的视图,SpringMVC
中用于把 View 对象呈现给客户端的是 View 对象本身,而 ViewResolver 只是把逻辑视图名称
解析为对象的 View 对象。
InternalResourceViewResolver 可以在视图名称前自动加前缀或后缀:1
2 bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
3 property name="prefix" value="/">property>
4 property name="suffix" value=".jsp">property>
5 bean>
FreeMaker 后面会进行介绍,
FreeMarker 与 spring 整合需要导入 jar: 1 dependency>
2 groupId>org.freemarkergroupId>
3 artifactId>freemarkerartifactId>
4 version>2.3.23version>
5 dependency>
6 dependency>
7 groupId>org.springframeworkgroupId>
8 artifactId>spring-context-supportartifactId>
9 version>4.3.11.RELEASEversion>
10 dependency>
1 bean id="freemarkerConfig"
2 class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
3
4 property name="templateLoaderPath" value="/WEB-INF/ftl/" />
5 property name="defaultEncoding" value="UTF-8" />
6 bean>
1 html>
2 head>
3 title>Titletitle>
4 head>
5 body>
6 h1>${hello}h1>
7 body>
1 @Controller
2 public class FreeMarkerController { {
3 @Autowired
4 private FreeMarkerConfigurer freeMarkerConfigurer;
5 @RequestMapping( "/freemarker.html")
6 @ResponseBody
7 public String genHtml() throws Exception { {
8 // 1 、从 g spring 容器中获得 r FreeMarkerConfigurer 对象。
9 // 2 、从 r FreeMarkerConfigurer 对象中获得 n Configuration 对象。
10 Configuration configuration = freeMarkerConfigurer.getConfiguration();
11 // 3 、使用 n Configuration 对象获得 e Template 对象。
12 Template template = configuration.getTemplate( "hello.ftl");
13 // 4 、创建数据集
14 Map dataModel = new HashMap ();
15 dataModel. put( "hello", "1000");
16 // 5 、创建输出文件的 r Writer 对象。
17 Writer out = new FileWriter( new File( "F:/spring- - freemarker.html"));
18 // 6 、调用模板对象的 s process 方法,生成文件。
19 template.process( dataModel, out);
20 // 7 、关闭流。
21 out. close();
22 return "OK";
23 } }
24 } }
如果想像读取 jsp 一样动态展示 freeMarker 的页面,可以配置视图解析器:1 bean id="viewResolverFtl"
2 class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
3 property name="viewClass"
4 value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>
5 property name="contentType" value="text/html; charset=utf-8"/>
6 property name="cache" value="true" />
7 property name="suffix" value=".ftl" />
8 property name="order" value="0"/>
9 bean>
1 @RequestMapping( "/hellofm.html")
2 public String sayHello( ModelMap map) { {
3 // 传递属性到页面
4 map.addAttribute( "hello", " Hello FreeMarker!");
5 return "/hello"; // 去找 hello.ftl
6 } }
引入 servlet 的 jar1
2 dependency>
3 groupId>javax.servletgroupId>
4 artifactId>javax.servlet-apiartifactId>
5 version>3.1.0version>
6 dependency>
1 public class HelloView implements View { {
2 public String getContentType() { {
3 return "text/html";
4 } }
5 public void render(Map model, HttpServletRequest request,
6 HttpServletResponse response) throws Exception { {
7 // 向相应中写入数据
8 response. getWriter().print( "Welcome to View:Hello");
9 } }
10 } }
1 bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
2 property name="order" value="10" />
3 bean>
4 bean id="helloView" class="view.HelloView"/>
1 @RequestMapping( "helloview.html")
2 public String hello() { {
3 // 因为当前没有 helloView.jsp
4 // 所以视图解析器依次执行,找到 w id=helloView 的视图并显示
5 return "helloView";
6 }
1
2 dependency>
3 groupId>com.fasterxml.jackson.coregroupId>
4 artifactId>jackson-databindartifactId>
5 version>2.7.4version>
6 dependency>
1 public class JsonView extends AbstractView { {
2 /**
3 * 该 w View 对应的输出类型
4 */
5 @Override
6 public String getContentType() { {
7 return "application/json; charset=UTF- - 8";
8 } }
9 // 向响应中写入数据
10 @Override
11 protected void renderMergedOutputModel(Map model,
12 HttpServletRequest request,HttpServletResponse response)
13 throws Exception { {
14 ObjectMapper mapper = new ObjectMapper();
15 // 设置 e Date 类型的格式,默认是显示毫秒数
16 mapper.setDateFormat( new SimpleDateFormat( "yyyy- - MM- - dd HH:mm:ss"));
17 // 需要注意的是放入 l model 的对象一定要实现 e Serializable 接口才能转化成 json
18 String jsonStr = mapper.writeValueAsString( model);
19 response. setContentType(getContentType());
20 response. setHeader( "Cache- - Control", "no- - cache");
21 response. setCharacterEncoding( "UTF- - 8");
22 PrintWriter out = null;
23 try { {
24 out = response. getWriter();
25 out.print( jsonStr);
26 out.flush();
27 } catch ( IOException e e) { {
28 } finally { {
29 if ( out != null) { {
30 out.close();
31 out = null;
32 } }
33 } }
34 } }
35 } }
1 @RequestMapping( "myview.html")
2 public ModelAndView myView() { {
3 Map result = new HashMap ();
4 result. put( "key1", "123");
5 result. put( "key2", new String[]{ { "a", "b"} });
6 result. put( "key3", new Date());
7 return new ModelAndView( new JsonView(), result);
8 } }
1 public String showView2() {
2 //转发前面加 forward:
3 return "index.html";
4 }
5 @RequestMapping("/redirect.html")
6 public String showView3() {
7 //重定向前面加 redirect:
8 return "redirect:index.html";
9 }
3. @ReponseBody
1
2 dependency>
3 groupId>com.fasterxml.jackson.coregroupId>
4 artifactId>jackson-databindartifactId>
5 version>2.7.4version>
6 dependency
1
2 bean id="contentNegotiationManagerFactoryBean"
3 class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
4
5 property name="favorPathExtension" value="true"/>
6
7 property name="favorParameter" value="true"/>
8
9 property name="ignoreAcceptHeader" value="false"/>
10 property name="mediaTypes">
11 map>
12
13 entry key="json" value="application/json"/>
14
15 entry key="xml" value="application/xml"/>
16 map>
17 property>
18 bean>
测试 favorParameter 请求中参数 format=json 和 format=xml
测试 ignoreAcceptHeader,请求的 Header 中 Accept=application/json 或 Accept=application/xml
如果要返回 Xml,需要将要转换为 xml 的实体类上添加注解,如:1 @XmlRootElement
2 public class Dept {
1 mvc:annotation-driven
2 content-negotiation-manager="contentNegotiationManagerFactoryBean"/>
1 @Controller
2 @RequestMapping("/json")
3 public class JsonController {
4 @RequestMapping("/get ")
5 @ResponseBody//会自动将返回值转换成 json
6 public Dept getJson() {
7 Dept dept = new Dept();
8 dept.setId(1);
9 dept.setName("张三");
10 return dept;
11 }
12 }
1 @RestController//相当于本类中所有的方法都加了@ResponseBody
2 @RequestMapping("/rest")
3 public class RestTestController {
4 //通过 method 限制请求的方式
5 @RequestMapping(value = "/{id}", method = RequestMethod. GET )
6 public Dept getDept(@PathVariable Integer id) {
7 //模拟从数据库中查出一条数据
8 Dept dept = new Dept();
9 dept.setId(id);
10 dept.setName("张三");
11 return dept;
12 }
13 @RequestMapping(method = RequestMethod. POST )
14 public Dept addDept(Dept dept) {
15 //模拟插入数据后生成主键
16 dept.setId(1);
17 System. out .println(dept.getName());
18 return dept;
19 }
20 @RequestMapping(method = RequestMethod. PUT , consumes = "application/json")
21 public Dept updateDept(@RequestBody Dept dept) {
22 System. out .println(dept.getName());
23 //执行修改的业务略
24 dept.setName("修改");//模拟修改名字
25 return dept;
26 }
27 @RequestMapping(value = "/{id}", method = RequestMethod. DELETE )
28 public String deleteDept(@PathVariable Integer id) {
29 //执行删除的业务略
30 System. out .println(id);
31 return "删除成功";
32 }
33 }
1 mvc:annotation-driven
2 content-negotiation-manager="contentNegotiationManagerFactoryBean">
3
4 mvc:message-converters>
5 bean class="org.springframework.http.converter.StringHttpMessageConverter">
6 constructor-arg value="UTF-8" />
7 bean>
8 mvc:message-converters>
9 mvc:annotation-driven>
4 HttpEntity
1 @RequestMapping("/entity.html")
2 public ResponseEntity
1 input type="button" onclick=" testEntity ()" value="测试 HttpEntity"/>
2 script type="text/javascript">
3 function testEntity (){
4 $.ajax({
5 type: "POST",
6 url: "/json/entity.html",
7 headers:{"MyRequestHeader":"abc"},
8 success: function(data, status, xhr){//xhr 可以看到响应的头
9 alert(data.id);
10 alert(status);
11 alert("Header="+xhr.getResponseHeader("MyResponseHeader"));
12 },
13 error: function(data, status, xhr){
14 alert(data.id);
15 alert(status);
16 alert("Header="+xhr.getResponseHeader("MyResponseHeader"));
17 }
18 });
19 }
20 script>
下一篇:A*算法的认识与求第K短路模板
文章标题:springMVC整理03--处理数据模型 & 试图解析器 & @ResponseBody & HttpEntity
文章链接:http://soscw.com/index.php/essay/101233.html