作者:郭先2502898821_918 | 来源:互联网 | 2023-09-23 17:14
1、控制器的基本形式@RequestMapping注解声明这个控制器所要处理的请求@ControllerpublicclassHomeController{@Requ
1、控制器的基本形式
@RequestMapping注解
声明这个控制器所要处理的请求
@Controller
public class HomeController{
@RequestMapping(value="/", method=GET)
public String home(){
return "home";
}
}
1.1、声明控制器
2种方式让控制器类能被扫描称为组件:
a、在类上使用@Controller声明这是一个控制器
b、在类上使用@Component声明这是一个组件,并且类名使用Controller作为结束
1.2、指定处理请求路径
@RequestMapping(value="/",method=GET)
value代表要处理的请求路径,method属性指定所处理的HTTP方法
1.3、返回视图名称
return "home";
返回一个字符串,代表需要渲染的视图名称。DispatcherServlet会要求视图解析器将这个逻辑名称解析为实际的视图。
基于我们在InternalResourceViewResolver的配置,视图名“home”将被解析为“/WEB-INF/views/home.jsp”路径的JSP。
2、测试控制器
控制器本身也是一个POJO,可用普通POJO的测试方法测试,但是没有太大的意义。
Public class HomeControllerTest{
@Test
public void testHomePage() throws Exception{
HomeController controller = new HomeController();
assertEquals("home", controller.home());
}
}
这个测试只是测试home()方法的返回值,没有站在SpringMVC控制器的角度进行测试。
Spring 3.2开始可以按照控制器的方式来测试控制器。
Spring 3.2开始包含一种mock Spring MVC并针对控制器执行HTTP请求的机制,这样测试控制器就不用启动Web服务器和Web浏览器了。
Public class HomeControllerTest{
@Test
public void testHomePage() throws Exception{
HomeController controller = new HomeController();
MockMvc mockMvc = standaloneSetup(controller).build();//搭建MockMvc
mockMvc.perform(get("/"))//对"/"执行GET请求
.andExpect(view().name("home"));//预期得到home视图
}
}
先传递一个HomeController实例到standaloneSetup()并调用build()来构建MockMvc实例,然后用这个实例来执行针对“/”的GET请求并设置期望得到的视图名称。
3、定义类级别的请求处理
对类使用@RequestMapping注解,那么这个注解会应用到所有处理器方法中。
@Controller
@RequestMapping("/")
public class HomeController{
@RequestMapping( method=GET)
public String home(){
return "home";
}
}
路径还可以是一个数组,下面例子代表home()方法可以映射到对“/”和“homepage”的GET请求。
@Controller
@RequestMapping({"/", "/homepage"})
public class HomeController{
@RequestMapping( method=GET)
public String home(){
return "home";
}
}
4、传递模型数据到视图中
使用Model传递数据
@RequestMapping(method=RequestMethod.GET)
public String spittles(Model model){
model.addAttribute(spittleRepository.findSpittles(Long.MAX_VALUE,20));
return "spittles";
}
通过Model参数,可以将控制器里面的值,传递到视图中,渲染到客户端。
Model实际上是一个Map(Key-Value对集合)
使用addAttribute并且不指定key的时候,Model会根据类型自动生成key,例如上面是一个List,那么key值就是spittleList
最后控制器返回视图逻辑名,标明需要渲染的视图。
改用Map传递数据
如果不想使用Spring类型,把Model改成Map类型也是可以的
@RequestMapping(method=RequestMethod.GET)
public String spittles(Map model){
model.put("spittleList",spittleRepository.findSpittles(Long.MAX_VALUE,20));
return "spittles";
}
直接返回数据
@RequestMapping(method=RequestMethod.GET)
public List spittles(){
return spittleRepository.findSpittles(Long.MAX_VALUE,20);
}
这种写法,没有返回视图名称,也没有显式设定模型。
模型:当处理器方法直接返回对象或集合时,这个值会放进模型中,模型的key由类型推断出来。
视图:而视图的逻辑名称会根据请求路径推断得出,如/spittles的GET请求,逻辑视图名称就是spittles(去掉开头斜线)。
视图的渲染
无论使用哪种方法,结果是一样的:
在控制器中,将数据定义为模型,并发送到指定的视图,根据视图的逻辑名称,按照我们配置的InternalResourceViewResolver视图解析器,找到对应的视图文件(如"/WEB-INF/views/spittles.jsp")。
当视图是JSP的时候,模型数据会作为请求属性放到请求(request)之中。
因此,在jsp文件中可以使用JSTL(JavaServer Pages Standard Tag Library)的标签进行渲染。
测试控制器视图名以及传递的模型数据
@Test
public void houldShowRecentSpittles() throws Exception {
List expectedSpittles = createSpittleList(20);
SpittleRepository mockRepository = mock(SpittleRepository.class);//使用mock,利用接口创建一个实现,并创建一个实例对象
when(mockRepository.findSpittles(Long.MAX_VALUE, 20))
.thenReturn(expectedSpittles);//调用mock实现,创建20个Spittle对象
SpittleController controller = new SpittleController(mockRepository);
MockMvc mockMvc = standaloneSetup(controller)//搭建MockMvc
.setSingleView(new InternalResourceView("/WEB-INF/views/spittles.jsp"))
.build();
mockMvc.perform(get("/spittles"))//对/spittles发起GET请求
.andExpect(view().name("spittles"))//断言视图名为spittles
.andExpect(model().attributeExists("spittleList"))
.andExpect(model().attribute("spittleList",
hasItems(expectedSpittles.toArray())));
}