# springMVC **Repository Path**: zhangyanghao/springmvc ## Basic Information - **Project Name**: springMVC - **Description**: 使用springMVC框架实现后台管理功能 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2017-05-29 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 入门 1. 引入spring 以及springmvc的jar包 2. 请求流程 3. 配置 3.0 在src/main/resources新建一个 spring的配置文件 applicationContext.xml 3.1 让web容器在启动的时候加载spring配置文件,创建spring IOC容器 。 在web.xml中配置一个 context-param (web应用上下文参数),指定要加载的spring配置文件 在web.xml中配置一个 DispatcherServlet ,将它设置为默认的Servlet,然后为该servelt配置一个对应的spring配置文件,这个配置文件在 WEB-INF/目录中, 名称规则是 [servletName]-servlet.xml 3.2 在`[servletName]-servlet.xml` 为springMVC做配置 配置点1: 打开annotation扫描 配置点2: 配置视图模板相关的(视图解析器 ViewResolver),比如 模板放在哪里, 前缀,后缀等等。 4. 开发 1. 定义Controller 在Controller中定义方法.因为这个类要被spring容器实例化,所以要在类上 添加 @Controller。 2. 定义方法 这个方法是请求到来的时候要调用的。所以应该在这个方法上 使用 @RequestMapping 来指定这个方法对应的请求地址 方法上定义一个 Model参数,这个参数是 DispatcherServlet调用方法的时候传递进来的。因为我们需要将处理的结果保存到model中。 返回的是一个String类型的字符串,它表示视图的地址。这个视图的地址 最终是 由视图解析器中配置的前缀 + 方法返回值+ 视图解析器中配置的后缀来 组合完成的。 ### @RequestMapping 做请求映射,最后调用的一定是 方法,所以在开发的时候,方法上是一定要加的。 如果它加载类上,那么最终的请求的地址就是 类上面的映射地址和 方法上的映射地址的组合 [关于restful](http://www.ruanyifeng.com/blog/2011/09/restful) 可以在@RequestMapping的请求路径中添加`路径变量`,从路径中取出变量应该使用`@PathVariable`,如果路径变量与参数名称一致,则不用添加参数,如果不一致,则需要在@PathVariable指出路径变量的名称。 如: @RequestMapping(value="/{id}",method=RequestMethod.GET) public String show(@PathVariable String id){ return "student/show"; } @RequestMapping(value="/{id}",method=RequestMethod.GET) public String show(@PathVariable("id") String id){ return "student/show"; } ### rest风格路由约定 以数据库表 users为例: Method | URL | Controller类名 | Controller方法名 | view文件名 | 说明 ------------- | --- | ------------- | ------------ | ------- | --- GET | /users | UsersController | index() | views/users/index.jsp | 列出所有用户 GET | /users/create | UsersController | _new() | views/users/new.jsp | 呈现新建用户的表单 POST | /users/create | UsersController | create() | | 保存到数据库,create方法执行完毕后进行重定向,以免发生重复提交 GET | /users/{id} | UsersController | show() | views/users/show.jsp | 显示指定id的信息 GET | /users/{id}/update | UsersController | edit() | views/users/edit.jsp | 显示编辑页面 PUT | /users/{id}/update | UsersController | update() | | 更新到数据库,update方法执行完毕后进行重定向,以免发生重复提交 DELETE | /users/{id} | UsersController | destory() | | 从数据库中删除,destory方法执行完毕后进行重定向,以免发生重复提交 ### handler methods controller中用来处理请求的方法被称为 Handler Method (处理器) #### Handler method 可接受的参数类型 SpringMVC 中的Front Controller (DispatcherServlet) 调用 Controller中的方法来处理请求,因为Controller被springIOC托管了,所以在调用Controller Handler方法的时候,就可以为方法注入参数。这些可以被注入的参数的类型常用的包含: - ServletRequest or HttpServletRequest - ServletResponse or HttpServletResponse - HttpSession - org.springframework.web.context.request.WebRequest or org.springframework.web.context.request.NativeWebRequest - java.util.Locale 用于国际化 - java.io.InputStream / java.io.Reader 可以读取请求中的输入流 - java.io.OutputStream / java.io.Writer 响应的输出流 - @PathVariable 请求路径变量 - @RequestParam 请求参数 - @RequestHeader 请求头 - @RequestPart 用于文件上传,获取上传的文件流 - org.springframework.ui.Model 用来存储视图上用到的数据 - org.springframework.web.servlet.mvc.support.RedirectAttributes - form objects to bind request parameters to bean properties (实体对象,SpringMVC可以将请求参数中的数据取出来后,创建实体对象,然后将这些数据设置到实体对象中) - org.springframework.validation.BindingResult 用于数据验证的时候 #### Handler method 返回类型 - ModelAndView - Model Object 可以直接将Model返回 常用于 ajax请求,返回 json数据 - Map 同上 - View object - A String value 一般情况下表示视图的逻辑名称 - void - method is annotated with @ResponseBody 如果处理器方法使用@ResponseBody表示,默认返回的是JSON格式的数据,首先需要引入jar包 com.fasterxml.jackson.core jackson-core 2.5.1 com.fasterxml.jackson.core jackson-databind 2.5.1 org.codehaus.jackson jackson-core-lgpl 1.9.6 org.codehaus.jackson jackson-core-asl 1.9.4 org.codehaus.jackson jackson-mapper-asl 1.9.5 org.codehaus.jackson jackson-mapper-lgpl 1.9.6 然后在 applicationContext中配置转换器和打开mvc的annotation配置: ### springmvc不拦截静态资源 ### SpringMVC标签库 1. 引入标签库 ``` <%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%> ``` 2. form:form 生成html form表单,可以绑定后台的model 3. form:input 生成input标签,可以绑定model中的某个property 4. form:radioButtons 绑定一组 radio button ### springmvc的数据校验 1. 引入验证jar包 ``` org.hibernate hibernate-validator 5.4.1.Final ``` 2. 在实体类上添加 annotation ,可以查看:org.hibernate.validator.constraints 和 javax.validation.constraints 包中的annotation 3. 在controller的处理器方法中添加 ``` public String create(@Valid Student student,BindingResult bindResult,Model model) ``` 注意: BindingResult一定要紧随 @Valid之后,然后可以在Controller中判断是否出错: ``` if(bindResult.hasErrors()){ } ``` SPring框架执行的时候: 首先收到请求,然后将请求中的参数放到student的property中,最后验证,验证的结果放在 BindingResult对象中。所有的这些操作都是在调用 Controller方法之前完成的。 4. 在页面上使用 form:errors来显示错误信息 ``` ``` ### @ModelAttribute 1. 修饰处理器方法的参数。执行过程: 首先到model中查找对象,如果model中已经存在对象,那么直接使用,如果不存在,则需要创建一个新的对象,然后放到model中。如果没有指定value,则使用 类型的首字母小写作为key放入到范围,然后将请求参数中的数据设置到对象中。 ### 乱码的问题 springMVC 提供了一个 filter,只需要在 web.xml中进行配置即可解决乱码的问题 ``` characterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 forceEncoding true characterEncodingFilter /* ``` ### RedirectAttributes 可以在session范围内保存数据,但是只要使用过一次之后,这个数据就会被删除。 说它特别适合在从定向的时候保存数据。 ``` redirectAttributes.addFlashAttribute(attributeName, attributeValue) ``` ### 自定义jsp标签 1. 编写一个类,继承SimpleTagSupport 重写doTag方法,在这个方法中获取 PageContext,再从pageContext中获取输出流,然后用流输出 2. 在src/main/resources目录中新建文件夹META-INF,再新建一个 tld文件,这个文件是标签描述文件。 3. 在jsp中引入自定义标签,然后使用 ### 登录 账号表中不存储密码的明文,应该存储密文(加密过的,并且不可逆+随机盐值) 至少应该有以下几个字段: 账号,密码密文, 盐值,最后一次登录时间 创建逻辑: 使用系统默认的密码,产生一个随机的盐值,然后进行加密,将加密的密文和 盐值都存储到数据库表中 验证逻辑: 先用账号从数据库中取出一行数据,然后 将 盐值与 输入的密码一起加密,比较 加密的结果与数据库中存储的结果是否一致 ### SpringMVC拦截器 Spring MVC中的Controller的 处理器方法还没有执行之前,可以对请求进行拦截。类似于 Servlet中的 Filter区别是 Filter是被web容器管理的,而 Spring HandlerInterceptor是被Spring容器管理的. ``` public interface HandlerInterceptor { boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; } ``` 接口中定义了三个方法 - preHandle方法 在Controller中的处理器方法执行之前进行拦截 - postHandle方法 在Controller中的处理器方法执行之后进行拦截,但是视图还没有渲染之前 -afterCompletion方法 在Controller中的处理器方法执行之后进行而且视图还已经渲染完毕,开始执行 -参数解释 - request 请求 - response 响应 - handler 对应的处理器方法(真正干活的,有可能是一个字符串,也有可能是一个方法 Method) - modelAndView SpringMVC 的modelAndView 。 因为postHandle 是在处理器方法执行完毕之后拦截的,所以可以获取到处理器方法执行的结果 - Exception :afterCompletion 是视图渲染完毕之后拦截的,拦截之前如果有异常,此时就可以进行拦截 自定义的拦截器需要实现这个接口,不过 SpringMVC中提供了一个类 HandlerInterceptorAdapter,它实现了HandlerInterceptor接口,只不过它的实现都是空实现。我们只需要继承这个类,然后重写感兴趣的方法即可。 - 注册 在applicationContext-springmvc.xml文件中配置拦截器