登陆页面总结(bootdo)

article/2025/8/27 2:56:12

总结自开源项目bootdo

图标设置

验证码

 验证码生成工具类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;/*** @author bootdo*/
public class RandomValidateCodeUtil {public static final String RANDOMCODEKEY = "RANDOMVALIDATECODEKEY";//放到session中的keyprivate String randString = "0123456789";//随机产生只有数字的字符串 private String//private String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串//private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生数字与字母组合的字符串private int width = 95;// 图片宽private int height = 25;// 图片高private int lineSize = 40;// 干扰线数量private int stringNum = 4;// 随机产生字符数量private static final Logger logger = LoggerFactory.getLogger(RandomValidateCodeUtil.class);private Random random = new Random();/*** 获得字体*/private Font getFont() {return new Font("Fixedsys", Font.CENTER_BASELINE, 18);}/*** 获得颜色*/private Color getRandColor(int fc, int bc) {if (fc > 255) {fc = 255;}if (bc > 255) {bc = 255;}int r = fc + random.nextInt(bc - fc - 16);int g = fc + random.nextInt(bc - fc - 14);int b = fc + random.nextInt(bc - fc - 18);return new Color(r, g, b);}/*** 生成随机图片*/public void getRandcode(HttpServletRequest request, HttpServletResponse response) {HttpSession session = request.getSession();// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作g.fillRect(0, 0, width, height);//图片大小g.setFont(new Font("Default", Font.ROMAN_BASELINE, 18));//字体大小g.setColor(getRandColor(110, 133));//字体颜色// 绘制干扰线for (int i = 0; i <= lineSize; i++) {drowLine(g);}// 绘制随机字符String randomString = "";for (int i = 1; i <= stringNum; i++) {randomString = drowString(g, randomString, i);}logger.info(randomString);//将生成的随机字符串保存到session中session.removeAttribute(RANDOMCODEKEY);session.setAttribute(RANDOMCODEKEY, randomString);g.dispose();try {// 将内存中的图片通过流动形式输出到客户端ImageIO.write(image, "JPEG", response.getOutputStream());} catch (Exception e) {logger.error("将内存中的图片通过流动形式输出到客户端失败>>>> ", e);}}/*** 绘制字符串*/private String drowString(Graphics g, String randomString, int i) {g.setFont(getFont());g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));String rand = String.valueOf(getRandomString(random.nextInt(randString.length())));randomString += rand;g.translate(random.nextInt(3), random.nextInt(3));g.drawString(rand, 13 * i, 16);return randomString;}/*** 绘制干扰线*/private void drowLine(Graphics g) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(13);int yl = random.nextInt(15);g.drawLine(x, y, x + xl, y + yl);}/*** 获取随机的字符*/public String getRandomString(int num) {return String.valueOf(randString.charAt(num));}
}
    /*** 生成验证码*/@GetMapping(value = "/getVerify")public void getVerify(HttpServletRequest request, HttpServletResponse response) {try {response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片response.setHeader("Pragma", "No-cache");//设置响应头信息,告诉浏览器不要缓存此内容response.setHeader("Cache-Control", "no-cache");response.setDateHeader("Expire", 0);RandomValidateCodeUtil randomValidateCode = new RandomValidateCodeUtil();randomValidateCode.getRandcode(request, response);//输出验证码图片方法} catch (Exception e) {logger.error("获取验证码失败>>>> ", e);}}
<div class="col-xs-6 pull_left"><a href="javascript:void(0);" rel="external nofollow" title="点击更换验证码"><img style="margin-top: 12px;" id="imgVerify" src="" alt="更换验证码" height="36" width="100%" onclick="getVerify(this);"></a>
</div>//获取验证码function getVerify(obj) {obj.src = "/getVerify?" + Math.random();   //加上随机数,切换图片,避免服务器缓存,相同路径,不再发送请求console.log(obj)}

关于请求头的设置

 图片来自菜鸟教程7.1.2 Android Http请求头与响应头的学习 | 菜鸟教程

表单验证

转自Validate表单验证_RocsLee筱站-CSDN博客_validate

validate属性,jquery的小插件

一、 validate的使用步骤

    引入jquery.min.js
    引入 jquery.validate.js
    页面加载后对表单进行验证 $("#表单id名").validate({})
    在validate中的rules中编写验证规则(格式如下)
        字段的name属性:“校验器”(tisps:一个输入框只有一个校验器的时候使用)
        字段的name属性:{校验器:值,校验器:值}(tips:输入框需要有多个校验器的时候使用)
    在validate中的messages中编写提示信息(tips格式与rules相对应)
    在validate中的submitHandler中编写验证通过执行的内容

二、实例

<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" src="scripts/common/jquery.min.js"></script>
<script type="text/javascript" src="scripts/common/jquery.validate.js"></script
<script type="text/javascript">$("#zhuce").validate({rules:{regist_username:{required:true/* remote:{type: "post",url: url,data:{userName:function () {return $("regist_username").val();}}}用ajax判断数据库中用户名是否存在*/},regist_password:{required:true,minlength:6},final_password:{equalTo:"#regist_password"}},messages:{regist_username:{required:"用户名不能为空"},regist_password:{required:"密码不能为空",minlength:"密码最小的长度为6"},final_password:{equalTo:"两次密码不一致"}},submitHandler: function () {//验证通过后进行注册register();}})</script>
</head>
<body><form id="zhuce"><dl><dt><div class='header'><h3>注&nbsp;册</h3></div></dt><dt></dt><dt><div class='letter'><label for="regist_username">用户名:&nbsp;</label><input type="text" name="regist_username" id="regist_username" tabindex='5'/></div></dt><dt><div class='letter'>昵&nbsp;&nbsp;&nbsp;称:&nbsp;<input type="text" name="nickname" id="nickname" tabindex='6'/></div></dt><dt><div class='letter'><label for="regist_password"> 密&nbsp;&nbsp;&nbsp;码:&nbsp;</label><input type="password" name="regist_password" id="regist_password" tabindex='7'/></div></dt><dt><div class='password'><label for="final_password">&nbsp;&nbsp;&nbsp;确认密码:&nbsp;</label><input type="password" name="final_password" id="final_password" tabindex='8'/></div></dt><dt><div><input type="submit" name="" id="regist_button" value='&nbsp注&nbsp册&nbsp' tabindex='9'/><input type="button" name="" id="back" value='&nbsp返&nbsp回&nbsp' tabindex='10'/></div></dt></dl></form>
</body>
</html>


实例二

    function validateRule() {var icon = "<i class='fa fa-times-circle'></i> ";$("#signupForm").validate({  //jquery插件验证表单内容rules: {username: {required: true},password: {required: true}},messages: {username: {required: icon + "请输入您的用户名",},password: {required: icon + "请输入您的密码",}}})}

详细使用jQuery validator 详解/应用_猿来是你-CSDN博客

获取model中数据

thymeleaf模板引擎为前端获取数据提供了较大的便利,在html标签可以通过th标签加${}表达式访问model中的数据。但是如果不想通过th标签而是简单的访问model对象数据,或者是在js中访问modle中的数据,则需要使用内联的方法。

比如我们可以使用[[$ {} ]]访问对象

<p>Hello, [[${session.user.name}]]!</p>

以上的代码可以取代一般的th标签写法

<p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>

Expressions between [[...]] or [(...)] are considered inlined expressions in Thymeleaf。即使用此语法被称为“内联”。使用内联的语句的确会更加简洁一点。

若是想在javascript代码块内直接的使用model的对象值,则必须使用内联实现。

<script type="text/javascript" th:inline="javascript">/*<![CDATA[*/var max = /*[[${maxSumOfDateInYear}]]*/ 20;alert(max);/*]]>*/
</script>

其中第2、5行为基于XML的转义写法,第3行把内联访问的语句用注释引起来,且后面跟着一个空格20,是指若不存在此对象,则自动设置默认值为20。

  注意以上的javascript内联写法是基于你需要“直接地”使用model对象值的场景。否则还有其它写法,比如简单地声明一个hidden input:
 

<input type="hidden" id="maxSumOfDateInYear" th:value="${maxSumOfDateInYear}"/>
<script type="text/javascript" th:inline="none">var max = $("#maxSumOfDateInYear").val();var data = [["2012-05-07", 6], ["2012-04-16", 4]];alert(max);alert(data);
</script>

  以上第1行声明了一个hidden的maxSumOfDateInYear,然后第3行通过jQuery来间接访问。

  注意,若在thymeleaf代码里存在第4行的二维数组字面量的写法,则必须要把javascript代码块设置为inline为none的,否则thymeleaf引擎会把此数组的[[也当成了内联语句处理,从而导致后端报错An error happened during template parsing。要么,你就还是通过hidden间接访问的方式实现。

  或者,也可以通过ajax直接获取内容来实现。但这就属与thymeleaf模板引擎计算过程无关了。

thymeleaf的内联th:inline(在javascript访问model中的数据)_纱厨藤簟,玉人罗扇轻缣。-CSDN博客

登录验证

发送请求

    function login() {$.ajax({type: "POST",url: ctx + "login",//serialize() 方法通过序列化表单值,创建 URL 编码文本字符串。您可以选择一个或多个表单元素(比如 input 及/或 文本框),// 或者 form 元素本身。序列化的值可在生成 AJAX 请求时用于 URL 查询字符串中。data: $('#signupForm').serialize(),success: function (r) {if (r.code == 0) {var index = layer.load(1, {shade: [0.1, '#fff'] //0.1透明度的白色背景});// 父页面跳转 http://localhost/indexparent.location.href = '/index';} else {//jquery插件 layer弹窗jslayer.msg(r.msg);}},});}

接收请求

    @PostMapping("/login")@ResponseBodyR ajaxLogin(String username, String password,String verify,HttpServletRequest request) {try {//从session中获取验证码的值String random = (String) request.getSession().getAttribute(RandomValidateCodeUtil.RANDOMCODEKEY);if (StringUtils.isBlank(verify)) {  //isBlank 判空return R.error("请输入验证码");}if (random.equals(verify)) {} else {return R.error("请输入正确的验证码");}} catch (Exception e) {logger.error("验证码校验失败", e);return R.error("验证码校验失败");}// md5加盐算法后的密码password = MD5Utils.encrypt(username, password);UsernamePasswordToken token = new UsernamePasswordToken(username, password);Subject subject = SecurityUtils.getSubject();try {subject.login(token);return R.ok();} catch (AuthenticationException e) {return R.error("用户或密码错误");}}

R是一个标志类

import java.util.HashMap;
import java.util.Map;public class R extends HashMap<String, Object> {private static final long serialVersionUID = 1L;public R() {put("code", 0);put("msg", "操作成功");}public static R error() {return error(1, "操作失败");}public static R error(String msg) {return error(500, msg);}public static R error(int code, String msg) {R r = new R();r.put("code", code);r.put("msg", msg);return r;}public static R ok(String msg) {R r = new R();r.put("msg", msg);return r;}public static R ok(Map<String, Object> map) {R r = new R();r.putAll(map);return r;}public static R ok() {return new R();}@Overridepublic R put(String key, Object value) {super.put(key, value);return this;}
}

MD5加盐工具类


import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;public class MD5Utils {private static final String SALT = "1qazxsw2";private static final String ALGORITH_NAME = "md5";private static final int HASH_ITERATIONS = 2;public static String encrypt(String pswd) {String newPassword = new SimpleHash(ALGORITH_NAME, pswd, ByteSource.Util.bytes(SALT), HASH_ITERATIONS).toHex();return newPassword;}public static String encrypt(String username, String pswd) {String newPassword = new SimpleHash(ALGORITH_NAME, pswd, ByteSource.Util.bytes(username + SALT),HASH_ITERATIONS).toHex();return newPassword;}public static void main(String[] args) {//		System.out.println(MD5Utils.encrypt("admin", "111111"));}}

对MD5加盐不太了解的可以看这篇文章使用Shiro的SimpleHash加密密码工具类_mr_foxsand的专栏-CSDN博客

关于ajax的页面跳转

使用AJAX实现页面跳转 - 南哥的天下 - 博客园

页面跳转的几种形式

  1. window.parent.location 用于更改父窗口的位置。

  2. window.top.location

    • 它是对象'window'的属性。
    • 它返回窗口层次结构中最顶层窗口的位置。
    • 如果窗口没有父窗口,则top是对自身的引用(窗口=== window.top)

window.top.location.href 和 window.location.href 的区别 - 戒不掉n_思念 - 博客园

日志记录

使用aop横切日志

package com.bootdo.common.aspect;import com.bootdo.common.utils.HttpContextUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import sun.net.util.IPAddressUtil;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;@Aspect
@Component
public class WebLogAspect {private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);@Pointcut("execution( * com.bootdo..controller.*.*(..))")//两个..代表所有子目录,最后括号里的两个..代表所有参数public void logPointCut() {}@Before("logPointCut()")public void doBefore(JoinPoint joinPoint) throws Throwable {// 接收到请求,记录请求内容ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();// 记录下请求内容logger.info("请求地址 : " + request.getRequestURL().toString());logger.info("HTTP METHOD : " + request.getMethod());// 获取真实的ip地址//logger.info("IP : " + IPAddressUtil.getClientIpAddress(request));logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "."+ joinPoint.getSignature().getName());logger.info("参数 : " + Arrays.toString(joinPoint.getArgs()));
//        loggger.info("参数 : " + joinPoint.getArgs());}@AfterReturning(returning = "ret", pointcut = "logPointCut()")// returning的值和doAfterReturning的参数名一致public void doAfterReturning(Object ret) throws Throwable {// 处理完请求,返回内容(返回值太复杂时,打印的是物理存储空间的地址)logger.debug("返回值 : " + ret);}@Around("logPointCut()")public Object doAround(ProceedingJoinPoint pjp) throws Throwable {long startTime = System.currentTimeMillis();Object ob = pjp.proceed();// ob 为方法的返回值logger.info("耗时 : " + (System.currentTimeMillis() - startTime));return ob;}
}

Spring AOP 中@Pointcut的用法 - 山高我为峰 - 博客园


http://chatgpt.dhexx.cn/article/m5qGnUMV.shtml

相关文章

bootdo mysql_iBootDo: 基于BootDo项目定制版,兼容MySQL、Oracle

iBootDo 项目介绍 基于BootDo项目定制版&#xff0c;根据个人项目经验改造&#xff1a;兼容MySQL、Oracle&#xff0c;Thymeleaf升级到3.0&#xff0c;默认Session存入Redis等&#xff1b; 感谢BootDo作者 lcg0124 的分享。 BootDo地址&#xff1a; https://gitee.com/lcg0124/…

bootdo框架首页解析

跳转首页 左侧大的方向上分三大块 左侧第一大块中 包含有 重复的功能 可以去掉 右侧部分控制左侧展开和收起的功能 <div class"row content-tabs"><button class"roll-nav roll-left J_tabLeft"><i class"fa fa-backward">&l…

后台管理页面(bootdo)

项目源码&#xff1a;bootdo: 面向学习型的开源框架&#xff0c;简洁高效&#xff0c;减少过渡封装&#xff0c;展现技术本质 左边的菜单栏分析 数据库结构 样式实例 用树结构封装菜单数据&#xff0c;方便获取前后节点&#xff0c;通过自身id和父id相匹配&#xff0c;构建菜…

BootDo项目

因为本地项目需要使用bootdo和springCloud结合&#xff0c;所以&#xff0c;我今天开始学习一下bootdo的知识 但是从官网下载下一个bootdo项目导入idea之后发现并不能运行起来&#xff0c;报cant found git.exe 然后需要在官网下载对应版本的git。并且在setting–git中配置一下…

BootDo:源代码打包与自启动

一、内容介绍 BootDo是在SpringBoot基础上搭建的一个Java基础开发平台&#xff0c;很有学习价值&#xff0c;本文将介绍BootDo的源代码打包与自启动。 二、前置工作 1.本文bootdo下载的地址为https://gitee.com/lcg0124/bootdo&#xff0c;压缩包名为lcg0124-bootdo-master.…

BootDO框架的使用及介绍

BootDo是一个用于微服务的高效、低包、面向学习的开源Java EE开发框架。 BootDo是一个基于SpringBoot的Java基本开发平台。MyBatis是数据访问层&#xff0c;ApacheShiro是权限授权层&#xff0c;Ehcache缓存常用数据。 BootDo主要定位在后台管理系统中学习通信。内置后端管理…

API网关设计与实现(一)

API网关使用场景API网关技术选型与应用架构 API网关使用场景 在使用微服务架构场景下&#xff0c;客户端在调用后台微服务时&#xff0c;都需要进行登陆认证、权限认证、流量控制、负载均衡、健康检查等操作&#xff0c;这些操作是调用每一个微服务都必须。因此需要将该操作交给…

API 网关实现功能

负载均衡 当网关后面挂接同一应用的多个副本时&#xff0c;每次用户的请求都会通过网关的负载均衡算法&#xff0c;路由到对应的服务上面。例如&#xff1a;随机算法&#xff0c;权重算法&#xff0c;Hash 算法等等。 如果上游服务采取微服务的架构&#xff0c;也可以和注册中…

API 网关

前言 假设你正在开发一个电商网站&#xff0c;那么这里会涉及到很多后端的微服务&#xff0c;比如会员、商品、推荐服务等等。 那么这里就会遇到一个问题&#xff0c;APP/Browser 怎么去访问这些后端的服务&#xff1f;如果业务比较简单的话&#xff0c;可以给每个业务都分配一…

API网关在API安全性中的作用

从单一应用程序切换到微服务时&#xff0c;客户端的行为不能与客户端具有该应用程序的一个入口点的行为相同。简单来说就是微服务上的某一部分功能与单独实现该应用程序时存在不同。 目前在使用微服务时&#xff0c;客户端必须处理微服务体系结构带来的所有复杂性&#xff0c;…

API网关-APISIX简介

本文分享自天翼云开发者社区《API网关-APISIX简介》&#xff0c;作者:w****n Apache APISIX 是一个动态、实时、高性能的云原生 API 网关&#xff0c;提供了负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。APISIX 构建于nginxngx_lua的技术…

初识API网关

网关是什么 百度百科&#xff1a;网关(Gateway)又称网间连接器、协议转换器&#xff0c;在网络层以上实现&#xff0c;连接两个或者多个广域网或者局域网。 我们这里说的是API网关&#xff0c;指的是所有api调用的统一入口。 api网关的在架构中的位置&#xff0c;如下图 ​…

API Gateway(API网关)介绍

API Gateway是一个服务器&#xff0c;也可以说是进入系统的唯一节点。这跟面向对象设计模式中的Facade模式很像。API Gateway封装内部系统的架构&#xff0c;并且提供API给各个客户端。它还可能有其他功能&#xff0c;如授权、监控、负载均衡、缓存、请求分片和管理、静态响应处…

API网关简介|TaobaoAPI接入

API网关是什么 在日常工作中&#xff0c;不同的场合下&#xff0c;我们可能听说过很多次网关这个名称&#xff0c;这里说的网关特指API网关&#xff08;API Gataway&#xff09;。字面意思是指将所有API的调用统一接入API网关层&#xff0c;由网关层负责接入和输出。 那么在什…

谈谈 API 网关

作者&#xff1a;预流 链接&#xff1a;https://www.jianshu.com/p/b52a2773e75f 背景 理论上&#xff0c;客户端可以直接向微服务发送请求&#xff0c;每个微服务都有一个公开的URL&#xff0c;该URL将映射到微服务的负载均衡器&#xff0c;由它负责在可用实例之间分发请求。…

API网关之Kong网关简介

1. Kong简介 Kong是一款基于OpenResty&#xff08;Nginx Lua模块&#xff09;编写的高可用、易扩展的&#xff0c;由Mashape公司开源的API Gateway项目。Kong是基于NGINX和Apache Cassandra或PostgreSQL构建的&#xff0c;能提供易于使用的RESTful API来操作和配置API管理系统…

如何手撕一个API 网关(API Gateway)?

一、什么是API Gateway 一个比较普遍的定义如下&#xff1a; API网关是一个服务器&#xff0c;是系统的唯一入口。从面向对象设计的角度看&#xff0c;它与外观模式类似。API网关封装了系统内部架构&#xff0c;为每个客户端提供一个定制的API。 API网关方式的核心要点是&…

接口网关

1、什么是接口网关&#xff1f; 接口网关的作用&#xff1a;拦截请求&#xff0c;类似Nginx&#xff08;在nginx中配置拦截策略&#xff09;&#xff0c;对该请求进行权限控制&#xff0c;负载均衡、日志管理、接口调用监控等 所有请求都交给接口网关&#xff0c;让网关再进行…

微服务中的 API 网关(API Gateway)

以下是个人于搭建脚手架过程中的一些理念。 SpringCloud微服务架构中&#xff0c;会使用到网关服务。那么可想而知&#xff0c;网关作为边缘服务&#xff0c;其承受的压力是最大的&#xff0c;当然是要考虑网关的高可用&#xff0c;那么就需要多个网关服务集群部署&#xff0c…

API网关,网关平台API流量统一入口

API网关作为API网关平台的API流量的统一入口承担着非常重要的数据输入输出工作&#xff0c;API网关最核心的作用是对服务进行路由并进行数据转发&#xff0c;API网关将成为前后端交互以及内外网交互的唯一数据进出口&#xff0c;所以API网关适合于进行服务鉴权.数据缓存.流量控…