SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-002-Controller的requestMapping、model

一、RequestMapping

1.可以写在方法上或类上,且值可以是数组

 1 package spittr.web;
 2
 3 import static org.springframework.web.bind.annotation.RequestMethod.*;
 4
 5 import org.springframework.stereotype.Controller;
 6 import org.springframework.ui.Model;
 7 import org.springframework.web.bind.annotation.RequestMapping;
 8
 9 @Controller
10 //@Component //也可用这个,但没有见名知义
11 //@RequestMapping("/")
12 @RequestMapping({"/", "/homepage"})
13 public class HomeController {
14
15   //@RequestMapping(value="/", method=GET)
16   @RequestMapping(method = GET)
17   public String home(Model model) {
18     return "home";
19   }
20
21 }

2.测试

 1 package spittr.web;
 2 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 3 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 4 import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
 5
 6 import org.junit.Test;
 7 import org.springframework.test.web.servlet.MockMvc;
 8
 9 import spittr.web.HomeController;
10
11 public class HomeControllerTest {
12
13   @Test
14   public void testHomePage() throws Exception {
15     HomeController controller = new HomeController();
16     MockMvc mockMvc = standaloneSetup(controller).build();
17     mockMvc.perform(get("/homepage"))
18            .andExpect(view().name("home"));
19   }
20
21 }

3.jsp

 1 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 2 <%@ page session="false" %>
 3 <html>
 4   <head>
 5     <title>Spitter</title>
 6     <link rel="stylesheet"
 7           type="text/css"
 8           href="<c:url value="/resources/style.css" />" >
 9   </head>
10   <body>
11     <h1>Welcome to Spitter</h1>
12
13     <a href="<c:url value="/spittles" />">Spittles</a> |
14     <a href="<c:url value="/spitter/register" />">Register</a>
15   </body>
16 </html>

二、在controller中使用model,model实际就是一个map

1.controller

(1)

package spittr.web;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import spittr.Spittle;
import spittr.data.SpittleRepository;
@Controller
@RequestMapping("/spittles")
public class SpittleController {
    private SpittleRepository spittleRepository;

    @Autowired
    public SpittleController(SpittleRepository spittleRepository) {
        this.spittleRepository = spittleRepository;
    }

    @RequestMapping(method = RequestMethod.GET)
    public String spittles(Model model) {
        model.addAttribute(spittleRepository.findSpittles(Long.MAX_VALUE, 20));
        return "spittles";
    }
}

如果在addAttribute时没有指定key,则spring会根据存入的数据类型来生成key,如上面存入的数据类型是List<Spittle>,所以key就是spittleList

(2)也可以明确key

1 @RequestMapping(method = RequestMethod.GET)
2 public String spittles(Model model) {
3     model.addAttribute("spittleList",spittleRepository.findSpittles(Long.MAX_VALUE, 20));
4     return "spittles";
5 }

(3)也可用map替换model

1 @RequestMapping(method = RequestMethod.GET)
2 public String spittles(Map model) {
3     model.put("spittleList",spittleRepository.findSpittles(Long.MAX_VALUE, 20));
4     return "spittles";
5 }

(4)不返回string,直接返回数据类型

@RequestMapping(method = RequestMethod.GET)
public List < Spittle > spittles() {
    return spittleRepository.findSpittles(Long.MAX_VALUE, 20));
}

When a handler method returns an object or a collection like this, the value returned is put into the model, and the model key is inferred from its type ( spittleList , as in the other examples).
As for the logical view name, it’s inferred from the request path. Because this method handles GET requests for /spittles, the view name is spittles (chopping off the leading slash).

2.View

在jsp中用jstl解析数据

 1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 2 <%@ taglib prefix="s" uri="http://www.springframework.org/tags"%>
 3 <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
 4
 5 <html>
 6   <head>
 7     <title>Spitter</title>
 8     <link rel="stylesheet" type="text/css" href="<c:url value="/resources/style.css" />" >
 9   </head>
10   <body>
11     <div class="spittleForm">
12       <h1>Spit it out...</h1>
13       <form method="POST" name="spittleForm">
14         <input type="hidden" name="latitude">
15         <input type="hidden" name="longitude">
16         <textarea name="message" cols="80" rows="5"></textarea><br/>
17         <input type="submit" value="Add" />
18       </form>
19     </div>
20     <div class="listTitle">
21       <h1>Recent Spittles</h1>
22       <ul class="spittleList">
23         <c:forEach items="${spittleList}" var="spittle" >
24           <li id="spittle_<c:out value="spittle.id"/>">
25             <div class="spittleMessage"><c:out value="${spittle.message}" /></div>
26             <div>
27               <span class="spittleTime"><c:out value="${spittle.time}" /></span>
28               <span class="spittleLocation">(<c:out value="${spittle.latitude}" />, <c:out value="${spittle.longitude}" />)</span>
29             </div>
30           </li>
31         </c:forEach>
32       </ul>
33       <c:if test="${fn:length(spittleList) gt 20}">
34         <hr />
35         <s:url value="/spittles?count=${nextCount}" var="more_url" />
36         <a href="${more_url}">Show more</a>
37       </c:if>
38     </div>
39   </body>
40 </html>

3.测试

 1 package spittr.web;
 2 import static org.hamcrest.Matchers.*;
 3 import static org.mockito.Mockito.*;
 4 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 5 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 6 import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
 7
 8 import java.util.ArrayList;
 9 import java.util.Date;
10 import java.util.List;
11
12 import org.junit.Test;
13 import org.springframework.test.web.servlet.MockMvc;
14 import org.springframework.web.servlet.view.InternalResourceView;
15
16 import spittr.Spittle;
17 import spittr.data.SpittleRepository;
18 import spittr.web.SpittleController;
19
20 public class SpittleControllerTest {
21
22   @Test
23   public void shouldShowRecentSpittles() throws Exception {
24     List<Spittle> expectedSpittles = createSpittleList(20);
25     SpittleRepository mockRepository = mock(SpittleRepository.class);
26     when(mockRepository.findSpittles(Long.MAX_VALUE, 20))
27         .thenReturn(expectedSpittles);
28
29     SpittleController controller = new SpittleController(mockRepository);
30     MockMvc mockMvc = standaloneSetup(controller)
31         .setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp"))
32         .build();
33
34     mockMvc.perform(get("/spittles"))
35        .andExpect(view().name("spittles"))
36        .andExpect(model().attributeExists("spittleList"))
37        .andExpect(model().attribute("spittleList",
38                   hasItems(expectedSpittles.toArray())));
39   }
40
41   @Test
42   public void shouldShowPagedSpittles() throws Exception {
43     List<Spittle> expectedSpittles = createSpittleList(50);
44     SpittleRepository mockRepository = mock(SpittleRepository.class);
45     when(mockRepository.findSpittles(238900, 50))
46         .thenReturn(expectedSpittles);
47
48     SpittleController controller = new SpittleController(mockRepository);
49     MockMvc mockMvc = standaloneSetup(controller)
50         .setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp"))
51         .build();
52
53     mockMvc.perform(get("/spittles?max=238900&count=50"))
54       .andExpect(view().name("spittles"))
55       .andExpect(model().attributeExists("spittleList"))
56       .andExpect(model().attribute("spittleList",
57                  hasItems(expectedSpittles.toArray())));
58   }
59
60   @Test
61   public void testSpittle() throws Exception {
62     Spittle expectedSpittle = new Spittle("Hello", new Date());
63     SpittleRepository mockRepository = mock(SpittleRepository.class);
64     when(mockRepository.findOne(12345)).thenReturn(expectedSpittle);
65
66     SpittleController controller = new SpittleController(mockRepository);
67     MockMvc mockMvc = standaloneSetup(controller).build();
68
69     mockMvc.perform(get("/spittles/12345"))
70       .andExpect(view().name("spittle"))
71       .andExpect(model().attributeExists("spittle"))
72       .andExpect(model().attribute("spittle", expectedSpittle));
73   }
74
75   @Test
76   public void saveSpittle() throws Exception {
77     SpittleRepository mockRepository = mock(SpittleRepository.class);
78     SpittleController controller = new SpittleController(mockRepository);
79     MockMvc mockMvc = standaloneSetup(controller).build();
80
81     mockMvc.perform(post("/spittles")
82            .param("message", "Hello World") // this works, but isn‘t really testing what really happens
83            .param("longitude", "-81.5811668")
84            .param("latitude", "28.4159649")
85            )
86            .andExpect(redirectedUrl("/spittles"));
87
88     verify(mockRepository, atLeastOnce()).save(new Spittle(null, "Hello World", new Date(), -81.5811668, 28.4159649));
89   }
90
91   private List<Spittle> createSpittleList(int count) {
92     List<Spittle> spittles = new ArrayList<Spittle>();
93     for (int i=0; i < count; i++) {
94       spittles.add(new Spittle("Spittle " + i, new Date()));
95     }
96     return spittles;
97   }
98 }
时间: 2024-12-14 09:31:30

SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-002-Controller的requestMapping、model的相关文章

SPRING IN ACTION 第4版笔记-第五章BUILDING SPRING WEB APPLICATIONS-003-示例项目用到的类及配置文件

一.配置文件 1.由于它继承AbstractAnnotationConfigDispatcherServletInitializer,Servlet容器会把它当做配置文件 1 package spittr.config; 2 3 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 4 5 import spittr.web.WebConfig; 6

SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-006- 如何保持重定向的request数据(用model、占位符、RedirectAttributes)

一.redirect为什么会丢数据? when a handler method completes, any model data specified in the method is copied into the request as request attributes, and the request is forwarded to the view for rendering. Because it’s the same request that’s handled by both

SPRING IN ACTION 第4版笔记-第七章Advanced Spring MVC-001- DispatcherServlet的高级配置(ServletRegistration.Dynamic、WebApplicationInitializer)

一. 1.如想在DispatcherServlet在Servlet容器中注册后自定义一些操作,如开启文件上传功能,则可重写通过AbstractAnnotationConfigDispatcherServletInitializer 的customizeRegistration() 来实现 1 // After AbstractAnnotation ConfigDispatcherServletInitializer registers DispatcherServlet with the ser

SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-010-Introduction为类增加新方法

一. 1.Introduction的作用是给类动态的增加方法 When Spring discovers a bean annotated with @Aspect , it will automatically create a proxy that delegates calls to either the proxied bean or to the introduction implementation, depending on whether the method called be

SPRING IN ACTION 第4版笔记-第六章RENDERING WEB VIEWS-003- SPRING的GENERAL TAG LIBRARY简介及用&lt;s:message&gt;和ReloadableResourceBundleMessageSource实现国际化

一. SPRING支持的GENERAL TAG LIBRARY 1. 二.用<s:message>和ReloadableResourceBundleMessageSource实现国际化 1.配置ReloadableResourceBundleMessageSource,它能it has the ability to reload message properties without recompiling or restarting the application. 1 package spi

SPRING IN ACTION 第4版笔记-第六章Rendering web views-001- Spring支持的View Resolver、InternalResourceViewResolver、JstlView

一.Spring支持的View Resolver 二.InternalResourceViewResolver Spring supports JSP views in two ways:? InternalResourceViewResolver ? Spring provides two JSP tag libraries, one for form-to-model binding and one providing general utility features. 1.在java中定义

SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-006Spring-Data的运行规则(@EnableJpaRepositories、&lt;jpa:repositories&gt;)

一.JpaRepository 1.要使Spring自动生成实现类的步骤 (1)配置文件xml 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xm

SPRING IN ACTION 第4版笔记-第三章ADVANCING WIRING-006-给bean运行时注入值(Environment,Property文件)

一. 直观的给bean注入值如下: @Bean public CompactDisc sgtPeppers() { return new BlankDisc( "Sgt. Pepper's Lonely Hearts Club Band", "The Beatles"); } < bean id = "sgtPeppers" class = "soundsystem.BlankDisc" c: _title = &quo

SPRING IN ACTION 第4版笔记-第三章ADVANCING WIRING-005-Bean的作用域@Scope、ProxyMode

一. Spring的bean默认是单例的 But sometimes you may find yourself working with a mutable class that does main-tain some state and therefore isn’t safe for reuse. In that case, declaring the class as asingleton bean probably isn’t a good idea because that obje