文档章节

SpringMvc的使用

丈量大地
 丈量大地
发布于 2015/11/26 14:58
字数 4255
阅读 553
收藏 36

目录结构

一、SpringMvc相关知识

        11SpringMvc的大体认识

        12、什么是MVC

        13SpringMvc内部是怎么样工作的?

二、环境以及第三方技术的说明

三、我们进入正题,下边通过一个个实例来介绍SpringMvc的用法

    31、重要配置文件的说明

    32、用户注册例子

    33、主页的展示

    34、登录例子

    35、文件上传

    36、表单的服务器端验证

 

一、SpringMvc相关知识

11SpringMvc的大体认识

SpringMvc构建在Spring框架的基础上,是对Servlet进行封装(对客户端的请求以及响应进行很友好的处理),方便我们开发Java EE程序的MVC框架。

12、什么是MVC

MVC全名是ModelViewController,他是一种软件设计的理念,即将数据、界面展现、业务逻辑进行分离,其好处是方便一个系统中不同开发角色的分工,相互之间没有太大的耦合,并且各层的代码也能进行很好的重用。其中:

M是模型Model的缩写,如对数据的存取;

V是视图View的缩写,是对M层提供数据以及展现M层的数据,常见技术包括JSPVelocityTilesiTextPOI

CController的缩写,它的一个重要的职责是将V层的数据获取到后交给M,最后将M层的数据交给V

13SpringMvc内部是怎么样工作的?

根据其工作原理,其内部工作流程如下图:

二、环境以及第三方技术的说明

当前项目是用Maven构建,其版本为apache-maven-3.0.4,开发工具为Eclipse,代码放在开源中国的Git中,当前项目的下载地址为:https://git.oschina.net/liw/Sports-SpringMvc.git ,其他环境以及技术说明如下:

 

第三方技术

版本

本实例中的作用

JDK

1.7

Tomcat

7

Web容器

Spring

4.1.4.RELEASE

Bean IOC

SpringMvc

4.1.4.RELEASE

MVC框架中处于C层,其作用为请求的处理以及处理结果的转发

jackson-mapper-asl

1.9.13

Jackson ,一种用于Json处理的第三方技术

jackson-annotations

2.5.0

jackson-core

2.5.0

jackson-databind

2.5.0

Jstl

1.2

Jsp页面数据的展现

Servlet-api

3.1-b05

J2EE的基础

hibernate-validator

5.2.2.Final

服务器端bean的验证技术,即可以对表单进行服务器端验证

Commons-fileupload

1.2.2

文件上传

Commons-io

2.4

Commons-lang

3.4

提供字符串、对象、日期、数字等方便处理的帮助类

BootStrap

3.3.5

用于页面展现布局等

Jquery

1.11.3

页面数据元素的操作

 

三、我们进入正题,下边通过一个个实例来介绍SpringMvc的用法 

31、几个配置文件的说明,设计到的配置文件有:spring.xmlspring-mvc.xmlweb.xml

spring.xml:

<?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:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-4.1.xsd">
 <context:component-scan base-package="cn.com.sports.utils"></context:component-scan>  
</beans>

我将一些工具类放到了cn.com.sports.utils包中,并配置自动扫描这个包下的类,方面在其他类中使用

spring-mvc.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-4.1.xsd 
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-4.1.xsd 
  http://www.springframework.org/schema/mvc 
  http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
 <!-- 自动扫描controller包下的所有类,如果@Controller注入为bean -->
 <context:component-scan base-package="cn.com.sports.controller" />
 <!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->
 <bean id="mappingJacksonHttpMessageConverter"
  class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
  <property name="supportedMediaTypes">
   <list>
    <value>text/html;charset=UTF-8</value>
   </list>
  </property>
 </bean>
 <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
 <bean
  class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  <property name="messageConverters">
   <list>
    <!-- json转换器 -->
    <ref bean="mappingJacksonHttpMessageConverter" />
   </list>
  </property>
 </bean>
 <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
 <bean
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass"
   value="org.springframework.web.servlet.view.JstlView" />
  <property name="prefix" value="/WEB-INF/views" />
  <property name="suffix" value=".jsp" />
 </bean>
 <!-- 配置多文件上传 -->  
    <bean id="multipartResolver"  
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
        <property name="defaultEncoding">  
            <value>UTF-8</value>  
        </property>  
        <property name="maxUploadSize">  
            <!-- 上传文件大小限制为31M,31*1024*1024 -->  
            <value>32505856</value>  
        </property>  
        <property name="maxInMemorySize">  
            <value>4096</value>  
        </property>  
    </bean>
    <mvc:interceptors>
     <bean class="cn.com.sports.interceptor.AllInterceptor"></bean>
     <mvc:interceptor>
      <mvc:mapping path="/login/otherHandUI.html"/>
      <bean class="cn.com.sports.interceptor.LoginInterceptor"></bean>
     </mvc:interceptor>
    </mvc:interceptors>
    
    <mvc:annotation-driven validator="validator"/>  
 <!-- 以下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册-->  
 <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">  
     <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>  
 </bean> 
</beans>

当前文件的配置文件有以下作用,当然你还能配置其他的,以下说明只适用于本项目

对bean到Json,以及返回Json到客户端的配置处理;

配置返回视图页面的前缀以及后缀;

配置文件上传的相关参数;

配置拦截器的相关信息;

配置使用HibernateValidator进行服务器验证 ;

web.xml :

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 id="WebApp_ID" version="3.0">
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:spring.xml</param-value>
 </context-param>
 <filter>
  <filter-name>encodingFilter</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>
  <init-param>
   <param-name>forceEncoding</param-name>
   <param-value>true</param-value>
  </init-param>
 </filter>
 <filter-mapping>
  <filter-name>encodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <!-- 防止spring内存溢出监听器 -->
 <listener>
  <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
 </listener>
 <servlet>
  <description>spring mvc servlet</description>
  <servlet-name>rest</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>
    classpath:spring-mvc.xml
   </param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>rest</servlet-name>
  <url-pattern>*.html</url-pattern>
 </servlet-mapping>
 <!-- 配置session超时时间,单位分钟 -->
 <session-config>
  <session-timeout>30</session-timeout>
 </session-config>
 <welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
  <display-name>Sports-SpringMvc</display-name>
</web-app>

对web.xml没什么多说的,只说明下当前项目中,配置的前端Servlet DispaterServlet只对后缀已.html结尾的URI进行拦截处理

32、一个人员注册的例子

首先创建一个bean,名称为User.java ,其中包含一些用户的基本信息,其字段上的直接可以先不关注

package cn.com.sports.model;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
public class User {
 private String id ;
 @NotEmpty(message="username不能为空")
 private String username ;
 @NotEmpty(message="密码不能为空")
 private String password ;
 @Email(message="email字段必须为Email")
 private String email ;
 private String hobby ;
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 public String getHobby() {
  return hobby;
 }
 public void setHobby(String hobby) {
  this.hobby = hobby;
 }
 public static void main(String[] args) {
  
 }
}

创建一个Controller,名称为:UserController ,其中包含对用户的各种操作的Handler

package cn.com.sports.controller;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import org.apache.commons.lang3.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import cn.com.sports.model.User;
import cn.com.sports.utils.DB;
import cn.com.sports.utils.KeyGeneratorImpl;
import cn.com.sports.utils.Utils;
@Controller
@RequestMapping("/user")
public class UserController {
 @Autowired
 private DB db ;
 @Autowired
 Validator validator ;
 /**
  * 返回添加人员视图
  * @return
  */
 @RequestMapping("/addUserUI")
 public String addUI(){
  return "/user/addUser";
 }
 /**
  * 对添加人员进行处理
  * @param user
  * @param modelMap
  * @return 服务器端定向到展示所有用户页面
  */
 @RequestMapping("/addUser")
 public String addUser(User user,ModelMap modelMap){
  String url = "redirect:/user/showUsers.html" ;
  //服务器端验证
  String error = validate(user);
  if(!"".equals(error.toString())){
   modelMap.addAttribute("errors", "用户保存失败!<br>"+error.toString());
   return "/user/addUser";
  }
  KeyGeneratorImpl k = new KeyGeneratorImpl();
  try {
   user.setId(k.getKey());
   user.setPassword(Utils.encrypt(user.getPassword()));
  } catch (Exception e) {
   e.printStackTrace();
  }
  if(db.getUserByUserOrEmail(user.getUsername()) == null)
   db.saveOrUpdateUser(user);
  else{
   modelMap.addAttribute("user", user);
   modelMap.addAttribute("flag", "1");
   url = "/user/addUser";
  }
    
  return url;
 }
 /**
  * 返回所有人员页面的视图
  * @param modelMap
  * @return
  */
 @RequestMapping("/showUsers")
 public String showUsers(ModelMap modelMap){
  List<User> users = db.getAllUser();
  modelMap.addAttribute("users",users);
  return "/user/showUsers";
 }
 /**
  * 通过人员ID删除人员
  * @param modelMap
  * @param userId
  * @return
  */
 @RequestMapping("/delUser/{userId}")
 public ModelAndView showUsers(ModelMap modelMap,@PathVariable String userId){
  db.delUser(userId);
  return new ModelAndView("redirect:/user/showUsers.html");
 }
 /**
  * 返回编辑页面视图
  * @param modelMap
  * @param userId
  * @return
  */
 @RequestMapping("/editUserUI/{userId}")
 public String editUserUI(ModelMap modelMap,@PathVariable String userId){
  User user = db.getUserById(userId);
  modelMap.addAttribute("user",user);
  return "/user/editUser";
 }
 /**
  * 对编辑人员进行处理
  * @param user
  * @param modelMap
  * @return
  */
 @RequestMapping("/editUser")
 public String editUserUI(User user,ModelMap modelMap){
  //服务器端验证
  String error = validate(user);
  if(!"".equals(error.toString())){
   modelMap.addAttribute("errors", "修改用户失败!<br>"+error.toString());
   return "/user/editUser";
  }
  db.saveOrUpdateUser(user);
  modelMap.addAttribute("flag", "1");
  return "/user/editUser";
 }
 public String validate(User user){
  Set<ConstraintViolation<User>> violations = validator.validate(user);
  StringBuffer buf = new StringBuffer(); 
   for(ConstraintViolation<User> violation: violations) { 
    String f = violation.getPropertyPath().toString() ;
    buf.append(f +":"+ violation.getMessage() +"<br>" ); 
  }
  return buf.toString();
 }
}

UserController中的方法很多,这里我们先只看addUI() 、 addUser()  、showUsers()这三方法

首先我们通过标签@Controller标注当前类为一个Controller,并且用标签@RequestMapping进行标注,其值为"/user" ,说明UserController类中方法在其标签@RequestMapping值中加上"/user"

其次addUI() 、 addUser() 、showUsers()三方法的标签@RequestMapping("/addUserUI")、@RequestMapping("/addUser")、@RequestMapping("/showUsers") ,其含义是浏览器请求/user/addUserUI.php、/user/addUserHand.php 、/user/showUsers.php后分别请求到的资源

再对UserController中的类DB类进行说明,这里的Validator类可以先不看,后边在进行说明

DB:这里的DB相当于一个服务器端的临时数据库,对用户的数据以及后边的文件信息的维护

package cn.com.sports.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.stereotype.Component;
import cn.com.sports.model.File;
import cn.com.sports.model.User;
@Component
public class DB {
 private static Map<String,User> t_user = new HashMap<String,User>();
 private static Map<String,File> t_file = new HashMap<String,File>();
 public void saveOrUpdateUser(User user){
  t_user.put(user.getId(), user);
 }
 public void delUser(String id){
  t_user.remove(id);
 }
 public List<User> getAllUser(){
  List<User> users = new ArrayList<User>();
  Set<String> keys = t_user.keySet();
  for(String key : keys){
   users.add(t_user.get(key));
  }
  return users ;
 }
 public User getUserById(String id){
  return t_user.get(id);
 }
 public User getUserByUserOrEmail(String s){
  User user = null ;
  List<User> users = getAllUser();
  for(User u : users){
   if(s.equals(u.getEmail()) || s.equals(u.getUsername())){
    user = u ;
    break ;
   }
  }
  return user ;
 }
 public void saveFile(File file){
  t_file.put(file.getId(), file);
 }
 public List<File> getAllFile(){
  Set<String> files = t_file.keySet();
  List<File> flist = new ArrayList<File>();
  for(String f : files){
   flist.add(t_file.get(f));
  }
  return flist ;
 }
}

说完了Model、Controller,下边我们来看下前端的View

addUser.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=ISO-8859-1">
<%@ include file="/common/taglib.jsp" %>
<%@ include file="/common/common.jsp" %>    
<base href="<%=basePath%>">
<title>添加用户</title>
</head>
<body>
<div class="container">
<h2 class="bg-info">添加用户</h2> 
<c:if test="${flag == 1 }">
<h5 class="bg-danger">添加用户失败,Username重复</h5>
</c:if>
<span style="color: red;">
 ${errors }
</span>
<form action="user/addUser.html" method="post">
   <div class="form-group">
     <label for="exampleInputEmail1">Username</label>
     <input type="text" class="form-control" id="exampleInputEmail1" placeholder="Username" name="username" value="${user.username }">
   </div>
   <div class="form-group">
     <label for="exampleInputEmail1">Email</label>
     <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email" name="email" value="${user.email }">
   </div>
   <div class="form-group">
     <label for="exampleInputPassword1">Password</label>
     <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password" name="password" value="${user.password }">
   </div>
   <div class="form-group">
     <label for="exampleInputEmail1">Yours Hobby</label>
     <input type="text" class="form-control" id="exampleInputEmail1" placeholder="hobby" name="hobby" value="${user.hobby }">
   </div> 
   <button type="submit" class="btn btn-default">Submit</button>
   <button type="reset" class="btn btn-default">Reset</button>
</form>
<br/>
<a href="user/showUsers.html" >返回人员列表</a>
</div>
</body>
</html>

用户信息呈现列表:

showUsers.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=ISO-8859-1">
<%@ include file="/common/taglib.jsp" %>
<%@ include file="/common/common.jsp" %>
<title>显示所有用户信息</title>
<base href="<%=basePath%>">
</head>
<body>
<div class="container">
 <h2 class="bg-info">展示用户</h2>
 <table class="table table-bordered table-hover">
 <thead>
 <tr>
  <th>Username</th>
  <th>Email</th>
  <th>Hobby</th>
  <th>ID</th>
  <th>Password</th>
  <th>操作</th>
 </tr>
 </thead>
 <c:forEach items="${users }" var="user">
  <tr>
   <td>
    ${user.username } 
   </td>
   <td>${user.email }</td>
   <td>${user.hobby }</td>
   <td>${user.id }</td>
   <td>${user.password }</td>
   <td><a href="user/delUser/${user.id }.html">删除</a>|<a href="user/editUserUI/${user.id }.html">编辑</a></td>
  </tr>
 </c:forEach>
 </table>
 <br>
 <a href="">返回主页</a>&nbsp;&nbsp;<a href="user/addUserUI.html">添加用户</a> 
</div>
</body>
</html>

以上就完成了一个M、V、C的过程,通过开源中国的Git地址下载我的代码,部署上项目,如果部署电脑IP为127.0.0.1,端口为8080,Sports-SpringMvc,那么通过URL http://127.0.0.1:8080/Sports-SpringMvc/user/addUserUI.html 能访问我们的人员注册页面,效果图如下:

保存成功后,跳转到人员列表中,如下图:

 33、为了对当前项目有一个很清晰的说明,我简单做了一个主页(index.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>
<%@ include file="/common/common.jsp" %>
<%@ include file="/common/taglib.jsp" %>    
<base href="<%=basePath %>">
<script type="text/javascript">
$(document).ready(function(){
 $("#logout").click(function(){
  logout();
 });
 function logout(){
     $.ajax({
              type:"POST",
              url:"login/logout.html",
              data:{},
              datatype: "text",//"xml", "html", "script", "json", "jsonp", "text".
              beforeSend:function(){},
              //成功返回之后调用的函数             
              success:function(data){
               window.location.reload();          
              },
              //调用执行(success方法)后调用的函数
              complete: function(XMLHttpRequest, textStatus){
              },
              //调用出错执行的函数
              error: function(){
                  //请求出错处理
              }         
           });
    }
});
</script>
</head>
<body>
 <div class="container"> 
 <h1>SpringMvc的学习</h1>
 <h4>我们通过以下几个场景来一起学习<c:if test="${not empty  userName}">,当前学习者:${userName } </c:if></h4>
 1、<a href="user/showUsers.html">人员管理</a><br>
 2、<a href="login/loginUI.html">人员登录</a><br>
 3、<a href="file/fileUI.html">上传文件</a><br>
 4、<a href="login/otherHandUI.html">其他资源</a><br>
 5、<a href="javascript:void()" id="logout">注销</a>
 </div>
</body>
</html>

 通过URL:http://127.0.0.1:8080/Sports-SpringMvc/ 访问,其效果如下

34、对功能模块”其他资源“的说明,该模块中,只有当用户登录过后,才能显示”其他资源“下的内容,这个模块中对过滤器进行了使用,访问http://127.0.0.1:8080/Sports-SpringMvc/,点击其他资源,就能完成以下描述的操作

相关的代码片段:

spring-mvc.xml中的过滤器的代码片段,其作用是对URL :http://127.0.0.1:8080/Sports-SpringMvc//login/otherHandUI.html的拦截,如果登录过,在跳转到资源页面,如果未登录则进行登录

<mvc:interceptors>
     <bean class="cn.com.sports.interceptor.AllInterceptor"></bean>
     <mvc:interceptor>
      <mvc:mapping path="/login/otherHandUI.html"/>
      <bean class="cn.com.sports.interceptor.LoginInterceptor"></bean>
     </mvc:interceptor>
    </mvc:interceptors>

cn.com.sports.interceptor.LoginInterceptor 类的代码,判断Session中是否保存了用户的一个唯一标识USERID

package cn.com.sports.interceptor;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import cn.com.sports.controller.LoginController;
/**
 * 只拦截 /login/otherUI.html
 * @author Liw
 *
 */
public class LoginInterceptor implements HandlerInterceptor{
 @Override
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3)
   throws Exception {
 }
 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView arg3)
   throws Exception {
 }
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
  Object o = request.getSession().getAttribute(LoginController.USERID);
  if(o == null){
   RequestDispatcher rd = request.getRequestDispatcher("/login/loginUI.html");
   rd.forward(request, response);
   return false ;
  }else{
   return true;
  }
 }
}

LoginController中的代码片段:其作用是返回一个Jsp页面

/**
  * 登录处理
  * @param user
  * @param modelMap
  * @return 根据验证结果返回不同的视图
  */
 @RequestMapping("/otherHandUI")
 public String otherHandUI(){
  return "/login/other";
 }

other.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=ISO-8859-1">
<%@ include file="/common/taglib.jsp" %>
<%@ include file="/common/common.jsp" %>    
<base href="<%=basePath%>">
<title>其他操作</title>
</head>
<body>
<div class="container">
<h2 class="bg-info">其他操作</h2> 
哈哈,你终于注册、登录啦!<br><br>
<a href="">返回主页</a>
</div>
</body>
</html>

35、上传文件

在浏览器中通过 http://127.0.0.1:8080/Sports-SpringMvc/ ,点击上传文件,就能完成以下描述的操作

FileController的代码如下,其作用是对文件的上传以及文件路径的保存

package cn.com.sports.controller;
import java.io.File;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import cn.com.sports.utils.DB;
import cn.com.sports.utils.KeyGeneratorImpl;
@Controller
@RequestMapping("/file")
public class FileController {
 @Autowired
 public KeyGeneratorImpl keyGeneratorImpl ;
 @Autowired
 public DB db ;
 /**
  * 返回文件上传视图
  * @return
  */
 @RequestMapping("/fileUI")
 public String uploadUI(ModelMap modelMap){
  modelMap.put("files", db.getAllFile());
  return "/file/file";
 }
 /**
  * 处理文件上传
  * @param file
  * @param request
  * @param model
  * @return
  */
 @RequestMapping("upload")
 public String upload(@RequestParam(value = "file", required = false) MultipartFile file, HttpServletRequest request, ModelMap model){
  String path = request.getSession().getServletContext().getRealPath("upload");  
        String fileName = file.getOriginalFilename();  
        File targetFile = new File(path, fileName);  
        if(!targetFile.exists()){  
            targetFile.mkdirs();  
        }  
        try {  
            file.transferTo(targetFile);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        cn.com.sports.model.File mode = new cn.com.sports.model.File();
        try {
   mode.setId(keyGeneratorImpl.getKey());
   mode.setName(fileName);
   mode.setUrl(request.getContextPath()+"/upload/"+fileName);
   db.saveFile(mode);
  } catch (Exception e) {
   e.printStackTrace();
  }
        model.addAttribute("fileUrl", request.getContextPath()+"/upload/"+fileName);  
  return "redirect:/file/fileUI.html";
 }
}

spring-mvc.xml的代码片段:

<bean id="multipartResolver"  
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
        <property name="defaultEncoding">  
            <value>UTF-8</value>  
        </property>  
        <property name="maxUploadSize">  
            <!-- 上传文件大小限制为31M,31*1024*1024 -->  
            <value>32505856</value>  
        </property>  
        <property name="maxInMemorySize">  
            <value>4096</value>  
        </property>  
    </bean>

上传页面的代码以及页面展现效果:

<%@ 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=ISO-8859-1">
<%@ include file="/common/taglib.jsp" %>
<%@ include file="/common/common.jsp" %>    
<base href="<%=basePath%>">
<title>上传文件</title>
<script type="text/javascript">
 function check(){
  if($("#exampleInputFile").val() == ""){
   alert('请选择您要上传的文件,图片哟!');
   return false ;
  }else{
   return true ;
  }
 }
</script>
</head>
<body>
<div class="container">
<h2 class="bg-info">上传文件</h2> 
<table class="table table-bordered table-hover">
<thead>
<tr>
 <th>ID</th>
 <th>name</th>
 <th>文件</th>
</tr>
</thead>
<c:forEach items="${files }" var="file">
 <tr>
  <td>
   ${file.id} 
  </td>
  <td>${file.name}</td>
  <td><a href="${file.url }"><img alt="" src="${file.url }" class="img-circle" height="100px;"></a></td>
 </tr>
</c:forEach>
</table>
<form action="file/upload.html" enctype="multipart/form-data" method="post" onsubmit="return check()">
  <div class="form-group">
    <label for="exampleInputFile">File input</label>
    <input type="file" id="exampleInputFile" name="file" />
    <p class="help-block">Example block-level help text here.</p>
  </div>
  <button type="submit" class="btn btn-default">Submit</button>
  <br><br><a href="">返回主页</a>
</form> 
</div>
</body>
</html>

其效果如下:

36、表单服务器端的验证,拿用户注册进行说明:

这个项目中通过HibernateValidator对表单进行服务器端进行验证,代码片段如下:

spring-mvc.xml

<!-- 以下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册-->  
 <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">  
     <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>  
 </bean>

UserController中的相关代码片段:

/**
  * 对添加人员进行处理
  * @param user
  * @param modelMap
  * @return 服务器端定向到展示所有用户页面
  */
 @RequestMapping("/addUser")
 public String addUser(User user,ModelMap modelMap){
  String url = "redirect:/user/showUsers.html" ;
  //服务器端验证
  String error = validate(user);
  if(!"".equals(error.toString())){
   modelMap.addAttribute("errors", "用户保存失败!<br>"+error.toString());
   return "/user/addUser";
  }
  KeyGeneratorImpl k = new KeyGeneratorImpl();
  try {
   user.setId(k.getKey());
   user.setPassword(Utils.encrypt(user.getPassword()));
  } catch (Exception e) {
   e.printStackTrace();
  }
  if(db.getUserByUserOrEmail(user.getUsername()) == null)
   db.saveOrUpdateUser(user);
  else{
   modelMap.addAttribute("user", user);
   modelMap.addAttribute("flag", "1");
   url = "/user/addUser";
  }
    
  return url;
 } 
 
 public String validate(User user){
  Set<ConstraintViolation<User>> violations = validator.validate(user);
  StringBuffer buf = new StringBuffer(); 
   for(ConstraintViolation<User> violation: violations) { 
    String f = violation.getPropertyPath().toString() ;
    buf.append(f +":"+ violation.getMessage() +"<br>" ); 
  }
  return buf.toString();
 }

添加页面的效果:

 

希望以上博文对初学者有帮助,具体详细代码可以到https://git.oschina.net/liw/Sports-SpringMvc.git中下载,编写博文难免有不详细或者理解有误,如有希望指出,并能相互学习。

© 著作权归作者所有

共有 人打赏支持
丈量大地

丈量大地

粉丝 16
博文 52
码字总数 27634
作品 0
都江堰
程序员
私信 提问
加载中

评论(4)

丈量大地
丈量大地

引用来自“brave666”的评论

下载下来的maven项目,其中的两个listener类找不到
不好意思,最近忙,这才回复你。这例子程序用到了两个listener,都是关于Spring在Tomcat启动时做的一些初始化事情,你说的找不到listener类可能有两种情况,一是启动Tomcat前就出现找不到ContextLoaderListener、IntrospectorCleanupListener这两类,可能的原因是Maven默认仓库在国外,没下载完成相应的Jar包,你可以将maven仓库该为国内的,如oschina的 ;二是启动Tomcat报错找不到ContextLoaderListener、IntrospectorCleanupListener这两类,你可以使用我的方式这个命令启动Tomcat “tomcat:run”
brave666
brave666
下载下来的maven项目,其中的两个listener类找不到
丈量大地
丈量大地

引用来自“浪子21”的评论

学习啦 讲的很仔细!
谢谢称赞,记录下学习的点滴,相互学习
浪子21
学习啦 讲的很仔细!
第二章——Spring Boot启动器与依赖管理

强烈推荐选择支持依赖管理和可以发布到“Maven中央”仓库的构建系统。推荐使用Maven或Gradle。Spring Boot可以使用其他构建系统(例如,Ant),但支持得并不是很好。 1 依赖管理 Spring Boo...

Leech
2018/02/04
0
0
Spring Boot学习资源

Spring Boot 入门 http://blog.csdn.net/isea533/article/details/50278205 ---------------------------------------------------------- Spring Boot 静态资源处理 http://blog.csdn.net/c......

IamOkay
2017/02/17
0
0
spring+ibatis整合之jar包引入配置篇

1.spring-2.5.6.SEC03,再加上spring-webmvc- 3.2.3,马上动手springmvc的工作, 2.使用了spring的注解方式,发生了在spring-2.5.6.SEC03的spring-core包缺少对springmvc的@Controller等一些的...

无起
2012/12/28
0
1
热门技术从零开始学Spring Cloud视频教程发布

使用技术 (1)spring boot,使用版本:1.5.8 (2)spring cloud ,使用版本:Dalston.SR4 (3)Netflix Eureka (4)Netflix Ribbon (5)Feign (6)Netflix Hystrix (7)Spring Clou Con...

小红牛
2018/08/04
0
0
Spring Cloud Finchley.SR1 发布,修复模块的 bug

Spring Cloud Finchley 的 Service Release 1 (SR1) 版本已发布,本次更新主要是对其包含的一些模块进行了升级,查看发布说明以了解更多信息。Spring Cloud Finchley 基于 Spring Boot 2.0....

局长
2018/08/03
2.2K
5

没有更多内容

加载失败,请刷新页面

加载更多

powerdesigner连接Mysql数据库

此次使用Mysql8.0和powerdesigner16.5 1、新建一个pdm 这里有个疑问,本人的mysql的版本是8.0,但如下图DBMS里最高只有mysql5.0,但以后没什么影响,所以未深究。 2、点击菜单栏里database,...

jxlgzwh
28分钟前
2
0
java 中 for 、foreach 和 迭代器 的学习笔记

for ,foreach 的区别如下: 1. 形式区别 对于for循环,我们采用: for(int i=0;i<arr.size();i++){...} 对于foreach: for(int i:arr){...} 对与迭代器: Iterator it = arr.iterator...

hellation_
34分钟前
3
1
使用keepalived搭建高可用集群

概览 涉及理论知识点:VRRP协议 https://blog.csdn.net/zhyvodka/article/details/41800399 准备工作 三台机器恢复快照,抹掉LVS的实验痕迹 规划: wangzb01 web1wangzb02 Nginx负载均衡1w...

wzb88
43分钟前
1
0
深入 理解char * ,char ** ,char a[ ] ,char *a[] 的区别

C语言中由于指针的灵活性,导致指针能代替数组使用,或者混合使用,这些导致了许多指针和数组的迷惑,因此,刻意再次深入探究了指针和数组这玩意儿,其他类型的数组比较简单,容易混淆的是字...

天王盖地虎626
今天
4
0
关于我这三年的架构历程(待完成)

从16年7月实习至今,快三年的开发经历中,经手了好几个项目。目前有幸作为一个项目的负责人,完成了一个项目的完全架构设计。因此想记录下这份架构设计中的点点面面。 总架构: 基于DNS的负载...

赵熠熠
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部