前端(这个是总结的笔记,不是项目,想看项目的,可以翻到第一点的最后,直接有源代码,注解我写的挺多的,对你应该有帮助)
- 前后端交互方式:
- 表单
- ajax
$.ajax({
type: "post",
url: "/recws/user/userLogout",
data: {},
async : false,
success: function (data) {//data为返回json数据
if(data.result == "success"){
window.location.replace("/");
}else{
}
}
});
- iframe
- 控制元素出现和消失:
方法一
利用该方法实现隐藏后,页面的位置还被控件占用,显示空白。
document.getElementById("div3").style.visibility="hidden";
document.getElementById("div4").style.visibility="visible";
<div>visibility:元素的位置仍被占用</div>
<div id="div3" style="visibility:visible;">DIV 3</div>
<div id="div4" style="visibility:hidden;">DIV 4</div>
方法二
利用该方法实现隐藏后,页面的位置不被占用。
document.getElementById("div2").style.display="inline";
document.getElementById("div1").style.display="none";
<div>display:元素的位置不被占用</div>
<div id="div1" style="display:block;">DIV 1</div>
<div id="div2" style="display:none;">DIV 2</div>
- js 操作元素div流程:
- 元素埋点,html中,对想要操作的元素块命名id或者name。
- js代码区中,通过id,name,或者type来获取元素:var userDom = document.getElementById(“user”);
- 操作元素变量进行修改,如修改元素的显示value值:userDom.value = use;
- 将操作封装为函数
- html中通过onclick()等方法,埋点绑定函数,实现点击动态事件等。
- js动态修改表单form的action值,实现不同的跳转:(表单的本质就是发送一个http请求,路由是action的值,参数是表单内的表单控件,其中属性名是控件的name,值是控件的值。比如input控件的输入框,给他取名name就是属性,输入的值就是属性值)
方法一
通过对select表单元件绑定函数,实现动态切换路由,主要通过方法:document.getElementById("Searchtype")
方法获得元素块。要熟悉对象的方法才可以。
<form id="form1" name="form1" method="post" action="../news/index.asp">
<table width="100%" height="43" border="0" cellpadding="0" cellspacing="0">
<tr>
<td height="28"><input name="keyword" type="text" style="width:150px" id="keyword"/></td>
</tr>
<tr>
<td height="28"><select name="Searchtype" style="width:110px" id="Searchtype" onchange="Searchtype1();">
<option value="news" selected="selected">新闻中心</option>
<option value="case">工程案例</option>
</select>
<input type="submit" name="Submit" value="搜索" /></td>
</tr>
</table>
</form>
<script language="javascript">
function Searchtype1(){
var type=document.getElementById("Searchtype").options[document.getElementById("Searchtype").selectedIndex].value;
if (type=="news"){document.getElementById("form1").action="../news/index.asp"}
else if (type=="case"){document.getElementById("form1").action="../case/index.asp"}
}
</script>
方法二
通过对表单绑定onSubmit()函数,实现动态切换路由,主要通过方法:document.form1.a[0].checked
方法判断转移条件,是直接通过name操作元素的方式。这要很熟悉每一个对象的内部属性才可以。
<html>
<head>
<script language="javascript">
function check(){
if(document.form1.a[0].checked==true)
document.form1.action="1.htm"
else
document.form1.action="2.htm"
}
</script>
</head>
<body>
<form name="form1" method="post" action="" onSubmit="check();">
转到页面一<input type="radio" name="a">
转到页面二<input type="radio" name="a">
<input name="" type="submit" value="提交">
</form>
</body>
</html>
- 覆盖已经输出的内容:
用途:
后台返回一个数据的时候,可以将内容输出到一个指定的区域,很多数据都可以放到这个位置,只要重写这里面的内容就好,而不需要自己预先建立很多个块,然后隐藏再显示什么的。
方法一
document.write()是在页面内写内容,他会覆盖页面内容,是写死的,且document.write会将页面上的所有内容清除包括标题。
document.write()
方法二
innerHTML只会重写所属元素的内容,即
<script>
window.onload = function(){
var ff=document.getElementById("sg");
ff.innerHTML="<p>I love <em>JavaScript</em>!</p>";
}
</script>
- 前端ui设置通式:
- 直接用
框住,然后配合埋点id加上css就可以实现好看的ui和合适的布局
- 前端执行js代码的时候,建议写好算法流程,比如:1.创建数组,2.数组转化为string,3.写好遍历数组的方法,4.写好数组运算的方法。即:按照面向过程的方式,一个过程一次测试,通过了再来下一个,而不要几个过程才进行一次,那样会导致debug时间增加。
- 同理,前端写css界面的时候也是,不要直接套下整个模板,要一步一步看。
前端源码:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
body {
background-image: url(http://gss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/8ad4b31c8701a18b4c1c626c9a2f07082838fe1a.jpg);
background-repeat: no-repeat;
/* 当内容高度大于图片高度时,背景图像的位置相对于viewport固定 */
background-attachment: fixed;
/*此条属性必须设置否则可能无效*/
/* 让背景图基于容器大小伸缩 */
background-size: cover;
/* 设置背景颜色,背景图加载过程中会显示背景色 */
background-color: #CCCCCC;
}
#user_reg {
font-family: 微软雅黑;
font-size: 40px;
text-align: center;
margin-top: 100px;
}
form {
width: 600px;
/*设置宽度,方便使其居中*/
/*margin: 40px auto auto auto;*/
/*上右下左*/
font-size: 25px;
}
input {
height: 30px;
width: 120px;
margin-top: 5px;
margin-bottom: 5px;
}
/*input标签下的属性选择器*/
input[type="submit"],
input[type="button"] {
height: 40px;
width: 130px;
margin-top: 5px;
margin-left: 6px;
}
input[type="text"]{
height: 25px;
width: 430px;
}
/*文本特效*/
span {
color: #d9d9d9;
position: relative;
z-index: 1;
}
span::before {
content: "";
z-index: -1;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: #262626;
transform-origin: center right;
transform: scaleX(0);
transition: transform 0.1s linear;
/* 这里不要指明为 all */
}
span:hover {
cursor: pointer;
}
span:hover::before {
transform-origin: center left;
transform: scaleX(1);
}
</style>
<script language="javascript" th:inline="javascript">
function check(){
if(document.form1.a[0].checked==true){
document.form1.action="/encryption/caeser";
}
if (document.form1.a[1].checked==true){
document.form1.action="/encryption/caeser/encode";
}
if(document.form1.a[2].checked==true)
document.form1.action="/encryption/playfair"
if(document.form1.a[3].checked==true)
document.form1.action="/encryption/playfair/encode"
if(document.form1.a[4].checked==true)
document.form1.action="/encryption/hill"
if(document.form1.a[5].checked==true)
document.form1.action="/encryption/hill/encode"
}
// function check2(){
// var userDom = document.getElementById("my");
// var use =userDom.value ;
// }
function show() {
if(document.getElementById("div2").style.display=="none"){
document.getElementById("div2").style.display="inline";
}
else{
document.getElementById("div2").style.display="none";
}
// <div id="div1" style="display:block;">DIV 1</div> block又是什么状态??
}
function click1() {
document.getElementById("div3").style.display = "inline";
var ff = document.getElementById("div3");
if (document.form1.a[0].checked == true) {
ff.innerHTML = "<br/>介绍:<br/>凯撒加密,移动位置为3,支持中文加密";
}
if (document.form1.a[1].checked == true) {
ff.innerHTML = "<br/>介绍:<br/>凯撒解密,移动位置为3,支持中文加密";
}
if (document.form1.a[2].checked == true)
ff.innerHTML = "<br/>介绍:<br/>playfair加密,采用的构成5*5字母表的单词为pengyuxia,仅仅支持英文";
if (document.form1.a[3].checked == true)
ff.innerHTML = "<br/>介绍:<br/>playfair解密,采用的构成5*5字母表的单词为pengyuxia,仅仅支持英文,注意,输入的密文肯定是偶数,如果想自己随意测试自己写的密文,请输入偶数位字符串";
if (document.form1.a[4].checked == true)
ff.innerHTML = "<br/>介绍:<br/>hill加密,采用3*3矩阵,支持所有ascii码,长度任意的字符加密,其中,长度不是3的倍数的字符长度将自动补x";
if (document.form1.a[5].checked == true)
ff.innerHTML = "<br/>介绍:<br/>hill解密,明文不是3的倍数的字符,最后将自动补x,直到为3的倍数";
}
function load() {
var a = [[${result}]];
if (a != null) {
document.getElementById("div2").style.display = "inline";
} else {
document.getElementById("div2").style.display = "none";
}
}
</script>
</head>
<body onload="load();">
<form name="form1" method="post" action="" onSubmit="check();">
<table>
<tr>
<td><p></p></td>
<td></td>
</tr>
</table>
<div id="user_reg">古典加密</div><br/>
<input type="radio" name="a" on onchange="click1();">---凯撒加密---
<!-- 只要一个绑定了,那么就都绑定了-->
<input type="radio" name="a" onchange="click1();">---凯撒解密---
<br>
<input type="radio" name="a" onchange="click1();">-playfair加密 -
<input type="radio" name="a" onchange="click1();">-playfair解密 -
<br>
<input type="radio" name="a" onchange="click1();"> ---hill加密----
<input type="radio" name="a" onchange="click1();"> ---hill解密---
<br/>
<br/>
<br/>
<span>明文/密文:</span><input id="my" type="text" name="front">
<br/>
<br/>
<div align="center">
<input name="" type="submit" value="提交">
<input name="display" type="button" value="显示结果" onclick="show();" >
</div>
<div id="div2" style="display:none;">
<p id="miwen" th:text="'结果:'+ ${result}" ></p>
</div>
<div id="div3" style="display:inline;">
<p id="m">使用说明:<br/>选择加密(或者解密)方式,而后输入要加密或者解密的文本,点击执行即可获得密文(明文)</p>
</div>
</form>
</body>
</html>
参考项目
- css界面参考:https://blog.csdn.net/weixin_41287260/article/details/83474429
后端
springmvc
总体来说,项目中我可以感受到的是:springmvc是控制跳转的。和我之前写的前后端分离的项目不一样的是,这种方式写出的项目,每次的返回值都是一个modelandview,这种情况带来的后果就是。每一次都要找到resource中的页面,然后渲染数据,再返回整个页面,这种方式,很不ajax,很消耗资源,每次都是重新的渲染。如果你在当前页面已经有一些状态和初始不一样了,那会带来一些麻烦。不过,因为是和spring集成的,所以,很自然的就可以用返回json的方式,只要,前端是通过ajax发送的请求,有接收函数即可。
- 返回数据的方式:
- string+model
@RequestMapping("/caeser")
public String encryptionByCaeser(Model model,@RequestParam String front){
String ciphertext=encryptByCaeserServer.encrypt(front);
model.addAttribute("result",ciphertext);
return "/mi/try";//返回路径文件也可以,不带model也可以,好奇怪啊。
}
- modelandview
@RequestMapping("/caeser/encode")
public ModelAndView encodeCaeser(@RequestParam String front){
ModelAndView modelAndView=new ModelAndView("/mi/try");
String ciphertext=encryptByCaeserServer.encode(front);
modelAndView.addObject("result",ciphertext);
return modelAndView;
}
- 为了实现ajax,我这没有用前端的$ajax()函数,而是直接用了表单,然后只要返回的表单地址是同一个值/mi/try,那么,最终结果显示再页面上,看起来就像是ajax一样了。因为页面没变,渲染数据已经在后台完成,形成了modelandview再返回的。
- 总结前后端交互方式:
前端传参方式,通过name给属性命名和赋值,再通过action发送http请求(通过url来处理),而后mvc再返回一个
数据处理了的页面,这个过程通过modelandview自动再默认的资源文件下查找
后端源码;
一个controller:
package com.example.dockerjd.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.example.dockerjd.passwordService.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* @Author: permission
* @Description:
* @Date: Create in 20:00 2019/10/28
* @Modified By:
*/
@Controller
@RequestMapping("/encryption")
public class encryptionController {
@Autowired
private encryptByCaeserServer encryptByCaeserServer;
@Autowired
private enByHillService enByHillService;
@Autowired
private playfairerService playfairerService;
@RequestMapping(value="/index")
public ModelAndView index(HttpServletRequest request, HttpServletResponse response){
return new ModelAndView("/mi/try");
}
//request方式获得参数
@RequestMapping("/caeser")
public String encryptionByCaeser(Model model,@RequestParam String front){
String ciphertext=encryptByCaeserServer.encrypt(front);
model.addAttribute("result",ciphertext);
return "/mi/try";//返回路径文件也可以,不带model也可以,好奇怪啊。
}
//model+string方式
//@RequestParam方式获得参数,三种方式,反射,@RequestParam(“属性名”),对象反射接收多个属性
@RequestMapping("/caeser/encode")
public ModelAndView encodeCaeser(@RequestParam String front){
ModelAndView modelAndView=new ModelAndView("/mi/try");
String ciphertext=encryptByCaeserServer.encode(front);
modelAndView.addObject("result",ciphertext);
return modelAndView;
}
//modelAndView直接插入法
@RequestMapping("/hill")
public String encryptionByHill(Model model,@RequestParam String front){
String ciphertext=enByHillService.hillCode(front);
model.addAttribute("result",ciphertext);
return "/mi/try";
}
//跳转方式
@RequestMapping("/hill/encode")
public String encodeHill(Model model,@RequestParam String front){
String plaintext=enByHillService.encode(front);
model.addAttribute("result",plaintext);
return "/mi/try";
}
//@ModelAttribute方法直接让所有的view都插入此model,此方法不讲
@RequestMapping("/playfair")
public String encryptionByPlayfair(Model model,@RequestParam String front){
String ciphertext=playfairerService.playfair(front);
model.addAttribute("result",ciphertext);
return "/mi/try";
}
@RequestMapping("/playfair/encode")
public String encodePlayfair(Model model,@RequestParam String front){
String plaintext=playfairerService.encode(front);
model.addAttribute("result",plaintext);
return "/mi/try";
}
}
三个service
package com.example.dockerjd.passwordService;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.LUDecomposition;
import org.apache.commons.math3.linear.RealMatrix;
import org.springframework.stereotype.Service;
import java.util.Scanner;
/**
* @Author: permission
* @Description:
* @Date: Create in 20:30 2019/10/28
* @Modified By:
*/
@Service
public class enByHillService {
public double[][] key={{8,6,9},{6,9,5},{5,8,4}};
/* 作用:对三位明文加密 */
private double[][] encrypt(double[][] b) {
RealMatrix matrixb = new Array2DRowRealMatrix(b);
RealMatrix matrixkey = new Array2DRowRealMatrix(key);
double[][] matrixtoarray = matrixb.multiply(matrixkey).getData();
return matrixtoarray;
}
/* 作用:字符串分割为三位 */
public String[] getPlaintexts(String plaintext){
String[] plaintexts;
if(plaintext.length()/3==0){
plaintexts=new String[1];
}else if(plaintext.length()%3==0){
plaintexts=new String[plaintext.length()/3];
}else {
plaintexts=new String[plaintext.length()/3+1];
}
if(plaintext.length()>=3){
int i=0,j=0;
for(;i<plaintext.length()/3;i++){
plaintexts[i]=plaintext.substring(j,j+3);
j+=3;
}
if (plaintext.substring(j).length()==1){
plaintexts[i]=plaintext.substring(j)+"xx";
}
if (plaintext.substring(j).length()==2){
plaintexts[i]=plaintext.substring(j)+"x";
}
}else{
if (plaintext.length()==1){
plaintexts[0]=plaintext+"xx";
}
if (plaintext.length()==2){
plaintexts[0]=plaintext+"x";
}
}
return plaintexts;
}
/* 作用:String转为double【】【】 */
public double[][] StringtoDouble(String a){
System.out.println(a);
char[] chars = new char[a.length()];//字符暂存数组
for (int i = 0; i < a.length(); i++) {
chars[i] = a.charAt(i);
}
double[][] b = new double[1][a.length()];//明文数组
for (int i = 0; i < a.length(); i++) {
int parse1=Integer.valueOf(a.charAt(i));
b[0][i]=parse1;
}
return b;
}
/* 作用:double二维数组转化一个字符串 */
public String doubleToString(double[][] array) {
StringBuffer plaintext=new StringBuffer();
System.out.println(array.length+"列长:"+array[0].length);
for (int t = 0; t < array.length; t++) {
for (int y = 0; y < array[t].length; y++) {
int ac= (int) (array[t][y]+0.001);
plaintext.append(ac+",");
}
}
return plaintext.toString();//问题1不确定会不会出现toString变成的是一串地址吗 没问题
}
/* 作用:长加密 */
public String hillCode(String plaintext){
/**
* @Author: permission
* @Description: 输入明文,即可获得密文
* @Date: 2019/10/31 23:30
* @Param [plaintext]
* @Return: java.lang.String
*/
String ciphertext="";
double[][] ciphertexts;
if(plaintext.length()/3==0){
ciphertexts=new double[1][3];
}else if(plaintext.length()%3==0){
ciphertexts=new double[plaintext.length()/3][3];
}else {
ciphertexts=new double[plaintext.length()/3+1][3];
}
String[] plaintexts=getPlaintexts(plaintext);
for(int i=0;i<plaintexts.length;i++){
double[][] d=StringtoDouble(plaintexts[i]);
double[][] d2=encrypt(d);
ciphertexts[i]=d2[0];//i行3列,一行是一个密文串
}
ciphertext=doubleToString(ciphertexts);
return ciphertext;
}
/* 作用:String[]数组转化为double[][] */
public double[][] StringToDouble(String[] mingwen){
double[][] d;
if(mingwen.length/3==0){
d=new double[1][3];
}else if(mingwen.length%3==0){
d=new double[mingwen.length/3][3];
}else {
d=new double[mingwen.length/3+1][3];
}
for(int i=0;i<d.length;i++){
for(int j=0;j<3;j++){
d[i][j]=Integer.valueOf(mingwen[i*3+j]);
}
}
return d;
}
/* 作用:翻译明文 */
public String translate(double[][] array){
StringBuffer plaintext=new StringBuffer();
for (int t = 0; t < array.length; t++) {
for (int y = 0; y < array[t].length; y++) {
int ac= (int) (array[t][y]+0.001);
plaintext.append((char)ac);
}
}
return plaintext.toString();//问题1不确定会不会出现toString变成的是一串地址吗 没问题
}
/* 作用:对三位密文解码 */
public double[][] decrypt(double[][] miwen) {
RealMatrix key_1 = inverseMatrix(new Array2DRowRealMatrix(key));
RealMatrix matrixmiwen;
double[][] mingwen;
double[][] mingwens=new double[miwen.length][3];
double[][] parse=new double[1][3];;
for(int i=0;i<miwen.length;i++){
parse[0]=miwen[i];
matrixmiwen = new Array2DRowRealMatrix(parse);
mingwen = matrixmiwen.multiply(key_1).getData();
mingwens[i]=mingwen[0];
}
return mingwens;
}
/* 作用:长解码 */
public String encode(String ciphertext){
/**
* @Author: permission
* @Description: 输入密文,即可获得明文
* @Date: 2019/10/31 23:31
* @Param [ciphertext]
* @Return: java.lang.String
*/
String plaintext="";
String[] ciphertexts = ciphertext.split(",");
double[][] d=StringToDouble(ciphertexts);//String[]数组转化为double[][]
double[][] mingwen=decrypt(d);//三位一组调用decrypt解密得到明文//返回的明文double[][]再次成为我的数据结构:即i行3列的形式
plaintext=translate(mingwen);//按顺序遍历明文double【】【】强转为char【】
//char输出为原文。
return plaintext;
}
/* 作用:key求逆 */
public static RealMatrix inverseMatrix(RealMatrix A) {
RealMatrix result = new LUDecomposition(A).getSolver().getInverse();
return result;
}
}
package com.example.dockerjd.passwordService;
import org.springframework.stereotype.Service;
/**
* @Author: permission
* @Description:
* @Date: Create in 20:06 2019/10/28
* @Modified By:
*/
@Service
public class encryptByCaeserServer {
/* 作用:加密 */
public String encrypt(String plaintext){
// String fro=plaintext.substring(0,3);
// String end=plaintext.substring(3);
// String caeserPassword=end+fro;
char[] chars = new char[plaintext.length()];//字符暂存数组
for (int i = 0; i < plaintext.length(); i++) {
chars[i] = (char)((int) plaintext.charAt(i)+3);
}
return new String(chars);
}
/* 作用:解码 */
public String encode(String caeserPassword){
char[] chars = new char[caeserPassword.length()];//字符暂存数组
for (int i = 0; i < caeserPassword.length(); i++) {
chars[i] = (char)((int) caeserPassword.charAt(i)-3);
}
return new String(chars);
}
}
package com.example.dockerjd.passwordService;
import org.springframework.stereotype.Service;
/**
* @Author: permission
* @Description:
* @Date: Create in 0:07 2019/10/30
* @Modified By:
*/
@Service
public class playfairerService {
private char[][] key ={{'p','e','n','g','y'},
{'u','x','i','a','b'},
{'q','w','r','t','o'},
{'s','d','f','h','j'},
{'k','l','c','v','m'}};//去z版本
/* 作用:置换 */
private char[] change(char a,char b){
char[] returnWord=new char[2];
int a1=0,b1=0;
int a2=0,b2=0;
for(int i=0;i<5;i++){
for (int j=0;j<5;j++){
if(a==key[i][j]){
a1=i;b1=j;
}
if(b==key[i][j]){
a2=i;b2=j;
}
}
}//循环遍历,确定ij位置
if(a1==a2){
returnWord[0]=key[a1][(b1+1)%5];
returnWord[1]=key[a2][(b2+1)%5];
}else if(b1==b2){
returnWord[0]=key[(a1+1)%5][b1];
returnWord[1]=key[(a2+1)%5][b2];
}else{
returnWord[0]=key[a2][b1];
returnWord[1]=key[a1][b2];
}
//比较两个word各自的ij,if(i1=i2)那么赋值给对应位置1/2的returnword的值是returnword【1】=key【(i+1)%5】【j】;
//if(j1=j2),那么对应的是rewornword【1】=key【i】【(j+1)%5】;最后,两个if都没有执行,那么对应的是(交换x,而不是对x进行计算)rewornword【1】=key【i2】【j】,rewornword【1】=key【i1】【j】
return returnWord;
}
/* 作用:整理明文 */
private char[] tidyPlaintext(String plaintext){
StringBuffer stringBuffer=new StringBuffer(plaintext);
for(int i=0;i<stringBuffer.length();i+=2){
if(i+1==stringBuffer.length()){//消除临界状态。处理数组等数据必备考虑点。
break;
}
if(stringBuffer.charAt(i)==stringBuffer.charAt(i+1)){
stringBuffer.insert(i+1,'x');//插入到指定位置,而不是指定位置后方
}
}
if(stringBuffer.length()%2!=0){
stringBuffer.append('x');
}
char[] returnWord=new char[stringBuffer.length()];
for (int i = 0; i < stringBuffer.length(); i++) {
returnWord[i] = stringBuffer.charAt(i);
}
return returnWord;
}
/* 作用:加密 */
public String playfair(String plaintext){
//整理明文,长度不是偶数就补上一个x,一组两个相同就补上x。分两步实现。最后返回字符化char【】数组,
//二元替代函数,传入两个字符char【】,传出两个字符char【】,不够偶数补充x
// 存储函数,将返回的数据循环存储。
String caeserPassword="";
char[] chars=tidyPlaintext(plaintext);
char[] parse=new char[chars.length];
for(int i=0;i<chars.length;i+=2){//明文处理了,必定是偶数,所以不用考虑临界基数的时候产生的越界情况
char[] a=change(chars[i],chars[i+1]);//暂存返回结果到a
parse[i]=a[0];parse[i+1]=a[1];//结果真正存入暂存char数组中
}
caeserPassword=new String(parse);
return caeserPassword;
}
/* 作用:两个char进行解码 */
private char[] reBack(char a,char b ){
char[] returnWord=new char[2];
int a1=0,b1=0;
int a2=0,b2=0;
for(int i=0;i<5;i++){
for (int j=0;j<5;j++){
if(a==key[i][j]){
a1=i;b1=j;
}
if(b==key[i][j]){
a2=i;b2=j;
}
}
}
if(a1==a2){
returnWord[0]=key[a1][(b1-1)%5];
returnWord[1]=key[a2][(b2-1)%5];
}else if(b1==b2){
returnWord[0]=key[(a1+4)%5][b1];
returnWord[1]=key[(a2+4)%5][b2];
}else{
returnWord[0]=key[a2][b1];
returnWord[1]=key[a1][b2];
}
return returnWord;
}
/* 作用:密文处理 */
private String tidyCiphertext(String Ciphertext){
//没有完善,出现了全xxx的符号,无法处理,同时,如果是3个以上的x连续,那么,规律是每多一个x,传入的Ciphertext就多两个x可以利用这个规律,判定多少个连续的x,
// 明文有3个连续x对应密文是4个x,明文4个x对应密文是6个x,密文5个对应8个x。即明文为x 对应密文(x-2)*2+2(x>2时).
System.out.println(Ciphertext);
int[] a= new int[Ciphertext.length()];int j=0;//准备好表的数据结构,这里用数组代替
StringBuffer stringBuffer=new StringBuffer(Ciphertext);
for(int i=1;i<stringBuffer.length();i++){//buffer遍历,找到x并且利用数组记录位置,将0和最后一个除外
if(i==Ciphertext.length()-1){
break;
}
else if (stringBuffer.charAt(i)=='x'){
a[j]=i;
j++;
}
}
for(int z=0;z<j;z++){//循环对x前后判断,一样就删除,不一样就保留
if(stringBuffer.charAt(a[z]-1)==stringBuffer.charAt(a[z]+1)){
stringBuffer.deleteCharAt(a[z]);
for(int k=1;k<j-z;k++){
a[z+k]--;
}
}
}
return stringBuffer.toString();
}
/* 作用:解密 */
public String encode(String ciphered){
if(ciphered.length()%2!=0){
return "密文错误,应该是偶数密文,不要自己乱打密文";
}
String plaintext ="";
char[] parse=new char[ciphered.length()];
// char[] chars=tidyPlaintext(ciphered);//密文一定是偶数,没有重复单词在同一组,所以不用处理了,只要转化为char【】就好了
char[] chars=tidyPlaintext(ciphered);int h=0; //准备转换字符串的数据结构。一个表来装,一个计数位
for (char t:ciphered.toCharArray()
) {
chars[h]=t;
h++;
}
for(int i=0;i<ciphered.length();i+=2){
char[] a=reBack(chars[i],chars[i+1]);//暂存返回结果到a
parse[i]=a[0];parse[i+1]=a[1];//结果真正存入暂存char数组中
}
plaintext=new String(parse);
return tidyCiphertext(plaintext);
}
// public static void main(String[] args) {
// playfairerService playfairerService=new playfairerService();
// String a=playfairerService.playfair("hello");
// System.out.println(a);
// String b=playfairerService.encode(a);
// System.out.println(b);
// }
}
即可实现项目。
整个项目结构源码可以看我的github:
使用github
- (可选)修改git的默认打开位置:找到git bash,右键属性,打开属性如下:
修改目标和起始位置即可。改为:
当然,也可以直接修改系统变量%HOMEDRIVE和%HOMEPATH为你想要的路径。
参考:https://blog.csdn.net/qq_15971883/article/details/97916942
参考:https://www.cnblogs.com/lightandtruth/p/9467428.html - gitGUI的使用:https://jingyan.baidu.com/article/19020a0a7ae6af529c284248.html
- 还有一篇pdf在我的github中
- git的一些小知识:
- 上传到gitlab的时候,没有自签名,怎么传送文件?
可以通过配置:git config --global http.sslVerify false
让项目上传不用密钥,而是直接传,如果不想改,要回到原样,可以输入:
git config --global -e
再把配置最后一个sslVerify一行删除即可:
参考:https://www.cnblogs.com/wshiqtb/p/5160608.html
4. git一个本地仓库推送到多个远端:
https://blog.csdn.net/qq_36667170/article/details/79336760
5. 常见的git操作:https://www.jianshu.com/p/fb61299086b6
6. git遇到的问题:
https://blog.csdn.net/myy629464/article/details/84205258
7. git和gitlab配合使用流程:
- 第一步是gitlab新建project
- 在一个本地文件夹,打开git bash中建立远端联系:git remote add [name] [https地址] 不用这一步,第四步已经建立联系了
- git bash克隆远端项目:git clone [https地址]
- 进入到有.git文件的目录,此时,远端仓库应该已经在.git中有了。
- 可以正常使用了
- 期间遇到的bug:
- ssh: Could not resolve hostname https: Name or service not known
其实拉下的项目中已经有了远端的仓库名字,不用自己取名字,我是自己去了名字,结果还报错说找不到 - nothing added to commit but untracked files present
每一次提交都需要将所有新加的文件add,不然无法提交。可以选择将不想提交的文件添加到。ignore中就好。 - Your branch is ahead of ‘origin/master’ by 1 commit.
这是说远端的版本比你的版本还要新,你若是继续修改,后面要merge一下才可以push。参考:https://www.liaoxuefeng.com/wiki/896043488029600/900004111093344