资源下载:http://download.csdn.net/detail/huhui_bj/8544163
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> <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>这里配置的servlet-name属性值是dispatcherServlet,故下文中Spring MVC的配置文件名称为dispatcherServlet-servlet.xml,名称一定要对应,这很重要。
如果还需要设置字符过滤器,则还应增加如下配置:
<!-- 设置字符编码 --> <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>
这个是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>
@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"; }*/ }
在用户数据校验时,需要用到bean-validator.jar,在User.java文件中添加校验:
@NotEmpty(message="用户名不能为空") public String getUsername() { return username; } @Email(message="邮箱格式不正确") public String getEmail() { return email; }
<sf:errors path="username"></sf:errors>