基于SpringBoot从零构建博客网站 - 设计可扩展上传模块和开发修改头像密码功能...

news/2024/5/20 2:47:58/文章来源:https://blog.csdn.net/weixin_30641999/article/details/96434855

上传模块在web开发中是很常见的功能也是很重要的功能,在web应用中需要上传的可以是图片、pdf、压缩包等其它类型的文件,同时对于图片可能需要回显,对于其它文件要能够支持下载等。在守望博客系统中对于上传模块进行统一管理,同时对于上传不同的类型文件,留有自定义实现机制的接口,也即可扩展。

基于上传模块机制,就可以实现修改头像功能了。同时顺带将修改密码的功能也一起实现,这个修改密码的功能相对就很简单了。

1、可扩展上传模块

统一上传模块的体现就是上传所有类型的文件,都是调用统一的一个接口,即上传接口唯一;同时对于具体上传的类型文件,如有特殊处理的可以自定义实现处理方法。

对于上传的文件能够有自定义的实现机制,则需要一个上传文件的处理接口,即:IUploadHandler,内容如下:

/*** 上传文件处理接口类** @author lzj* @since 1.0* @date [2019-07-09]*/
public interface IUploadHandler {/*** 上传文件处理方法* 文件上传成功,返回文件的相关信息* 文件上传失败, 返回null** @param file* @param distType* @param userId* @return* @throws Exception*/public Object upload(MultipartFile file, String distType, String userId) throws Exception;/*** 下载文件** @param fileId* @param response* @throws Exception*/public void download(String fileId, HttpServletResponse response) throws Exception;/*** 根据条件列出文件信息** @param distType* @param userId* @return* @throws Exception*/public Object list(String distType, String userId) throws Exception;
}

目前本版本中暂定有3个方法,即:

  • upload方法,用于处理自定义上传文件方式;
  • download方法,用于处理自定义下载的方式;
  • list方法,用于处理自定义列出文件列表的方式。

这里以上传头像图片为例,则上传头像的实现类UploadAvatarHandler,内容如下:

/*** 上传头像处理类** @author lzj* @since 1.0* @date [2019-07-09]*/
@Slf4j
@Component("_avatar")
public class UploadAvatarHandler implements IUploadHandler {@Autowiredprivate IUserService userService;@Resource(name = "configCache")private ICache<Config> configCache;@Overridepublic Object upload(MultipartFile file, String distType, String userId) throws Exception {Map<String, Object> result = new HashMap<String, Object>();try {// 获取图片的大小long fileSize = file.getSize();// 图片大小不能超过2M, 2M = 2 * 1024 * 1024B = 2097152Bif (fileSize > 2097152L) {throw new TipException("您上传的图片超过2M");}Config config = configCache.get(Config.CONFIG_IMG_AVATAR_PATH);// 保存头像的根目录String basePath = config.getConfigValue();if (!basePath.endsWith("/")) {basePath += "/";}// 根据当前时间构建yyyyMM的文件夹,建立到月的文件夹String dateDirName = DateUtil.date2Str(new Date(), DateUtil.YEAR_MONTH_FORMAT);basePath += dateDirName;File imageDir = new File(basePath);if (!imageDir.exists()) {imageDir.mkdirs();}String fileNewName = IdGenarator.guid() + ".jpg";FileUtil.copy(file.getInputStream(), new FileOutputStream(new File(imageDir, fileNewName)));// 获取用户信息User user = userService.getById(userId);user.setPicture(dateDirName + "/" + fileNewName);// 更新信息userService.updateById(user);result.put("success", true);result.put("msg", "上传头像成功");} catch (TipException e) {result.put("success", false);result.put("msg", e.getMessage());} catch (Exception e) {log.error("上传头像失败", e);result.put("success", false);result.put("msg", "上传头像失败");}return result;}@Overridepublic void download(String fileId, HttpServletResponse response) throws Exception {}@Overridepublic Object list(String distType, String userId) throws Exception {return null;}

这里有2个注意点,即这个@Component("_avatar"),这个类的名称最好自定义命名,最好以处理这种文件的类型为名,例如此处的是处理头像的,所以就是avatar,但是为了防止重名,所以前缀加上了下划线。

另外一个需要注意的就是,并不是所有的方法都需要实现,例如此处就没有实现download和list方法,因为头像图片不是通过流的方式回显的,而是直接通过映射到具体的图片,同时也是不需要列出头像的功能。

前面说过所有上传文件,都是调用统一的一个接口,也即是UploadController,内容如下:

/*** 处理文件上传下载控制器类** @author lzj* @date [2019-07-09]* @since 1.0*/
@Slf4j
@Controller
public class UploadController {@Autowiredprivate ApplicationContext context;// 用于存储处理上传文件对象private Map<String, IUploadHandler> uploadHandlers;/*** 初始化操作** @throws Exception*/@PostConstructpublic void init() throws Exception {uploadHandlers = context.getBeansOfType(IUploadHandler.class);}/*** 上传文件** @param file* @param request* @param session* @return*/@RequestMapping(value = "/upload", method = RequestMethod.POST)@ResponseBodypublic Object upload(@RequestParam(value = "_uploadFile", required = false) MultipartFile file, HttpServletRequest request, HttpSession session) {Object result = null;try {// 接收参数// 获取上传文件类型,参数名为_fileTypeString _distType = request.getParameter("_distType");// 获取用户信息User user = (User) session.getAttribute(Const.SESSION_USER);result = uploadHandlers.get(_distType).upload(file, _distType, user.getUserId());} catch (Exception e) {log.error("上传文件失败", e);}return result;}
}

这里需要注意init方法,该方法会将IUploadHandler接口的实现类都扫描出来,同时以类名为key,实例为value返回。

同时调用上传方法时是需要带_distType参数的,该参数值要与具体IUploadHandler的实现类的类名一样,例如:上传头像就需要将 _distType = _avatar参数带过来。这样UploadController就知道具体用哪个实现类来处理。

2、修改头像

有了前面的上传模块,对于修改头像就简单多了,首先需要实现上传头像的实现类,即UploadAvatarHandler类,代码在上方已经罗列了此处省略。

加载出修改头像页面的核心的如下:

/*** 加载出修改头像页面** @return*/
@RequestMapping(value = "/user/avatar", method = RequestMethod.GET)
public String avatar(HttpSession session, Model model) {// session中的信息User sessionUser = (User) session.getAttribute(Const.SESSION_USER);// 从数据库中获取用户信息User user = userService.getById(sessionUser.getUserId());model.addAttribute("user", user);return Const.BASE_INDEX_PAGE + "auth/user/avatar";
}

修改头像,运用了fullAvatarEditor插件,所以核心的前台代码如下:

<script type="text/javascript">swfobject.addDomLoadEvent(function () {var swf = new fullAvatarEditor("${rc.contextPath}/static/plugins/fullAvatarEditor/fullAvatarEditor.swf", "${rc.contextPath}/resources/plugins/fullAvatarEditor/expressInstall.swf", "swfContainer", {id: 'swf',upload_url: '${rc.contextPath}/upload?_distType=_avatar',   //上传接口method: 'post', //传递到上传接口中的查询参数的提交方式。更改该值时,请注意更改上传接口中的查询参数的接收方式src_upload: 0,      //是否上传原图片的选项,有以下值:0-不上传;1-上传;2-显示复选框由用户选择avatar_box_border_width: 0,avatar_sizes: '150*150',avatar_sizes_desc: '150*150像素',avatar_field_names: '_uploadFile'}, function (msg) {console.log(msg);switch (msg.code) {case 1 :break;case 2 :document.getElementById("upload").style.display = "inline";break;case 3 :if (msg.type == 0) {}else if (msg.type == 1) {alert("摄像头已准备就绪但用户未允许使用!");}else {alert("摄像头被占用!");}break;case 5 :setTimeout(function () {window.location.href = window.location.href;}, 1000);break;}});document.getElementById("upload").onclick = function () {swf.call("upload");};});
</script>

注意:

里面一个upload_url参数就是写上传接口的,上述中为:

upload_url: '${rc.contextPath}/upload?_distType=_avatar'

正如在前面讨论的一样的,需要带上 _distType参数

页面效果如下:
840503-20190715131610222-1459741502.jpg

注意在回显图片时,需要加上如下配置:

/*** 静态资源配置** @param registry*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {// 映射头像图片String avatarPath = configCache.get(Config.CONFIG_IMG_AVATAR_PATH).getConfigValue();if (!avatarPath.endsWith("/")) {avatarPath += "/";}registry.addResourceHandler("/img/avatar/**").addResourceLocations("file:" + avatarPath);
}

3、修改密码

修改密码功能相对简单,页面效果如下:
840503-20190715131558676-1139801794.png

此处就只列出修改密码的核心逻辑,即:

/*** 修改密码** @param request* @param session* @param model* @return*/
@RequestMapping(value = "/user/password", method = RequestMethod.POST)
@ResponseBody
public Result password(HttpServletRequest request, HttpSession session) {Result result = new Result();try {// 获取登录信息User tempUser = (User) session.getAttribute(Const.SESSION_USER);String userId = tempUser.getUserId();// 接收参数String password = request.getParameter("password");String newPwd = request.getParameter("newPwd");String confirmNewPwd = request.getParameter("confirmNewPwd");if (StringUtils.isEmpty(password) || StringUtils.isEmpty(newPwd) || StringUtils.isEmpty(confirmNewPwd)) {throw new TipException("缺少必要请求参数");}if (!newPwd.equals(confirmNewPwd)) {throw new TipException("两次输入的新密码不相等");}// 获取用户信息User user = userService.getById(userId);if (!user.getPassword().equals(StringUtil.md5(password))) {throw new TipException("旧密码输入不正确");}// 修改密码user.setPassword(StringUtil.md5(newPwd));boolean flag = userService.updateById(user);if (!flag) {throw new TipException("修改密码失败");}result.setCode(Result.CODE_SUCCESS);result.setMsg("修改成功");} catch (TipException e) {result.setCode(Result.CODE_EXCEPTION);result.setMsg(e.getMessage());} catch (Exception e) {log.error("修改密码失败", e);result.setCode(Result.CODE_EXCEPTION);result.setMsg("修改密码失败");}return result;
}

关注我

以你最方便的方式关注我:
微信公众号:
840503-20190715131540753-568529549.jpg

转载于:https://www.cnblogs.com/atcloud/p/11188320.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_777639.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

django+uwsgi+nginx部署网站

djangouwsginginx部署网站 静态&#xff1a;nginx直接处理 动态&#xff1a;wsgi或者uwsgi给python处理 uwsgi web协议&#xff0c;发布python网站。 uwsgi是服务器和服务端应⽤程序的通信协议&#xff0c;规定了怎么把请求转发给应⽤程序和返回 uWSGI实现WSGI协议&#xff0…

Certbot给网站域名申请免费SSL证书 及Nginx配置

Certbot 官网&#xff1a; https://certbot.eff.org/ 前提是自己已经安装好nginx&#xff0c;并配置好自己的域名。 1.安装snap 官网要求用snap工具安装&#xff0c;那就先安装相关依赖包&#xff0c;和snap软件。 yum -y install epel-release #安装依赖 yum -y…

Linux开源软件Gatus - 自动化监控网站运行服务

一&#xff1a;Gatus简介&#xff1a; Gatus 提供一个轻量级的监控健康&#xff0c;让开发者通过服务的简单 HTTP、ICMP 等协议来监控情况&#xff0c;并根据网页监控 TCP 的状态码或响应时间及正文来决定网站是否健康&#xff0c;如果发生的话异常&#xff0c;可以设置不同的…

用acme.sh给网站域名,申请免费SSL永久证书(自动续期)

一&#xff1a;简介 申请ssl证书&#xff0c;即https有很多&#xff0c;有免费的&#xff0c;也有收费的。如第三方域名管理cloudflare也可以自动添加使用https&#xff0c;而且永久。 但是由于有些服务&#xff0c;需要在服务器使用自签证书&#xff0c;所以需要自己申请。免…

java旅游网站毕业论文_旅游网站的设计与实现

摘 要 现代社会是信息社会。随着计算机网络技术、数据库技术、管理技术的发展&#xff0c;对信息的处理和利用已经深入到人类生活的各个方面。旅游是人们生活不可分割的组成部分&#xff0c;旅游业已成为当今世界上发展势头最强劲的产业&#xff0c;它是集吃、住、行、游、购、…

centos php 绑定域名解析,Linux系统下网站站点部署优势之:域名泛解析绑定

做过站群或绑定多个二级域名的技术人员都知道&#xff0c;在windows下如果可绑定多个二级域名&#xff0c;一般都会用到默认站点的空主机头&#xff0c;只有绑定了80端口的空主机头&#xff0c;才可实现多个二级域名的绑定&#xff0c;或指定目录或301转发。但是&#xff0c;服…

如何查看网站服务器更新信息,如何实现本地修改网站,服务器上的网站跟着自动更新?...

用DreamweaverCS4的自动上传功能呀&#xff01;详细步骤(以DreamweaverCS4为例)1、点击DreamweaverCS4(以下简称DW)工具栏上的站点按钮&#xff0c;选择“新建站点”2、选中“高级”选项卡后&#xff0c;输入站点名称、本地路径等信息&#xff0c;在HTTP一栏中&#xff0c;输入…

Winform 程序以POST形式访问网站

Winform 程序以POST形式访问网站 本例介绍了Winform程序发送POST请求访问页面&#xff0c;主要使用到了HttpWebRequest和HttpWebResponse这两个对象。 程序主要代码如下&#xff1a; 代码 1 using System.Net; 2 using System.IO; 3 4 5 //创建HttpWebRequest对象 6 …

网站设计欣赏:45+靓丽的蓝绿色主题网站作品【下篇】

网站给用户留下第一印象的既不是网站丰富的内容&#xff0c;也不是网站合理的布局&#xff0c;而是网站的色彩。色彩给人的视觉效果最明显&#xff0c;一个网站设计成功与否&#xff0c;在某种程度上就取决于设计者对色彩的运用和搭配。这篇文章搜集了45靓丽的蓝色和绿色主题网…

重定向网站的几种简单方法

最近需要关闭一个网站&#xff0c;当用户输入这个网站的所有网址的时候&#xff0c;重定向指定的页面。当跳转到指定页面的时候&#xff0c;30s之后再次跳转到另外一个网站的首页。 1.方法一&#xff1a; 在IIS 6上面找到将要关闭的网站&#xff0c;右键属性&#xff0c;打开Ho…

win2003 sp2+iis 6.0上部署.net 2.0和.net 4.0网站的方法

网站环境 IIS6.0,操作系统Windows server2003 sp2,服务器之前已经部署了.net 2.0和asp的网站,现在要部署新开发的.net 4.0网站.本来认为很简单&#xff0c;却遇到了很多问题&#xff0c;下面详细描述下过程&#xff1a; 1.官网下载.net framework4.0,下载地址:http://www.micro…

SP2010开发和VS2010专家食谱--第二章节--工作流(1)--创建带有初始表单的网站工作流...

上一篇文章是没有人参与的顺序工作流的好例子。我们这次创建自己的贷款应用程序审批系统。本文章中&#xff0c;我们将创建网站工作流&#xff0c;完成我们的贷款应用程序审批过程。因为网站工作流并不与任何列表关联&#xff0c;这里没有输入数据和启动工作流的开箱即用表单。…

网站服务器到期后 内容释放,服务器到期后多久释放

服务器到期后多久释放 内容精选换一换自助解封配额根据您选择的业务规模和购买时长计费。当前仅以下区域的公网IP可以使用自助解封功能&#xff1a;华北华东华南自助解封配额提供包周期(3个月、6个月或1年)预付费计费模式&#xff0c;使用越久越便宜。包周期计费按照订单的购买…

Nutch 2.2+MySQL+Solr4.2实现网站内容的抓取和索引

原文地址&#xff1a; http://blog.sina.com.cn/s/blog_3c9872d00101p4f0.html Nutch 2.2.1发布快两月了&#xff0c;该版本与Nutch之前版本相比&#xff0c;有较大变化&#xff0c;特别是与MySQL联合应用的安装和配置过程有不少地方容易出错。本人在安装过程中也遇到了不少麻烦…

长尾词推广系统推荐乐云seo_SEO笔记分享---网站关键词优化(三)

今天主要和大家分享关于SEO关键词优化的三个问题&#xff1a;1 选择关键词需要注意什么2 写网页内容需要注意些什么&#xff1f;3 新站如何快速获得关键词排名大家喜欢的话可以关注我&#xff0c;每天分享关于SEO的知识&#xff0c;我们一起学习及进步选择关键词需要注意什么经…

php中seo优化怎么做,php怎么seo优化

现在SEO基本上已经是在广泛的应用了&#xff0c;php程序的企业网站也越来越多&#xff0c;其实我之前一直喜欢用asp的&#xff0c;但是发现很多国外的空间现在不支持asp&#xff0c;所以也就研究了一下php&#xff0c;网站建好&#xff0c;当然也想要有一个好的网站排名&#x…

windows 网站迁移linux,Windows迁移Linux问题集锦

1)‘_wcsicmp’在此作用域中尚未声明#ifdef WIN32#define _tcsicmp _wcsicmp#else#define _tcsicmp wcscasecmp#endif2)_stricmp 在此作用域中尚未声明#include 将_stricmp改成strcasecmp3)atoi的wchar版本不存在&#xff0c;#define _ttoi _wtoi改成使用#d…

python爬虫爬取汽车网站外型图片

我选择的起始网址&#xff1a;http://www.hao123.com/auto/brand 当你随便选择一个车牌的选框&#xff08; 不要 同时选择多个选框&#xff09;你就会发现每个车牌对应一个网址 每个网址的区别就是数字不同 比如选中奥迪时对应的网址&#xff1a;https://car.58che.com/brand/…

发现了个非常不错的OJ题目分类网站

网上瞎逛发现了一个东华大学的非常不错的OJ题目分类网站&#xff0c;把好些有名的OJ系统上的题目分别按知识点和难易程度进行了分类&#xff0c;非常适合那些希望有针对性做题的同学。同时针对每一个题目还配有相应的博客。http://acm.dhu.edu.cn/search3/index.jsp 转载于:htt…

配置ISA Server以创建站点到站点××× 连接之三 启用连接(接续之二)

在本练习中&#xff0c;您将在两个 ISAServer 阵列之间测试和使用站点到站点 连接。注意&#xff1a;本实验室练习使用以下计算机&#xff1a;Denver - Florence - Berlin - Istanbul 本次实验的目的&#xff0c;是启使用前两个步骤所建立的站点到站点连接的配置在 Florence 计…