SpringMVC 第二天
第1章 響應數據和結果視圖
1.1返回值分類
1.1.1字符串
controller 方法返回字符串可以指定邏輯視圖名,通過視圖解析器解析爲物理視圖地址。
//指定邏輯視圖名,經過視圖解析器解析爲 jsp 物理路徑:/WEB-INF/pages/success.jsp
@RequestMapping("/testReturnString")
public String testReturnString() {
System.out.println("AccountController 的 testReturnString 方法執行了。。。。");
return "success";
}
運行結果:
1.1.2void
在昨天的學習中,我們知道 Servlet 原始 API 可以作爲控制器中方法的參數:
@RequestMapping("/testReturnVoid")
public void testReturnVoid(HttpServletRequest request,HttpServletResponse response)
throws Exception {
}
在 controller 方法形參上可以定義 request 和 response,使用 request 或 response 指定響應結果:
1、使用 request 轉向頁面,如下:
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,
response);
2、也可以通過 response 頁面重定向:
response.sendRedirect("testRetrunString")
3、也可以通過 response 指定響應結果,例如響應 json 數據:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json 串");
1.1.3ModelAndView
ModelAndView 是 SpringMVC 爲我們提供的一個對象,該對象也可以用作控制器方法的返回值。
該對象中有兩個方法:
示例代碼:
/**
*返回 ModeAndView
*@return
*/
@RequestMapping("/testReturnModelAndView")
public ModelAndView testReturnModelAndView() {
ModelAndView mv = new ModelAndView();
mv.addObject("username", "張三");
mv.setViewName("success");
return mv;
}
響應的 jsp 代碼:
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>執行成功</title>
</head>
<body>
執行成功!
${requestScope.username}
</body>
</html>
輸出結果:
注意:
我們在頁面上上獲取使用的是 requestScope.username 取的,所以返回 ModelAndView 類型時,瀏
覽器跳轉只能是請求轉發。
1.2轉發和重定向
1.2.1forward 轉發
controller 方法在提供了 String 類型的返回值之後,默認就是請求轉發。我們也可以寫成:
/**
*轉發
*@return
*/
@RequestMapping("/testForward")
public String testForward() {
System.out.println("AccountController 的 testForward 方法執行了。。。。");
return "forward:/WEB-INF/pages/success.jsp";
}
需要注意的是,如果用了 formward:則路徑必須寫成實際視圖 url,不能寫邏輯視圖。
它相當於“request.getRequestDispatcher("url").forward(request,response)”。使用請求
轉發,既可以轉發到 jsp,也可以轉發到其他的控制器方法。
1.2.2Redirect 重定向
contrller 方法提供了一個 String 類型返回值之後,它需要在返回值裏使用:redirect:
/**
*重定向
*@return
*/
@RequestMapping("/testRedirect")
public String testRedirect() {
System.out.println("AccountController 的 testRedirect 方法執行了。。。。");
return "redirect:testReturnModelAndView";
}
它相當於“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 頁面,則 jsp 頁面不
能寫在 WEB-INF 目錄中,否則無法找到。
1.3ResponseBody 響應 json 數據
1.3.1使用說明
作用:
該註解用於將 Controller 的方法返回的對象,通過 HttpMessageConverter 接口轉換爲指定格式的
數據如:json,xml 等,通過 Response 響應給客戶端
1.3.2使用示例
需求:
使用@ResponseBody 註解實現將 controller 方法返回對象轉換爲 json 響應給客戶端。
前置知識點:
Springmvc 默認用 MappingJacksonHttpMessageConverter 對 json 數據進行轉換,需要加入
jackson 的包。
注意:2.7.0 以下的版本用不了
jsp 中的代碼:
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$("#testJson").click(function(){
$.ajax({
type:"post",
url:"${pageContext.request.contextPath}/testResponseJson",
contentType:"application/json;charset=utf-8",
data:'{"id":1,"name":"test","money":999.0}',
dataType:"json",
success:function(data){
alert(data);
}
});
});
})
</script>
<!-- 測試異步請求 -->
<input type="button" value="測試 ajax 請求 json 和響應 json" id="testJson"/>
控制器中的代碼:
/**
*響應 json 數據的控制器
*/
@Controller("jsonController")
public class JsonController {
/**
* 測試響應 json 數據
*/
@RequestMapping("/testResponseJson")
public @ResponseBody Account testResponseJson(@RequestBody Account account) {
System.out.println("異步請求:"+account);
return account;
}
}
運行結果:
第2章 SpringMVC 實現文件上傳
2.1文件上傳的回顧
2.1.1文件上傳的必要前提
A form 表單的 enctype 取值必須是:multipart/form-data
(默認值是:application/x-www-form-urlencoded)
enctype:是表單請求正文的類型
B method 屬性取值必須是 Post
C 提供一個文件選擇域<input type=”file” />
2.1.2文件上傳的原理分析
當 form 表單的 enctype 取值不是默認值後,request.getParameter()將失效。
enctype=”application/x-www-form-urlencoded”時,form 表單的正文內容是:
key=value&key=value&key=value
當 form 表單的 enctype 取值爲 Mutilpart/form-data 時,請求正文內容就變成:
每一部分都是 MIME 類型描述的正文
-----------------------------7de1a433602ac 分界符
Content-Disposition: form-data; name="userName" 協議頭
aaa 協議的正文
-----------------------------7de1a433602ac
Content-Disposition: form-data; name="file"; filename=
"C:\Users\zhy\Desktop\fileupload_demofile\b.txt"
Content-Type: text/plain 協議的類型(MIME 類型)
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-----------------------------7de1a433602ac--
2.1.3藉助第三方組件實現文件上傳
使用 Commons-fileupload 組件實現文件上傳,需要導入該組件相應的支撐 jar 包:Commons-fileupload 和
commons-io。commons-io 不屬於文件上傳組件的開發jar 文件,但Commons-fileupload 組件從 1.1 版本開始,它
工作時需要 commons-io 包的支持。
2.2springmvc 傳統方式的文件上傳
2.2.1說明
傳統方式的文件上傳,指的是我們上傳的文件和訪問的應用存在於同一臺服務器上。
並且上傳完成之後,瀏覽器可能跳轉。
2.2.2實現步驟
2.2.2.1第一步:拷貝文件上傳的 jar 包到工程的 lib 目錄
2.2.2.2第二步:編寫 jsp 頁面
<form action="/fileUpload" method="post" enctype="multipart/form-data">
名稱:<input type="text" name="picname"/><br/>
圖片:<input type="file" name="uploadFile"/><br/>
<input type="submit" value="上傳"/>
</form>
2.2.2.3第三步:編寫控制器
/**
*文件上傳的的控制器
*/
@Controller("fileUploadController")
public class FileUploadController {
/**
* 文件上傳
*/
@RequestMapping("/fileUpload")
public String testResponseJson(String picname,MultipartFile uploadFile,
HttpServletRequest request) throws Exception{
//定義文件名
String fileName = "";
//1.獲取原始文件名
String uploadFileName = uploadFile.getOriginalFilename();
//2.截取文件擴展名
String extendName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1,
uploadFileName.length());
//3.把文件加上隨機數,防止文件重複
String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
//4.判斷是否輸入了文件名
if(!StringUtils.isEmpty(picname)) {
fileName = uuid+"_"+picname+"."+extendName;
}else {
fileName = uuid+"_"+uploadFileName;
}
System.out.println(fileName);
//2.獲取文件路徑
ServletContext context = request.getServletContext();
String basePath = context.getRealPath("/uploads");
//3.解決同一文件夾中文件過多問題
String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
//4.判斷路徑是否存在
File file = new File(basePath+"/"+datePath);
if(!file.exists()) {
file.mkdirs();
}
//5.使用 MulitpartFile 接口中方法,把上傳的文件寫到指定位置
uploadFile.transferTo(new File(file,fileName));
return "success";
}
}
2.2.2.4第四步:配置文件解析器
<!-- 配置文件上傳解析器 -->
<bean id="multipartResolver" <!-- id的值是固定的 -->
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 設置上傳文件的最大尺寸爲 5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
注意:
文件上傳的解析器 id 是固定的,不能起別的名稱,否則無法實現請求參數的綁定。(不光是文件,其他
字段也將無法綁定)
2.3springmvc 跨服務器方式的文件上傳
2.3.1分服務器的目的
在實際開發中,我們會有很多處理不同功能的服務器。例如:
應用服務器:負責部署我們的應用
數據庫服務器:運行我們的數據庫
緩存和消息服務器:負責處理大併發訪問的緩存和消息
文件服務器:負責存儲用戶上傳文件的服務器。
(注意:此處說的不是服務器集羣)
分服務器處理的目的是讓服務器各司其職,從而提高我們項目的運行效率。
2.3.2準備兩個 tomcat 服務器,並創建一個用於存放圖片的 web 工程
在文件服務器的 tomcat 配置中加入,允許讀寫操作。文件位置:
加入內容:
加入此行的含義是:接收文件的目標服務器可以支持寫入操作。
2.3.3拷貝 jar 包
在我們負責處理文件上傳的項目中拷貝文件上傳的必備 jar 包
2.3.4編寫控制器實現上傳圖片/**
*響應 json 數據的控制器
*/
@Controller("fileUploadController2")
public class FileUploadController2 {
public static final String FILESERVERURL = "http://localhost:9090/day06_spring_image/uploads/";
/**
* 文件上傳,保存文件到不同服務器
*/
@RequestMapping("/fileUpload2")
public String testResponseJson(String picname,MultipartFile uploadFile) throws
Exception{
//定義文件名
String fileName = "";
//1.獲取原始文件名
String uploadFileName = uploadFile.getOriginalFilename();
//2.截取文件擴展名
String extendName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1,
uploadFileName.length());
//3.把文件加上隨機數,防止文件重複
String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
//4.判斷是否輸入了文件名
if(!StringUtils.isEmpty(picname)) {
fileName = uuid+"_"+picname+"."+extendName;
}else {
fileName = uuid+"_"+uploadFileName;
}
System.out.println(fileName);
//5.創建 sun 公司提供的 jersey 包中的 Client 對象
Client client = Client.create();
//6.指定上傳文件的地址,該地址是 web 路徑
WebResource resource = client.resource(FILESERVERURL+fileName);
//7.實現上傳
String result = resource.put(String.class,uploadFile.getBytes()); System.out.println(result);
return "success";
}
}
2.3.5編寫 jsp 頁面
<form action="fileUpload2" method="post" enctype="multipart/form-data">
名稱:<input type="text" name="picname"/><br/>
圖片:<input type="file" name="uploadFile"/><br/>
<input type="submit" value="上傳"/>
</form>
2.3.6配置解析器
<!-- 配置文件上傳解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 設置上傳文件的最大尺寸爲 5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
第3章 SpringMVC 中的異常處理
3.1異常處理的思路
系統中異常包括兩類:預期異常和運行時異常 RuntimeException,前者通過捕獲異常從而獲取異常信息,
後者主要通過規範代碼開發、測試通過手段減少運行時異常的發生。
系統的 dao、service、controller 出現都通過 throws Exception 向上拋出,最後由 springmvc 前端
控制器交由異常處理器進行異常處理,如下圖:
3.2實現步驟
3.2.1編寫異常類和錯誤頁面
/**
* 自定義異常
*/
public class CustomException extends Exception {
private String message;
public CustomException(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
jsp 頁面:
<%@ page language="java" contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>執行失敗</title>
</head>
<body>
執行失敗!
${message }
</body>
</html>
3.2.2自定義異常處理器
/**
*自定義異常處理器
*/
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
ex.printStackTrace();
CustomException customException = null;
//如果拋出的是系統自定義異常則直接轉換
if(ex instanceof CustomException){
customException = (CustomException)ex;
}else{
//如果拋出的不是系統自定義異常則重新構造一個系統錯誤異常。
customException = new CustomException("系統錯誤,請與系統管理 員聯繫!");
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", customException.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
3.2.3配置異常處理器
<!-- 配置自定義異常處理器 -->
<bean id="handlerExceptionResolver" class="com.itheima.exception.CustomExceptionResolver"/>
3.2.4運行結果:
第4章 SpringMVC 中的攔截器
4.1攔截器的作用
Spring MVC 的處理器攔截器類似於 Servlet 開發中的過濾器 Filter,用於對處理器進行預處理和後處理。
用戶可以自己定義一些攔截器來實現特定的功能。
談到攔截器,還要向大家提一個詞——攔截器鏈(Interceptor Chain)。攔截器鏈就是將攔截器按一定的順
序聯結成一條鏈。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其之前定義的順序被調用。
說到這裏,可能大家腦海中有了一個疑問,這不是我們之前學的過濾器嗎?是的它和過濾器是有幾分相似,但
是也有區別,接下來我們就來說說他們的區別:
過濾器是 servlet 規範中的一部分,任何 java web 工程都可以使用。
攔截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
過濾器在 url-pattern 中配置了//*之後,可以對所有要訪問的資源攔截。
攔截器它是隻會攔截訪問的控制器方法,如果訪問的是 jsp,html,css,image 或者 js 是不會進行攔
截的。
它也是 AOP 思想的具體應用。
我們要想自定義攔截器, 要求必須實現:HandlerInterceptor 接口。
4.2自定義攔截器的步驟
4.2.1第一步:編寫一個普通類實現 HandlerInterceptor 接口
/**
*自定義攔截器
*/
public class HandlerInterceptorDemo1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("preHandle 攔截器攔截了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler,ModelAndView modelAndView) throws Exception {
System.out.println("postHandle 方法執行了");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion 方法執行了");
}
}
4.2.2第二步:配置攔截器
<!-- 配置攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean id="handlerInterceptorDemo1"
class="com.itheima.web.interceptor.HandlerInterceptorDemo1"></bean>
</mvc:interceptor>
</mvc:interceptors>
4.2.3測試運行結果:
4.3攔截器的細節
4.3.1攔截器的放行
放行的含義是指,如果有下一個攔截器就執行下一個,如果該攔截器處於攔截器鏈的最後一個,則執行控制器
中的方法。
4.3.2攔截器中方法的說明
public interface HandlerInterceptor {
/**
* 如何調用:
* 按攔截器定義順序調用
* 何時調用:
* 只要配置了都會調用
* 有什麼用:
* 如果程序員決定該攔截器對請求進行攔截處理後還要調用其他的攔截器,或者是業務處理器去
* 進行處理,則返回 true。
* 如果程序員決定不需要再調用其他的組件去處理請求,則返回 false。
*/
default boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
return true;
}
/**
* 如何調用:
* 按攔截器定義逆序調用
* 何時調用:
* 在攔截器鏈內所有攔截器返成功調用
* 有什麼用:
* 在業務處理器處理完請求後,但是 DispatcherServlet 向客戶端返回響應前被調用,
* 在該方法中對用戶請求 request 進行處理。
*/
default void postHandle(HttpServletRequest request,HttpServletResponseresponse,
Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
/**
* 如何調用:
* 按攔截器定義逆序調用
* 何時調用:
* 只有 preHandle 返回 true 才調用
* 有什麼用:
* 在 DispatcherServlet 完全處理完請求後被調用,
* 可以在該方法中進行一些資源清理的操作。
*/
default void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, @Nullable Exception ex) throws Exception {
}
}
思考:
如果有多個攔截器,這時攔截器 1 的 preHandle 方法返回 true,但是攔截器 2 的 preHandle 方法返回 false,而此時攔截器 1 的 afterCompletion 方法是否執行?
4.3.3攔截器的作用路徑
作用路徑可以通過在配置文件中配置。
<!-- 配置攔截器的作用範圍 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" /><!-- 用於指定對攔截的 url -->
<mvc:exclude-mapping path=""/><!-- 用於指定排除的 url-->
<bean id="handlerInterceptorDemo1"
class="com.itheima.web.interceptor.HandlerInterceptorDemo1"></bean>
</mvc:interceptor>
</mvc:interceptors>
4.3.4多個攔截器的執行順序
多個攔截器是按照配置的順序決定的。
4.4正常流程測試
4.4.1配置文件:
<!-- 配置攔截器的作用範圍 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" /><!-- 用於指定對攔截的 url -->
<bean id="handlerInterceptorDemo1"
class="com.itheima.web.interceptor.HandlerInterceptorDemo1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean id="handlerInterceptorDemo2"
class="com.itheima.web.interceptor.HandlerInterceptorDemo2"></bean>
</mvc:interceptor>
</mvc:interceptors>
4.4.2攔截器 1 的代碼:
/**
*自定義攔截器
*/
public class HandlerInterceptorDemo1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("攔截器 1:preHandle 攔截器攔截了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler,ModelAndView modelAndView) throws Exception {
System.out.println("攔截器 1:postHandle 方法執行了");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("攔截器 1:afterCompletion 方法執行了");
}
}
4.4.3攔截器 2 的代碼:
/**
*自定義攔截器
*/
public class HandlerInterceptorDemo2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("攔截器 2:preHandle 攔截器攔截了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler,ModelAndView modelAndView) throws Exception {
System.out.println("攔截器 2:postHandle 方法執行了");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("攔截器 2:afterCompletion 方法執行了");
}
}
4.4.4運行結果:
4.5中斷流程測試
4.5.1配置文件:
<!-- 配置攔截器的作用範圍 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" /><!-- 用於指定對攔截的 url -->
<bean id="handlerInterceptorDemo1"
class="com.itheima.web.interceptor.HandlerInterceptorDemo1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean id="handlerInterceptorDemo2"
class="com.itheima.web.interceptor.HandlerInterceptorDemo2"></bean>
</mvc:interceptor>
</mvc:interceptors>
4.5.2攔截器 1 的代碼:
/**
*自定義攔截器
*/
public class HandlerInterceptorDemo1 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("攔截器 1:preHandle 攔截器攔截了");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler,ModelAndView modelAndView) throws Exception {
System.out.println("攔截器 1:postHandle 方法執行了");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("攔截器 1:afterCompletion 方法執行了");
}
}
4.5.3攔截器 2 的代碼:
/**
*自定義攔截器
*/
public class HandlerInterceptorDemo2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("攔截器 2:preHandle 攔截器攔截了");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler,ModelAndView modelAndView) throws Exception {
System.out.println("攔截器 2:postHandle 方法執行了");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("攔截器 2:afterCompletion 方法執行了");
}
}
4.5.4運行結果:
4.6攔截器的簡單案例(驗證用戶是否登錄)
4.6.1實現思路
1、有一個登錄頁面,需要寫一個 controller 訪問頁面
2、登錄頁面有一提交表單的動作。需要在 controller 中處理。
2.1、判斷用戶名密碼是否正確
2.2、如果正確 向 session 中寫入用戶信息
2.3、返回登錄成功。
3、攔截用戶請求,判斷用戶是否登錄
3.1、如果用戶已經登錄。放行
3.2、如果用戶未登錄,跳轉到登錄頁面
4.6.2控制器代碼
//登陸頁面
@RequestMapping("/login")
public String login(Model model)throws Exception{
return "login";
}
//登陸提交
//userid:用戶賬號,pwd:密碼
@RequestMapping("/loginsubmit")
public String loginsubmit(HttpSession session,String userid,String pwd)throws Exception{
//向 session 記錄用戶身份信息
session.setAttribute("activeUser", userid);
return "redirect:/main.jsp";
}
//退出
@RequestMapping("/logout")
public String logout(HttpSession session)throws Exception{
//session 過期
session.invalidate();
return "redirect:index.jsp";
}
4.6.3攔截器代碼
public class LoginInterceptor implements HandlerInterceptor{
@Override
Public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
//如果是登錄頁面則放行
if(request.getRequestURI().indexOf("login.action")>=0){
return true;
}
HttpSession session = request.getSession();
//如果用戶已登錄也放行
if(session.getAttribute("user")!=null){
return true;
}
//用戶沒有登錄挑戰到登錄頁面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}