一、需要实现的功能:
(1)实现用户的登录功能;并将用户信息存放到session中。
(2)实现用户的注册功能;并为注册用户在服务器创建一个指定目录存放数据。
(3)实现用户登录后查询当前用户的所有文件信息。
(4)实现文件的上传和下载及删除。
(5)自定义拦截器和自定义异常的应用。
二、实现步骤:
1.导人jar文件建立整个项目的架构:
(1)创建数据库:
-
t_user用户表:
t_user -
t_file文件信息表:
t_file
外键
(2)导包:
jar包
(3)项目的整个框架:
需要创建的包a.创建需要的包:从实体类到控制器;
applicationContext-*.xmlb.需要的配置文件和映射文件:
web.xml
(4)创建实体类:
- User用户类(生成getter和setter方法及构造方法):
private int userid;//用户ID
private String username;//用户名
private String userpass;//密码
private int usertype;//用户类型,1:普通用户,2:VIP用户
- Files文件信息类(生成getter和setter方法及构造方法):
private int fileid;//文件ID
private String filename;//文件名
private Date uploaddate;//上传日期
private long filesize;//文件大小
private String filecode;//文件的提取码
private String filepath;//文件存放的路径
private int userid;//用户ID
2.XML文件的配置:
(1)web.xml:
DispatcherServlet:前端控制器的配置;
字符编码的配置;
扫描applicationContext-*.xml配置;
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 字符编码 -->
<filter>
<filter-name>encod</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>encod</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--指定配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-*.xml</param-value>
</context-param>
<!--声明Web容器监听器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
(2)applicationContext-mybatis.xml:
用于数据库连接和创建mapper代理对象;
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/udisk"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="com.zlw.pojo"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="factory"></property>
<property name="basePackage" value="com.zlw.mapper"></property>
</bean>
</beans>
(3)applicationContext-service.xml:
<!--扫描service对象-->
<context:component-scan base-package="com.zlw.service"></context:component-scan>
(4)springmvc.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:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 扫描@Controller -->
<context:component-scan base-package="com.zlw.controller"></context:component-scan>
<!-- @RequestMapping -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 对静态资源放行 -->
<mvc:default-servlet-handler />
<!-- 视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
3.注册和登录功能的实现:
(1)创建mapper接口和映射文件:
实现数据访问层,根据用户名和密码查询用户信息,添加用户信息。
- userMapper接口:
public interface UserMapper {
/**
* 查询指定的用户
* @param user
* @return
*/
User findOne(User user);
/**
* 添加用户
* @param user
* @return
*/
int userAdd(User user);
}
- userMapper映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zlw.mapper.UserMapper">
<select id="findOne" resultType="user" parameterType="user">
select *from t_user where username = #{username} and userpass=#{userpass}
</select>
<insert id="userAdd" parameterType="user">
insert into t_user values (default,#{username},#{userpass},#{usertype})
</insert>
</mapper>
(2)service业务层:
- userService接口:
package com.zlw.service;
import com.zlw.pojo.ResultMessage;
import com.zlw.pojo.User;
public interface UserService {
/**
* 登录操作
* @param user
* @return
*/
User findOne(User user);
/**
* 注册操作
* @param user
* @return
*/
int userAdd(User user);
}
- userServiceImpl实现类:
package com.zlw.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zlw.mapper.UserMapper;
import com.zlw.pojo.ResultMessage;
import com.zlw.pojo.User;
import com.zlw.service.UserService;
import com.zlw.util.MD5Utils;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
/**
* 登录操作的查询
*/
@Override
public User findOne(User user) {
//对用户输入的密码进行MD5加密
String md5 = MD5Utils.createMD5(user.getUserpass());
user.setUserpass(md5);
return userMapper.findOne(user);
}
/**
* 添加操作
*/
@Override
public int userAdd(User user) {
//对用户输入的密码进行MD5加密
String md5 = MD5Utils.createMD5(user.getUserpass());
user.setUserpass(md5);
return userMapper.userAdd(user);
}
}
- 使用MD5加密工具类对密码进行加密(可以直接使用):
package com.zlw.util;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 对字符串进行MD5加密
*
* @author Think
*
*/
public class MD5Utils {
/**
* 对字符串进行加密
*
* @param str
* @return
*/
public static String createMD5(String str) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
// 将字符串转换为字节数组
byte[] oldBytes = str.getBytes("iso-8859-1");
// 对字节数组进行加密
byte[] md5Bytes = messageDigest.digest(oldBytes);
// 对md5字节数组进行二次加密
StringBuffer sb = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
byte b = md5Bytes[i];
int val = ((int) b) & 0xff;// 与一个16进制的数值进行与运算 0xff(盐)
if (val < 10) {
sb.append(0);
}
sb.append(Integer.toHexString(val));// 转换为16进制
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String hello = "123";
System.out.println(MD5Utils.createMD5(hello));
}
}
(3)控制器Controller:
@Controller
@RequestMapping("/udisk")
public class UserController {
@Autowired
private UserService userService;
/**
* 登录操作
*
* @param user
* @param session
* @param request
* @return
*/
@RequestMapping("login")
public String login(User user, HttpSession session, HttpServletRequest request) {
User us = userService.findOne(user);
if (us != null) {
session.setAttribute("user", us);
return "redirect:/file/list";
} else {
request.setAttribute("errors", "用户名或密码错误!");
}
return "forward:/login.jsp";
}
@RequestMapping("check")
public void check(User user, HttpServletResponse response) throws IOException {
User us = userService.findOne(user);
if (us != null) {
response.getWriter().print(true);
} else {
response.getWriter().print(false);
}
}
/**
* 注册操作
*
* @param user
* @param session
* @param request
* @return
*/
@RequestMapping("register")
public String register(User user, HttpSession session, HttpServletRequest request) {
// 动态创建隶属于该用户的专属文件夹(用于保存该用户上传的文件)
File filePath = new File("D:/upload/" + user.getUsername());
if (!filePath.exists()) {
filePath.mkdirs();// 创建文件夹
}
int n = userService.userAdd(user);
if (n > 0) {
return "redirect:/login.jsp";
} else {
return "forward:/register";
}
}
}
(4)jsp页面:
- login.jsp:
<div id="content">
<h4 class="service-head">请您登录</h4>
<form action="udisk/login" method="post">
<P>用户名:<input name="username" id="inp"/><span style="color: red" >${errors }</span>
<P>密 码 :<input type="password" name="userpass" id="inp2"/><span id="span"></span>
<p><input type="submit" value="登录"/>
</form>
</div>
- register.jsp:
<div id="content">
<h4 class="service-head">请您注册</h4>
<form action="udisk/register" method="post">
<P>
用户名:<input name="username" id="inp"/><span id="span"></span>
<P>
密 码 :<input name="userpass" id="inp2"/>
<P>
类 型 :<input name="usertype" type="radio" value="1" /> 普通会员 <input
name="usertype" type="radio" value="2" /> VIP会员
<p>
<input type="submit" value="注册" id="sub" />
</form>
</div>
(5)增加注册时用户名校验功能:
- mapper中添加方法:
/**
* 根据用户名查询用户
* @param username
* @return
*/
User findByName(String username);
<select id="findByName" resultType="user" parameterType="java.lang.String">
select * from t_user where username = #{0}
</select>
- 添加实体类ResultMessage用来存放消息:
private boolean extis;
private String massage;
- service业务层添加:
@Override
public ResultMessage findByName(String username) {
ResultMessage rm = new ResultMessage();
User us = userMapper.findByName(username);
if (us!=null) {
rm.setExtis(true);
rm.setMassage("用户名不可用!");
}else{
rm.setExtis(false);
rm.setMassage("用户名可用!");
}
return rm;
}
- Controller控制器:
/**
* 校验注册的用户名
*/
@RequestMapping("checkuser")
@ResponseBody
public ResultMessage checkUser(String username) {
return userService.findByName(username);
}
- register.jsp添加函数:
<script type="text/javascript" src="js/jquery-1.9.1.js"></script>
<script type="text/javascript">
$(function(){
$("#inp").blur(function(){
var username = $("#inp").val();
$.post("udisk/checkuser","username="+username,function(data){
if(data.extis){
$("#span").html("<font color=red>"+data.massage+"</font>")
$("#sub").attr("disabled",true);
}else{
$("#span").html("<font color=green>"+data.massage+"</font>")
$("#sub").attr("disabled",false);
}
});
});
});
</script>
(6)实现效果:
注册页面
登录页面
4.用户界面文件信息展示:
(1)查询所有文件信息:
- filesMapper接口和映射文件:
/**
* 查询所有文件信息
* @param userid
* @return
*/
List<Files> findByUserId(int userid);
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zlw.mapper.FilesMapper">
<select id="findByUserId" parameterType="files" resultType="files">
select *from t_file where userid = #{userid}
</select>
</mapper>
- service业务层:
public interface FilesService {
/**
* 查询所有文件操作
* @param userId
* @return
*/
public List<Files> FindByUserId(int userId);
}
@Service("filesService")
public class FilesServiceImpl implements FilesService {
@Autowired
private FilesMapper filesMapper;
@Override
public List<Files> FindByUserId(int userId) {
return filesMapper.findByUserId(userId);
}
}
- Controller控制层:
@Controller
@RequestMapping("/file")
public class FilesController {
@Autowired
private FilesService filesService;
@RequestMapping("list")
public String list(HttpSession session,HttpServletRequest request){
//从session中取出数据
User us = (User) session.getAttribute("user");
List<Files> list = filesService.FindByUserId(us.getUserid());
System.out.println(list);
request.setAttribute("list", list);
return "list";
}
}
- jsp页面:
<div id="content">
<h4 class="service-head">欢迎您:${user.username }</h4>
<p> </p>
<table style="border:solid 1px gray;padding:2px" width="100%">
<thead style="background-color:#EEE">
<tr>
<th width="30%">文件名</th>
<th width="20%">上传日期</th>
<th width="15%">大小</th>
<th width="25%">提取码</th>
<th width="10%">操作</th>
</tr>
</thead>
<tbody>
<c:if test="${empty list}">
<tr>
<td colspan="5" align="center">文件列表为空!</td>
</tr>
</c:if>
<c:if test="${ not empty list }">
<c:forEach items="${list }" var="file">
<tr>
<td>${file.filename }</td>
<td>${file.uploaddate }</td>
<td>${file.filesize }</td>
<td>${file.filecode }</td>
<td><A href="file/download?filecode=${file.filecode }">下载</A>
<A href="file/delete?fileid=${file.fileid }">删除</A></td>
</tr>
</c:forEach>
</c:if>
</tbody>
</table>
<p> </p>
<h4 class="service-head">上传文件</h4>
<form action="file/upload" enctype="multipart/form-data" method="post">
<c:if test="${user.usertype==2 }">
上传文件的数量: <select onchange="makeFile(this.options[this.selectedIndex].text)">
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</c:if>
<div id="divFile">
<input type="file" name="fl" /><br />
</div>
<input type="submit" value="上传" />
</form>
<script>
function makeFile(v) {
var divFile = document.getElementById('divFile');
divFile.innerHTML = '';
for (var i = 0; i < v; i++) {
divFile.innerHTML += '<input type="file" name="fl"><br/>';
}
}
</script>
</div>
-(2)实现效果:
主界面
5.上传和下载:
(1)mapper数据访问层:
/**
* 添加文件信息
*/
int addFile(Files files);
/**
* 根据ID查找指定文件信息
* @param fileid
* @return
*/
Files findById(int fileid);
/**
* 删除指定的文件信息
* @param fileid
* @return
*/
int delete(int fileid);
/**
* 根据文件提取码查询指定文件
*/
Files findByCode(String filecode);
<insert id="addFile" parameterType="files">
insert into t_file values(default,#{filename},now(),#{filesize},#{filecode},#{filepath},#{userid})
</insert>
<select id="findById" resultType="files">
select * from t_file where fileid=#{0}
</select>
<delete id="delete" >
delete from t_file where fileid = #{0}
</delete>
<select id="findByCode" resultType="files">
select *from t_file where filecode=#{0}
</select>
- service业务层:
/**
* 添加文件操作
* @param files
* @return
*/
int addFile(Files files);
/**
* 删除指定文件操作
* @param fileid
* @return
*/
int delete(int fileid);
/**
* 根据文件提取码查询指定文件操作
*/
Files findByCode(String fileCode);
//上传操作
@Override
public int addFile(Files files) {
return filesMapper.addFile(files);
}
@Override
public int delete(int fileid) {
//获取文件的路径
Files fl = filesMapper.findById(fileid);
String filePath = fl.getFilepath();
File file = new File(filePath);
System.out.println(file);
if(file.exists()){//判断文件是否存在
file.delete();//删除文件
}
return filesMapper.delete(fileid);
}
@Override
public Files findByCode(String fileCode) {
return filesMapper.findByCode(fileCode);
}
- Controller控制层:
@RequestMapping("upload")
public String upload(@RequestParam MultipartFile[] fl,HttpSession session) throws Exception{
//从session中获取用户类型
User us = (User) session.getAttribute("user");
int userType = us.getUsertype();
//获取个人空间总大小
long totalSpaceSize = 0;
if(userType==1){
totalSpaceSize = 32*1024*1024;
}else{
totalSpaceSize = 128*1024*1024;
}
//获取用户保存文件的目录
File userPath= new File("D:/upload/"+us.getUsername());
//获取该目录下的所有文件信息
File fil[] = userPath.listFiles();
//获取该目录下所有文件的总大小
long userSpeceSize = 0;
for (File file : fil) {
userSpeceSize += file.length();
}
//计算剩余的空间
long freeSpeceSize = totalSpaceSize-userSpeceSize;
//获取上传文件的总大小
long uploadSize = 0;
for (MultipartFile mult : fl) {
System.out.println(mult.getName());
long fileSize = mult.getSize();
uploadSize +=fileSize;
}
//上传文件
for (MultipartFile mult : fl) {
//获取上传文件的名称
String fileName = mult.getOriginalFilename();
//获取上传文件的大小
long fileSize = mult.getSize();
if(uploadSize>freeSpeceSize){
throw new CustomException("剩余空间不足!");
}else{
if(userType==1&&fileSize>1*1024*1024){
throw new CustomException("文件大小不能超过1M");
}else if(userType==2&&fileSize>2*1024*1024){
throw new CustomException("文件大小不能超过2M");
}
}
//执行上传操作
mult.transferTo(new File(userPath,fileName));
//将信息添加到数据库
String filePath = "D:/upload/"+us.getUsername()+"/"+fileName;
String fileCode = MD5Utils.createMD5(filePath);
Files files = new Files(fileName, fileSize, fileCode, filePath, us.getUserid());
filesService.addFile(files);
}
return "redirect:/file/list";
}
//下载
@RequestMapping("download")
public void downLoad(String filecode,HttpServletResponse response) throws IOException{
response.setCharacterEncoding(filecode);
//获取文件目录
Files file = filesService.findByCode(filecode);
String filePath = file.getFilepath();
InputStream is = new FileInputStream(filePath);
//解决响应时客户端出现的中文乱码问题
String fileName = new String(file.getFilename().getBytes("UTF-8"),"iso-8859-1");
//设置响应头信息
response.setHeader("Content-Disposition","attachment;filename="+fileName);
//读取文件到本地
OutputStream os = response.getOutputStream();
IOUtils.copy(is, os);
//关闭资源
os.close();
is.close();
}
- jsp页面:
<td><A href="file/download?filecode=${file.filecode }">下载</A>
<A href="file/delete?fileid=${file.fileid }">删除</A></td>
-
实现效果:
操作
提取码
三、自定义拦截器和自定义异常
1.自定义拦截器:
通过判断session中是否有信息存在,决定是否可以直接访问其他页面;
(1)创建一个拦截器实现HandlerInterceptor接口:
package com.zlw.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.zlw.pojo.User;
public class VisitInceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
System.out.println("preHandle");
//获取HttpSession
HttpSession session = request.getSession();
if(session.getAttribute("user")!=null){//判断session中是否有信息
return true;
}else{
//获取项目根目录
String path = request.getServletContext().getContextPath();
response.sendRedirect(path+"/login.jsp");
return false;
}
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("postHandle!!!!");
}
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
}
(2)在springmvc中配置自定义拦截器:
<!-- 自定义拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/file/list" />
<!-- 不进行拦截的 -->
<!-- <mvc:exclude-mapping path=""/> -->
<bean class="com.zlw.interceptor.VisitInceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
(3)实现效果:
访问主界面控制器在没有进行登录不能访问主界面;会自动跳转到登录页面。
跳转登录页面
2.自定义异常:
(1)springmvc.xml中配置自定义异常解析器:
<!-- 自定异常解析器 -->
<bean id="handlerExceptionResolver" class="com.zlw.util.CustomExceptionResolver"></bean>
(2)创建自定义异常解析器类实现HandlerExceptionResolver接口:
/**
* 自定义异常处理器的解析器
* @author zhang
*
*/
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object object,
Exception exce) {
CustomException custo = null;
if(exce instanceof CustomException){
custo = (CustomException) exce;
}else{
custo = new CustomException("未知异常!");
}
ModelAndView ma = new ModelAndView();
ma.addObject("message",custo.getMessage());
ma.setViewName("error");
return ma;
}
}
(3)自定义异常:
/**
* 自定异常
* @author zhang
*
*/
public class CustomException extends Exception{
public CustomException(String message) {
super(message);
}
}
(4)在上传文件中使用自定义异常:
if(uploadSize>freeSpeceSize){
throw new CustomException("剩余空间不足!");
}else{
if(userType==1&&fileSize>1*1024*1024){
throw new CustomException("文件大小不能超过1M");
}else if(userType==2&&fileSize>2*1024*1024){
throw new CustomException("文件大小不能超过2M");
}
}
效果
网友评论