本篇主要介紹SpringMVC控制器的以下內容:
@RequestMapping 請求映射
@RequestParam 請求參數
ModelAndView 返回模型和視圖
SpringMVC 對象屬性自動封裝
SpringMVCPOST 請求亂碼解決
Controller 內部轉發和重定向
我們通過一個簡單的小項目來介紹。模擬學生管理(展示,添加,修改,刪除)的過程。
定義實體類:Student,屬性有:id,name,age並生成get,set,和3個參數的構造方法。
新建包:controller,寫一個StudentController
@Controller
@RequestMapping("/student")
public class StudentController {
private static List<Student> studentList = new ArrayList<Student>();
//靜態代碼塊,只執行一次,模擬數據
static {
studentList.add(new Student(1, "張三", 11));
studentList.add(new Student(2, "李四", 22));
studentList.add(new Student(3, "王五", 33));
}
@RequestMapping("/list")
public ModelAndView list() {
ModelAndView mav = new ModelAndView();
mav.addObject("studentList",studentList);
mav.setViewName("list");
return mav;
}
}
我們模塊化處理:在StudentController前加請求映射"student":可能還有成績管理。在WEB-INF下建一個名爲student的包,裏面寫關於student的jsp.
mav有兩個方法:addobject是向ModelAndView(模型和視圖)添加對象。setViewName:向視圖解析器返回,解析成jsp
然後我們在WebContent目錄下,建一個index.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%
response.sendRedirect("student/list.do");
%>
直接請求student/list,經過Controller,執行list方法,把數據封裝,並通過視圖解析器轉發到list,jsp,這就是展示數據。
<table>
<tr>
<th>編號</th>
<th>姓名</th>
<th>年齡</th>
<th colspan="2">操作</th>
</tr>
<c:forEach var="student" items="${studentList }">
<tr>
<td>${student.id }</td>
<td>${student.name }</td>
<td>${student.age }</td>
<td><a href="">修改</a></td>
<td><a href="">刪除</a></td>
</tr>
</c:forEach>
</table>
下面我們弄添加學生,在list.jsp下面寫一個超鏈接:
<a href="${pageContext.request.contextPath }/student/preSave.do">添加學生</a>
這個地方不寫add是因爲修改的時候,也請求preSave讓其判斷,但一個是有參數的,一個是沒有的。
<td><a href="${pageContext.request.contextPath }/student/preSave.do?id=${student.id }">修改</a></td>
preSave方法:
@RequestMapping("/preSave")
public ModelAndView preSave(@RequestParam(value="id",required=false) String id) {
ModelAndView mav = new ModelAndView();
if(id!=null) {
mav.addObject("student",studentList.get(Integer.parseInt(id)-1));
mav.setViewName("student/update");
return mav;
}
mav.setViewName("student/add");
return mav;
}
@RequestParam(value="id",required=false):請求參數,獲得請求url中的參數,在這裏是獲取修改按鈕url裏的參數:判斷如果不爲空,說明請求的url中是有參數的,那就是修改,獲取到該id的Student,封裝到ModelAndView中,並請求update,解析到update.jsp
如果是空,就表示是請求添加,直接解析到add.jsp.
update.jsp:
<form action="${pageContext.request.contextPath }/student/save.do" method="post">
<table>
<tr>
<th colspan="2">學生修改</th>
</tr>
<tr>
<td>姓名</td>
<td><input type="text" name="name" value="${student.name }"></td>
</tr>
<tr>
<td>年齡</td>
<td><input type="text" name="age" value="${student.age }"></td>
</tr>
<tr>
<td><input type="hidden" name="id" value="${student.id }"></td>
<td><input type="submit" value="修改"></td>
</tr>
</table>
</form>
add.jsp:
<form action="${pageContext.request.contextPath }/student/save.do" method="post">
<table>
<tr>
<th colspan="2">學生添加</th>
</tr>
<tr>
<td>姓名</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>年齡</td>
<td><input type="text" name="age"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"></td>
</tr>
</table>
</form>
兩個jsp都請求save,都會把數據自動封裝,但update封裝的數據是有id的,而添加是沒有id的,根據這個寫save方法:
@RequestMapping("/save")
public String add(Student student) {
if(student.getId()!=0) {
Student s = studentList.get(student.getId()-1);
s.setName(student.getName());
s.setAge(student.getAge());
}else {
studentList.add(student);
}
return "redirect:/student/list.do";
}
有就是封裝的Student裏面的id不爲0,就是修改,然後根據id獲取到數據中指定的對象,進行修改即可,
id爲0,就是添加,直接把封裝的對象,添加到數據中就行,執行完後重定向到list.jsp.
redirect:/ :重定向,不把參數傳過去,並且不會改變瀏覽器url.
forward:/ :轉發,不寫默認就是轉發,會將參數帶過去,並且瀏覽器url也會改過去。
剩下一個刪除,直接在刪除時,請求dalete.do,調用Controller中delete方法,請求參數,得到url裏面的id,根據id,刪除指定Student對象。然後重定向到list.jsp.
@RequestMapping("/delete")
public String delete(@RequestParam(value="id") int id) {
studentList.remove(id-1);
return "redirect:/student/list.do";
}
最後,因爲這是爲了介紹SpringMVC的Controller控制器,所以就沒用數據庫,直接靜態封裝的數據,所以id也不是自增,id肯定會有bug ,比如添加的數據,不能修改。因爲找不到id,添加時候沒有添加id,默認就是0.
在添加時候,返回過來的數據會有亂碼,所以要在web.xml中定義攔截器,攔截所有請求,將編碼統一設置爲utf-8:
<!-- 攔截所有請求,統一utf-8編碼 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>