1. 混合多種視圖技術
1.1. 目的
同一資源,多種表述,允許你用同樣的內容數據來呈現不同的view
1.2. 三種方式
方式1 使用擴展名
http://www.test.com/user.xml 呈現xml文件
http://www.test.com/user.json 呈現json格式
http://www.test.com/user 使用默認view呈現,比如jsp等
---------------------------------------------------------------------
方式2 使用http request header的Accept
GET /user HTTP/1.1
Accept:application/xml
GET /user HTTP/1.1
Accept:application/json
---------------------------------------------------------------------
方式3 使用參數
http://www.test.com/user?format=xml
http://www.test.com/user?format=json
1.3. ContentNegotiatingViewResolver配置文件說明
ContentNegotiatingViewResolver:該解析器是Spring 3.0新增的,它不負責具體的視圖解析,而是作爲一箇中間人的角色根據請求所要求的MIME類型,從上下文中選擇一個適合的視圖解析器,再將視圖解析工作委託其負責
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"
p:order="0" >
</bean>
<!-- 混合多種視圖技術 -->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
p:order="1"
p:defaultContentType="text/html"
p:ignoreAcceptHeader="true"
p:favorPathExtension="false"
p:favorParameter="true"
p:parameterName="content"
>
<property name="mediaTypes">
<map>
<entry key="html" value="text/html"></entry>
<entry key="xml" value="application/xml"></entry>
<entry key="json" value="application/json"></entry>
</map>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"
p:renderedAttributes="jsonData">
</bean>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView"
p:modelKey="xmlData" p:marshaller-ref="xmlMarshaller"></bean>
</list>
</property>
</bean>
<bean id="xmlMarshaller"
class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="streamDriver">
<bean class="com.thoughtworks.xstream.io.xml.StaxDriver"></bean>
</property>
<property name="autodetectAnnotations" ><value>true</value></property>
<property name="annotatedClasses">
<list>
<value>com.loushi135.model.User</value>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.<span style="font-family: 宋體;">InternalResourceViewResolver</span>"
p:order="100" >
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="userListExcelView" class="com.loushi135.view.UserListExcelView"></bean>
<bean id="userListPoiExcelView"
class="com.loushi135.view.UserListPoiExcelView"></bean>
<bean id="userListPdfView" class="com.loushi135.view.UserListPdfView"></bean>
說明:
1.BeanNameViewResolver
視圖解析器,根據視圖的名稱new ModelAndView(name),在配置文件查找對應的bean配置,返回視圖'userListExcelView'就進入userListExcelView處理
2.defaultContentType如果所有的mediaType擴展名都沒匹配上,就會使用defaultContentType
3.ignoreAcceptHeader
是否忽略掉accept header,默認就是false
4.favorPathExtension是否啓用擴展名支持,默認就是true
5.favorParameter
是否啓用參數支持,默認就是true
6.parameterName
參數支持的參數名,默認爲format
7.mediaTypes
擴展名至mediaType的映射關係
8.renderedAttributes="jsonData"
json對象根屬性
9.xmlMarshaller
也可以使用Jaxb2Marshaller
<span style="color:#333333;"><bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<array>
<value>com.hoo.entity.User</value>
<value>com.hoo.entity.AccountBean</value>
<value>com.hoo.entity.MapBean</value>
</array>
</property>
</bean>
</constructor-arg>
</bean></span>
10.streamDriver
設置驅動,StaxDriver,DomDriver
1.3.1. UserController
package com.loushi135.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import com.loushi135.model.User;
@Controller
@RequestMapping("/user")
public class UserController {
private List<User> userList = new ArrayList<User>();
public UserController() {
super();
for(int i = 0;i<5;i++){
User user = new User();
user.setName("loushi"+i);
user.setPassword("password"+i);
userList.add(user);
}
}
@RequestMapping("/userIndex")
public String toUserIndex(){
return "userIndex";
}
/**
* 返回json數據
*/
@RequestMapping("/getJson")
public String getJson(ModelMap mm){
mm.addAttribute("jsonData", userList);
return "listJson";
}
/**
* 返回xml數據
*/
@RequestMapping("/getXml")
public String getXml(ModelMap mm){
mm.addAttribute("xmlData", userList);
return "listXml";
}
/**
* 返回excel數據
*/
@RequestMapping("/getExcel")
public String getExcel(ModelMap mm){
mm.addAttribute("userList",userList);
return "userListExcelView";
}
/**
* 返回excel數據
*/
@RequestMapping("/getPoiExcel")
public String getPoiExcel(ModelMap mm){
mm.addAttribute("userList",userList);
return "userListPoiExcelView";
}
/**
* 返回pdf數據
*/
@RequestMapping("/getPdf")
public String getPdf(ModelMap mm){
mm.addAttribute("userList",userList);
return "userListPdfView";
}
}
1.3.2. jxl返回Excel視圖
package com.loushi135.view;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jxl.WorkbookSettings;
import jxl.format.Alignment;
import jxl.format.VerticalAlignment;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.web.servlet.view.document.AbstractJExcelView;
import com.loushi135.model.User;
public class UserListExcelView extends AbstractJExcelView {
private String[] columnNames = new String[] {"姓名","密碼"};
private String[] dbColumnNames = new String[] {"name","password"};
private Integer[] columnWidths = new Integer[] { 40, 40 };
@Override
protected void buildExcelDocument(Map<String, Object> model,
WritableWorkbook workbook, HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/ms-excel");
String fileName = "用戶列表excel.xls";
// response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", "inline; filename="+new String(fileName.getBytes(),"iso8859-1"));
String sheetName = "用戶信息";
// 全局設置
WorkbookSettings setting = new WorkbookSettings();
java.util.Locale locale = new java.util.Locale("zh", "CN");
setting.setLocale(locale);
setting.setEncoding("UTF-8");
// 創建工作薄
// workbook = Workbook.createWorkbook(os); // 建立excel文件
// 創建第一個工作表
jxl.write.WritableSheet ws = workbook.createSheet(sheetName, 1); // sheet名稱
List<User> userList = (List<User>)model.get("userList");
// 添加標題
addColumNameToWsheet(ws);
writeContext(ws, userList);
} catch (Exception e) {
e.printStackTrace();
}
// finally {
// 寫入文件
// try {
// workbook.write();
// workbook.close();
// os.flush();
// os.close();
// } catch (WriteException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
}
private <T> void writeContext(WritableSheet wsheet, List<T> list) {
jxl.write.Label wlabel = null;
jxl.write.WritableCellFormat wcf = getFormat();
int rows = list.size();
int cols = dbColumnNames.length;
String columnName = null;
Object value = null;
try {
for (int i = 0; i < rows; i++) {
T t = (T) list.get(i);
for (int j = 0; j < cols; j++) {
columnName = dbColumnNames[j].toLowerCase();
value = PropertyUtils.getProperty(t, columnName);
wlabel = new jxl.write.Label(j, (i + 1), value + "", wcf);
wlabel = new jxl.write.Label(j, (i + 1), value + "");
wsheet.addCell(wlabel);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 添加標題樣式
private void addColumNameToWsheet(jxl.write.WritableSheet wsheet)
throws RowsExceededException, WriteException {
// 設置excel標題
jxl.write.WritableFont wfont = getFont();
if (null == wfont) {
wfont = new WritableFont(WritableFont.ARIAL,
WritableFont.DEFAULT_POINT_SIZE, WritableFont.BOLD);
}
jxl.write.WritableCellFormat wcfFC = getFormat();
if (null == wcfFC) {
wcfFC = new jxl.write.WritableCellFormat(wfont);
try {
wcfFC.setWrap(true);// 自動換行
wcfFC.setAlignment(Alignment.CENTRE);
wcfFC.setVerticalAlignment(VerticalAlignment.CENTRE);// 設置對齊方式
} catch (WriteException e) {
e.printStackTrace();
}
}
jxl.write.Label wlabel1 = null;
String[] columNames = columnNames;
if (null == columNames)
return;
int colSize = columNames.length;
Integer[] colsWidth = columnWidths;
if (null == colsWidth) {
colsWidth = new Integer[colSize];
for (int i = 0; i < colSize; i++) {
colsWidth[i] = 20;
}
}
int temp = 0;
String colName = null;
for (int i = 0; i < colSize; i++) {
colName = columNames[i];
if (null == colName || "".equals(colName))
colName = "";
wlabel1 = new jxl.write.Label(i, 0, colName, wcfFC);
wsheet.addCell(wlabel1);
temp = colsWidth[i].intValue();
// 默認設置列寬
temp = temp == 0 ? 20 : temp;
wsheet.setColumnView(i, temp);
}
}
// 設置格式
private WritableCellFormat getFormat() {
jxl.write.WritableFont wfont = getFont();
jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(
wfont);
try {
wcfFC.setWrap(true);
wcfFC.setAlignment(Alignment.CENTRE);
wcfFC.setVerticalAlignment(VerticalAlignment.CENTRE);
} catch (WriteException e) {
e.printStackTrace();
}
return wcfFC;
}
// 設置字體
private WritableFont getFont() {
return new WritableFont(WritableFont.ARIAL,
WritableFont.DEFAULT_POINT_SIZE, WritableFont.BOLD);
}
}
1.3.3. poi返回excel
package com.loushi135.view;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.web.servlet.view.document.AbstractExcelView;
import com.loushi135.model.User;
public class UserListPoiExcelView extends AbstractExcelView {
@Override
protected void buildExcelDocument(Map<String, Object> model,
HSSFWorkbook workbook, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String fileName = "用戶列表excel.xls";
// 設置response方式,使執行此controller時候自動出現下載頁面,而非直接使用excel打開
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", "inline; filename="+new String(fileName.getBytes(),"iso8859-1"));
List<User> userList = (List<User>) model.get("userList");
// 產生Excel表頭
HSSFSheet sheet = workbook.createSheet("用戶列表");
HSSFRow header = sheet.createRow(0); // 第0行
// 產生標題列
header.createCell((short) 0).setCellValue("name");
header.createCell((short) 1).setCellValue("password");
HSSFCellStyle cellStyle = workbook.createCellStyle();
// 填充數據
int rowNum = 1;
for (User user:userList) {
HSSFRow row = sheet.createRow(rowNum++);
row.createCell((short) 0)
.setCellValue(user.getName().toString());
row.createCell((short) 1).setCellValue(user.getPassword());
}
// // 列總和計算
// HSSFRow row = sheet.createRow(rowNum);
// row.createCell((short) 0).setCellValue("TOTAL:");
// String formual = "SUM(D2:D" + rowNum + ")"; // D2到D[rowNum]單元格起(count數據)
// row.createCell((short) 3).setCellFormula(formual);
}
}
1.3.4. 返回pdf視圖
package com.loushi135.view;
import java.awt.Color;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.view.document.AbstractPdfView;
import com.loushi135.model.User;
import com.lowagie.text.Document;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
public class UserListPdfView extends AbstractPdfView {
@Override
protected void buildPdfDocument(Map<String, Object> model,
Document document, PdfWriter writer, HttpServletRequest request,
HttpServletResponse response) throws Exception {
String fileName = "用戶列表pdf.pdf";
// 設置response方式,使執行此controller時候自動出現下載頁面,而非直接使用excel打開
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition", "inline; filename="+new String(fileName.getBytes(),"iso8859-1"));
List<User> userList = (List<User>) model.get("userList");
//顯示中文
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
com.lowagie.text.Font FontChinese = new com.lowagie.text.Font(bfChinese, 12, com.lowagie.text.Font.NORMAL );
//創建一個有2列的表格
PdfPTable table = new PdfPTable(2);
//定義一個表格單元
PdfPCell cell = new PdfPCell(new Paragraph("header with colspan 2"));
//定義一個表格單元的跨度
cell.setColspan(2);
//定義單元格的背景顏色
cell.setBackgroundColor(new Color(0xC0, 0xC0, 0xC0));
table.addCell(cell);
PdfPCell headName = new PdfPCell(new Paragraph("姓名",FontChinese));
//定義單元格的框顏色
headName.setBorderColor(new Color(255, 0, 0));
PdfPCell headPassword = new PdfPCell(new Paragraph("密碼",FontChinese));
headPassword.setBorderColor(new Color(255, 0, 0));
table.addCell(headName);
table.addCell(headPassword);
for (User user:userList) {
PdfPCell name = new PdfPCell(new Paragraph(user.getName(),FontChinese));
PdfPCell password = new PdfPCell(new Paragraph(user.getPassword(),FontChinese));
table.addCell(name);
table.addCell(password);
}
document.add(table);
}
}
1.3.5. 測試jsp頁面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>視圖</title>
<script type="text/javascript"
src="${pageContext.request.contextPath}/js/jquery-1.8.1.js"></script>
<script type="text/javascript">
var _ctx="${pageContext.request.contextPath}";
$(document).ready(function(){
$("#json").click(function(event){
$.post(
_ctx+"/user/getJson.do?content=json",//請求使用content=?來實現restful風格,來選擇進入什麼視圖
{},
function(data){
var jsonData = data.jsonData;
var message = "";
$(jsonData).each(function(i,item){//解析json
message +=" 用戶名:"+item.name+" 密碼:"+item.password;
});
alert(message);
},
'json'
);
});
$("#xml").click(function(event){
$.post(
_ctx+"/user/getXml.do?content=xml",
{},
function(data){
var message = "";
$(data).find("User").each(function(i,item){//解析xml
var name = $(item).children('name').text();
var password = $(item).children('password').text();
message +=" 用戶名:"+name+" 密碼:"+password;
});
alert(message);
},
'xml'
);
});
});
</script>
</head>
<body>
<input type="button" value="請求返回json" id="json"/>
<br/>
<input type="button" value="請求返回xml" id="xml"/>
<br>
<input type="button" value="請求jxl返回excel" id="jxlExcel" οnclick="location='${pageContext.request.contextPath}/user/getExcel.do'"/>
<br/>
<input type="button" value="請求poi返回excel" id="poiExcel" οnclick="location='${pageContext.request.contextPath}/user/getPoiExcel.do'"/>
<br/>
<input type="button" value="請求返回pdf" id="pdf" οnclick="location='${pageContext.request.contextPath}/user/getPdf.do'"/>
<br/>
<input type="button" value="請求返回模板" id="template"/>
</body>
</html>
通過http://localhost:8080/SpringMvcHelloWorld/user/userIndex.do 進入 userIndex.jsp