Spring+Spring MVC+JDBCTemplate實現簡單的使用者管理功能
1. 前言
最近一直在學習Spring相關的知識,這篇部落格是一個階段性的自我總結,寫給自己以後作為參考用。本文介紹的是使用Spring、Spring MVC和JDBCTemplate來實現一個十分簡單的使用者管理功能,實現資料的增、刪、改、查。工程目錄是這樣的:
在src的config目錄中存放的是jdbc.properties檔案,即資料庫配置檔案。Spring部分的知識實際上在之前的部落格中已經總結過:傳送1,傳送2,傳送3 ,這篇部落格主要想總結一下最近學習的Spring MVC相關知識。
2. Spring MVC工作原理
上面的是springMVC的工作原理圖:
1、客戶端發出一個http請求給web伺服器,web伺服器對http請求進行解析,如果匹配DispatcherServlet的請求對映路徑(在web.xml中指定),web容器將請求轉交給DispatcherServlet.
2、DipatcherServlet接收到這個請求之後將根據請求的資訊(包括URL、Http方法、請求報文頭和請求引數Cookie等)以及HandlerMapping的配置找到處理請求的處理器(Handler)。
3-4、DispatcherServlet根據HandlerMapping找到對應的Handler,將處理權交給Handler(Handler將具體的處理進行封裝),再由具體的HandlerAdapter對Handler進行具體的呼叫。
5、Handler對資料處理完成以後將返回一個ModelAndView()物件給DispatcherServlet。
6、Handler返回的ModelAndView()只是一個邏輯檢視並不是一個正式的檢視,DispatcherSevlet通過ViewResolver將邏輯檢視轉化為真正的檢視View。
7、Dispatcher通過model解析出ModelAndView()中的引數進行解析最終展現出完整的view並返回給客戶端。
3. 配置檔案
(1)web.xml
首先是配置web.xml檔案,增加如下配置:
這裡配置的servlet-name屬性值是dispatcherServlet,故下文中Spring MVC的配置檔名稱為dispatcherServlet-servlet.xml,名稱一定要對應,這很重要。<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
如果還需要設定字元過濾器,則還應增加如下配置:
<!-- 設定字元編碼 --> <filter> <filter-name>CharacterFilter</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>CharacterFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
(2)dispatcherServlet-servlet.xml
這個是Spring MVC的配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven/>
<!-- 開啟Spring的Annotation支援 -->
<context:annotation-config />
<!-- 設定Spring掃描Annotation的範圍 -->
<context:component-scan base-package="com.um" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 讀取jdbc.properties檔案 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置全域性異常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="com.springmvc.model.UserException">user/error</prop> <!-- 當丟擲UserException異常,則進入error頁面 -->
</props>
</property>
</bean>
<!-- 將靜態檔案(如css檔案)指定到某個特殊的資料夾中統一處理 -->
<mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources> <!-- 一個*代表resources中的檔案,兩個**代表resources中檔案及子檔案內容 -->
<!-- 設定了multipartResolver才能完成檔案上傳 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5000000"></property> <!-- 設定檔案大小是5M -->
</bean>
</beans>
4.UserController.java
@Controller
@RequestMapping("/user") //這個意思是凡是要訪問這個Controller,就需要在前面加user
public class UserController {
@Resource
private UserService userService;
@RequestMapping(value="/users", method=RequestMethod.GET) //當URL中有"/user/users",且是get方法則訪問這個方法,
public String list(Model model){
List<User> userList = userService.query();
model.addAttribute("userList", userList);
return "user/users";
}
//連結到add頁面時是GET請求,會訪問這段程式碼
@RequestMapping(value="/add", method=RequestMethod.GET)
public String add(Model model){
//開啟modelDriven
model.addAttribute(new User());
return "user/add"; //伺服器端跳轉
}
//在具體新增使用者時,是post請求,就訪問以下程式碼
@RequestMapping(value="/add", method=RequestMethod.POST)
public String add(@Validated User user, BindingResult br, MultipartFile attach, HttpServletRequest request) throws IOException{//bean驗證,驗證User,一定要緊跟@Validated之後寫驗證結果
if(br.hasErrors()){
return "user/add";//如果有錯誤,則跳轉到add頁面
}
String realPath = request.getSession().getServletContext().getRealPath("/resources/upload");
File f = new File(realPath+"/"+attach.getOriginalFilename());
FileUtils.copyInputStreamToFile(attach.getInputStream(), f);
System.out.println(attach.getName()+", "+attach.getOriginalFilename()+", "+attach.getContentType());
userService.add(user);
return "redirect:/user/users";
}
@RequestMapping(value="/{username}", method=RequestMethod.GET)//只要不涉及更新,就用get方法
public String show(@PathVariable String username, Model model){ // @PathVariable表示路徑中的某個值(/{username})用作引數
model.addAttribute(userService.query(username)); //傳入一個User物件,檢視得到的就是一個key為user,值為User的物件
return "user/show";
}
@RequestMapping(value="/{username}", method=RequestMethod.GET, params="json")
@ResponseBody
public User show(@PathVariable String username){
return userService.query(username);
}
@RequestMapping(value="/{username}/update", method=RequestMethod.GET)
public String update(@PathVariable String username, Model model){
model.addAttribute(userService.query(username));
return "user/update";
}
@RequestMapping(value="/{username}/update", method=RequestMethod.POST)
public String update(@Validated User user, BindingResult br, @PathVariable String username){
if(br.hasErrors()){
return "user/update";
}
userService.update(username, user);
return "redirect:/user/users";
}
@RequestMapping(value="/{username}/delete", method=RequestMethod.GET)
public String delete(@PathVariable String username){
userService.delete(username);
return "redirect:/user/users";
}
@RequestMapping(value="/login", method=RequestMethod.POST)
public String login(String username, String password, HttpSession session){//會自動注入session
if(!users.containsKey(username)){
throw new UserException("使用者名稱不存在");
}
User u = users.get(username);
if(!u.getPassword().equals(password)){
throw new UserException("密碼錯誤");
}
session.setAttribute("loginUser", u);
return "redirect:/user/users";
}
/**
* 區域性異常處理,僅僅只能處理這個控制器的異常
*/
/*@ExceptionHandler(value={UserException.class})
public String handleException(UserException e, HttpServletRequest request){
request.setAttribute("e", e);
return "user/error";
}*/
}
5.使用者資料校驗
在使用者資料校驗時,需要用到bean-validator.jar,在User.java檔案中新增校驗:
@NotEmpty(message="使用者名稱不能為空")
public String getUsername() {
return username;
}
@Email(message="郵箱格式不正確")
public String getEmail() {
return email;
}
然後在View層新增校驗失敗時的顯示資訊:
<sf:errors path="username"></sf:errors>