BeanNameViewResolver(自定义View)
BeanNameViewResolver
这个视图解析器,用于返回自定义的视图。顾名思义,通过配置后,控制器返回自定义的视图的bean名
,即可返回自定义的视图。
自定义View
package org.views;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.View;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Map;
@Component("myview")
public class MyView implements View {
private static final String ContentType = "text/html;charset=utf-8";
@Override
public String getContentType() {
return ContentType;
}
@Override
public void render(Map<String, ?> map,
HttpServletRequest httpServletRequest,
HttpServletResponse response)
throws Exception {
response.setContentType(ContentType);
PrintWriter writer = response.getWriter();
map.forEach((k,v)->writer.println(k+" "+v));
writer.println("<pre>this is bottom</pre>");
}
}
分析:实现接口View
(或者继承AbstractView
),其中方法render
实际上跟servlet的service
方法功能类似,只不过render方法还传入了模型(model)。@Component("myview")
将该视图,声明为框架组件,而且BeanName
设置为myview
,所以需要将自定义的视图的路径添加到,调度器(dispatcherServlet)配置文件组件扫描标签中,如
<context:component-scan base-package="org.spring;org.spring2;org.views"/>
以上是通过注释的方式,配置自定义视图的使用。由BeanName
也可以看出,也可以在配置文件中添加bean
的方式实现相同效果,
<bean name="myview" class="org.views.MyView"/>
最后必须提醒,实现接口View
时,一定要实现getContentType
方法(即使实现了getContentType
方法,也别以为是设置了响应体的类型,那你就错了),否则视图解析器将不会返回该视图,原因不明,实测如此。抽象类AbstractView
实现了View
接口,推荐使用继承抽象类AbstractView
取代View
接口。
package org.views;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.AbstractView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Map;
@Component("myview")
public class MyView extends AbstractView {
private static final String ContentType = "text/html;charset=utf-8";
protected void renderMergedOutputModel(
Map<String, Object> map,
HttpServletRequest httpServletRequest,
HttpServletResponse response
) throws Exception {
response.setContentType(ContentType);
PrintWriter writer = response.getWriter();
map.forEach((k,v)->writer.println(k+" "+v));
writer.println("<pre>this is bottom</pre>");
}
}
控制器
package org.spring;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping(path = "/hello")
public String execute(ModelMap modelMap) {
modelMap.addAttribute(
"testMessage",
"<pre>hello huanghaifeng</pre>"
);
return "myview";
}
}
分析:模型添加了一个属性,然后返回自定义视图的BeanName
配置文件
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="10"/>
</bean>
</list>
</property>
</bean>
这里,BeanNameViewResolver
需要初始化order属性,这样InternalResourceViewResolver"
就默认位于视图链的最后。