diff --git a/src/main/java/com/lz/common/annotation/TaskHeader.java b/src/main/java/com/lz/common/annotation/TaskHeader.java new file mode 100644 index 00000000..f1ee62f5 --- /dev/null +++ b/src/main/java/com/lz/common/annotation/TaskHeader.java @@ -0,0 +1,11 @@ +package com.lz.common.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface TaskHeader { + + String value ( ) default ""; +} diff --git a/src/main/java/com/lz/common/cli/CliToken.java b/src/main/java/com/lz/common/cli/CliToken.java new file mode 100644 index 00000000..48fda924 --- /dev/null +++ b/src/main/java/com/lz/common/cli/CliToken.java @@ -0,0 +1,23 @@ +package com.lz.common.cli; + +public interface CliToken { + /** + * @return the token value + */ + String value(); + + /** + * @return the raw token value, that may contain unescaped chars, for instance {@literal "ab\"cd"} + */ + String raw(); + + /** + * @return true when it's a text token + */ + boolean isText(); + + /** + * @return true when it's a blank token + */ + boolean isBlank(); +} diff --git a/src/main/java/com/lz/common/cli/CliTokens.java b/src/main/java/com/lz/common/cli/CliTokens.java new file mode 100644 index 00000000..c70f5625 --- /dev/null +++ b/src/main/java/com/lz/common/cli/CliTokens.java @@ -0,0 +1,43 @@ +package com.lz.common.cli; + + + + +import com.lz.common.cli.impl.CliTokenImpl; + +import java.util.List; + +/** + * @author beiwei30 on 09/11/2016. + */ +public class CliTokens { + /** + * Create a text token. + * + * @param text the text + * @return the token + */ + public static CliToken createText(String text) { + return new CliTokenImpl(true, text, text); + } + + /** + * Create a new blank token. + * + * @param blank the blank value + * @return the token + */ + public static CliToken createBlank(String blank) { + return new CliTokenImpl(false, blank, blank); + } + + /** + * Tokenize the string argument and return a list of tokens. + * + * @param s the tokenized string + * @return the tokens + */ + public static List tokenize(String s) { + return CliTokenImpl.tokenize(s); + } +} diff --git a/src/main/java/com/lz/common/cli/IntConsumer.java b/src/main/java/com/lz/common/cli/IntConsumer.java new file mode 100644 index 00000000..a2f23539 --- /dev/null +++ b/src/main/java/com/lz/common/cli/IntConsumer.java @@ -0,0 +1,8 @@ +package com.lz.common.cli; + +/** + * @author bw on 25/10/2016. + */ +public interface IntConsumer { + void accept(int value); +} diff --git a/src/main/java/com/lz/common/cli/LineStatus.java b/src/main/java/com/lz/common/cli/LineStatus.java new file mode 100644 index 00000000..3e4a9854 --- /dev/null +++ b/src/main/java/com/lz/common/cli/LineStatus.java @@ -0,0 +1,160 @@ +/* + * Copyright 2015 Julien Viet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.lz.common.cli; + + +import java.util.LinkedList; + +/** + * @author Julien Viet + */ +public class LineStatus implements IntConsumer { + + // Keeping this internal to this package + static class Ext extends LineStatus implements IntConsumer { + final LinkedList buffer; + Ext() { + this.buffer = new LinkedList(); + } + public void accept(int codePoint) { + super.accept(codePoint); + switch (transition) { + case TO_WEAK: + buffer.add((int) '"'); + break; + case TO_STRONG: + buffer.add((int) '\''); + break; + case FROM_WEAK: + buffer.add((int) '"'); + break; + case FROM_STRONG: + buffer.add((int) '\''); + break; + case TO_ESC: + buffer.add((int)'\\'); + break; + case FROM_ESC: + if (codePoint != '\r') { + buffer.add(codePoint); + } else { + buffer.removeLast(); + } + break; + case CODE_POINT: + buffer.add(codePoint); + break; + } + } + } + + protected int quote = 0; + protected Transition transition; + + public boolean isEscaped() { + return transition == Transition.FROM_ESC; + } + + public boolean isEscaping() { + return transition == Transition.TO_ESC; + } + + /** + * @return true if it's currently quoted + */ + public boolean isQuoted() { + return quote != 0; + } + + public boolean isWeaklyQuoted() { + return quote == '"'; + } + + public boolean isStronglyQuoted() { + return quote == '\''; + } + + /** + * @return the current quote: {@code 0}, {@code '} or {@code "} value + */ + public int getQuote() { + return quote; + } + + public boolean isCodePoint() { + return transition == Transition.CODE_POINT || transition == Transition.FROM_ESC; + } + + @Override + public void accept(int cp) { + Transition next; + if (transition == Transition.TO_ESC) { + next = Transition.FROM_ESC; + } else { + switch (quote) { + case 0: + switch (cp) { + case '\'': + quote = '\''; + next = Transition.TO_STRONG; + break; + case '"': + quote = '"'; + next = Transition.TO_WEAK; + break; + case '\\': + next = Transition.TO_ESC; + break; + default: + next = Transition.CODE_POINT; + break; + } + break; + case '\'': + if (cp == '\'') { + quote = 0; + next = Transition.FROM_STRONG; + } else { + next = Transition.CODE_POINT; + } + break; + case '"': + if (cp == '"') { + quote = 0; + next = Transition.FROM_WEAK; + } else if (cp == '\\') { + // Note we don't make the distinction between special chars like " or \ from other chars + // that are supposed to not escaped (i.e "\a" is \a and "\$" is $) + // this interpretation is not done by termd + next = Transition.TO_ESC; + } else { + next = Transition.CODE_POINT; + } + break; + default: + throw new AssertionError(); + } + } + this.transition = next; + } + + private enum Transition { + + TO_STRONG, TO_WEAK, FROM_STRONG, FROM_WEAK, TO_ESC, CODE_POINT, FROM_ESC; + + } +} diff --git a/src/main/java/com/lz/common/cli/impl/CliTokenImpl.java b/src/main/java/com/lz/common/cli/impl/CliTokenImpl.java new file mode 100644 index 00000000..bf4bbad5 --- /dev/null +++ b/src/main/java/com/lz/common/cli/impl/CliTokenImpl.java @@ -0,0 +1,175 @@ +package com.lz.common.cli.impl; + + +import com.lz.common.cli.CliToken; +import com.lz.common.cli.LineStatus; + +import java.util.LinkedList; +import java.util.List; + +/** + * @author Julien Viet + */ +public class CliTokenImpl implements CliToken { + + final boolean text; + final String raw; + final String value; + + public CliTokenImpl(boolean text, String value) { + this(text, value, value); + } + + public CliTokenImpl(boolean text, String raw, String value) { + this.text = text; + this.raw = raw; + this.value = value; + } + + @Override + public boolean isText() { + return text; + } + + @Override + public boolean isBlank() { + return !text; + } + + public String raw() { + return raw; + } + + public String value() { + return value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof CliTokenImpl) { + CliTokenImpl that = (CliTokenImpl) obj; + return text == that.text && value.equals(that.value); + } + return false; + } + + @Override + public String toString() { + return "CliToken[text=" + text + ",value=" + value + "]"; + } + + public static List tokenize(String s) { + + List tokens = new LinkedList(); + + tokenize(s, 0, tokens); + return tokens; + + } + + private static void tokenize(String s, int index, List builder) { + while (index < s.length()) { + char c = s.charAt(index); + switch (c) { + case ' ': + case '\t': + index = blankToken(s, index, builder); + break; + case '(': + index = khToken(s, index, builder); + break; + default: + index = textToken(s, index, builder); + break; + } + } + } + + // Todo use code points and not chars + private static int textToken(String s, int index, List builder) { + LineStatus quoter = new LineStatus(); + int from = index; + StringBuilder value = new StringBuilder(); + while (index < s.length()) { + char c = s.charAt(index); + if (isLeftKuo(c)) { + break; + } + quoter.accept(c); + if (!quoter.isQuoted() && !quoter.isEscaped() && isBlank(c)) { + break; + } + if (quoter.isCodePoint()) { + if (quoter.isEscaped() && quoter.isWeaklyQuoted() && c != '"') { + value.append('\\'); + } + value.append(c); + } + index++; + } + builder.add(new CliTokenImpl(true, s.substring(from, index), value.toString())); + return index; + } + + private static int blankToken(String s, int index, List builder) { + int from = index; + while (index < s.length() && isBlank(s.charAt(index))) { + index++; + } + // builder.add(new CliTokenImpl(false, s.substring(from, index))); + return index; + } + + + private static int khToken(String s, int index, List builder) { + int from = index; + int kuo = 0; + while (index < s.length()) { + index++; + char c = s.charAt(index); + try { + //Thread.sleep(100); + } catch (Exception e) { + e.printStackTrace(); + } + if (isLeftKuo(c)) { + kuo++; + continue; + } + if (isRightKuo(c)) { + if (kuo == 0) { + index++; + break; + } else { + kuo--; + continue; + } + } + } + builder.add(new CliTokenImpl(false, s.substring(from, index))); + return index; + } + + + private static boolean isBlank(char c) { + return c == ' ' || c == '\t'; + } + + + private static boolean isLeftKuo(char c) { + return c == '('; + } + + private static boolean isRightKuo(char c) { + return c == ')'; + } + + +} diff --git a/src/main/java/com/lz/common/utils/Md5Utils.java b/src/main/java/com/lz/common/utils/Md5Utils.java new file mode 100644 index 00000000..92bccbb4 --- /dev/null +++ b/src/main/java/com/lz/common/utils/Md5Utils.java @@ -0,0 +1,24 @@ +package com.lz.common.utils; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Md5Utils { + + public static String toMD5(String plainText) { + byte[] secretBytes = null; + try { + secretBytes = MessageDigest.getInstance("md5").digest( + plainText.getBytes()); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("没有md5这个算法!"); + } + String md5code = new BigInteger(1, secretBytes).toString(16);// 16进制数字 + // 如果生成数字未满32位,需要前面补0 + for (int i = 0; i < 32 - md5code.length(); i++) { + md5code = "0" + md5code; + } + return md5code; + } +} diff --git a/src/main/java/com/lz/common/utils/R.java b/src/main/java/com/lz/common/utils/R.java index e604cace..05a6f4e3 100644 --- a/src/main/java/com/lz/common/utils/R.java +++ b/src/main/java/com/lz/common/utils/R.java @@ -8,6 +8,7 @@ package com.lz.common.utils; +import com.lz.modules.app.utils.t.Tuple; import org.apache.http.HttpStatus; import java.util.HashMap; @@ -23,6 +24,8 @@ public class R extends HashMap { private boolean isSuccess; + private Tuple tuple; + public R() { put("code", 200); put("msg", "success"); @@ -45,6 +48,19 @@ public class R extends HashMap { return r; } + + public R putObj(Tuple tuple) { + this.tuple = tuple; + return this; + } + + public static R ok(int code) { + R r = new R(); + r.put("code", code); + return r; + } + + public static R ok(String msg) { R r = new R(); r.put("msg", msg); diff --git a/src/main/java/com/lz/common/utils/TaskCommand.java b/src/main/java/com/lz/common/utils/TaskCommand.java new file mode 100644 index 00000000..0999d946 --- /dev/null +++ b/src/main/java/com/lz/common/utils/TaskCommand.java @@ -0,0 +1,60 @@ +package com.lz.common.utils; + + +import com.lz.common.cli.CliToken; +import com.lz.common.cli.CliTokens; +import com.lz.modules.app.utils.t.Tuple; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class TaskCommand { + + public static final String add = "add"; + public static final String update = "update"; + public static final String list = "list"; + public static final String task = "task"; + public static final String record = "record"; + + public static List commandCommands = new ArrayList(Arrays.asList(new String[]{"add","update","list"})); + + public static List optTargets = new ArrayList(Arrays.asList(new String[]{"task", "record"})); + + + public static Tuple parse(String command) { + String[] tokens = getTokens(command); + if (commandCommands.contains(tokens[0])) { + return new Tuple(488, "命令的第一个参数必需是 add or update or list"); + } + if (optTargets.contains(tokens[1])) { + return new Tuple(488, "命令的第二个参数必需是 task or record"); + } + if (task.equals(tokens[1])) { //表示对 task 增删改查 + + } else if (record.equals(tokens[1])) { //表示对 list 增删改查 + + } + return new Tuple(); + } + + + public static String [] getTokens(String command) { + List tokenList = new ArrayList<>(); + List tokens = CliTokens.tokenize(command); + for (int i = 0; i < tokens.size(); i++) { + tokenList.add(tokens.get(i).value()); + } + return tokenList.toArray(new String[tokenList.size()]); + } + + @Test + public void test11() { + String ln = " abcdef b csssss dddddd -c \"b ccc ' bb a , bb x b\" a "; + List tokens = CliTokens.tokenize(ln); + for (int i = 0; i < tokens.size(); i++) { + System.out.println(tokens.get(i).value()); + } + } +} diff --git a/src/main/java/com/lz/config/ShiroConfig.java b/src/main/java/com/lz/config/ShiroConfig.java index eb62fd20..08bbc15d 100644 --- a/src/main/java/com/lz/config/ShiroConfig.java +++ b/src/main/java/com/lz/config/ShiroConfig.java @@ -55,6 +55,7 @@ public class ShiroConfig { filterMap.put("/dingding/**", "anon"); filterMap.put("/file/**", "anon"); filterMap.put("/test/**", "anon"); + filterMap.put("/third/**", "anon"); filterMap.put("/druid/**", "anon"); filterMap.put("/app/**", "anon"); filterMap.put("/sys/login", "anon"); diff --git a/src/main/java/com/lz/modules/app/controller/DepartmentsController.java b/src/main/java/com/lz/modules/app/controller/DepartmentsController.java index 38cfe697..d8609ba8 100644 --- a/src/main/java/com/lz/modules/app/controller/DepartmentsController.java +++ b/src/main/java/com/lz/modules/app/controller/DepartmentsController.java @@ -49,8 +49,6 @@ public class DepartmentsController { return R.ok().put("data", departmentList); } - - /** * 信息 */ diff --git a/src/main/java/com/lz/modules/app/controller/ThirdTaskController.java b/src/main/java/com/lz/modules/app/controller/ThirdTaskController.java new file mode 100644 index 00000000..271d75c5 --- /dev/null +++ b/src/main/java/com/lz/modules/app/controller/ThirdTaskController.java @@ -0,0 +1,101 @@ +package com.lz.modules.app.controller; + +import com.lz.common.constant.CacheConstants; +import com.lz.common.utils.Md5Utils; +import com.lz.common.utils.R; +import com.lz.common.utils.RedisCacheUtil; +import com.lz.common.utils.RedisUtils; +import com.lz.modules.app.dto.CommandDto; +import com.lz.modules.app.entity.StaffEntity; +import com.lz.modules.app.service.StaffService; +import com.lz.modules.sys.entity.SysUserEntity; +import com.lz.modules.sys.service.SysUserService; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.crypto.hash.Sha256Hash; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@RestController +@RequestMapping("third") +@Slf4j +public class ThirdTaskController { + + @Autowired + private RedisCacheUtil redisCacheUtil; + + @Autowired + private StaffService staffService; + + @Autowired + private SysUserService sysUserService; + + @RequestMapping("/handler") + public R handler(@RequestBody CommandDto command) { + SysUserEntity user = checkLogin(command.getToken()); + if (user == null) { + return R.error(499, "登陆己经过期"); + } + + log.info("command:" + command); + + + + List> data = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + List a = new ArrayList<>(); + for (int j = 0; j < 5; j++) { + a.add(j + ""); + } + data.add(a); + } + List header = new ArrayList<>(Arrays.asList(new String[]{"用户名", "密码", "哈哈", "双", "你是"})); + + + + + return R.ok().put("header", header).put("data", data); + } + + public SysUserEntity checkLogin(String token) { + Object object = redisCacheUtil.getObject(token); + if (object != null) { + return (SysUserEntity) object; + } + return null; + } + + @RequestMapping("/login") + public R login(@RequestBody CommandDto command) { + SysUserEntity user = sysUserService.queryByUserName(command.getUsername()); + if (user == null) { + StaffEntity staffEntity = staffService.selectByPhone(command.getUsername()); + if (staffEntity != null) { + user = new SysUserEntity(); + user.setPassword(staffEntity.getPassword()); + user.setMobile(staffEntity.getMobile()); + user.setUserId(staffEntity.getId()); + user.setEmail(staffEntity.getEmail()); + user.setSalt(staffEntity.getSalt()); + user.setStatus(1); + user.setType(1); + user.setUsername(staffEntity.getMobile()); + user.setRealName(staffEntity.getName()); + user.setUserNo(staffEntity.getMobile()); + } else { + return R.error("username 不存在!"); + } + } + if (!user.getPassword().equals(new Sha256Hash(command.getPassword(), user.getSalt()).toHex())) { + return R.error("password不正确!"); + } + String token = Md5Utils.toMD5(System.currentTimeMillis() + user.getUserId() + ""); + redisCacheUtil.saveObject(token, user, CacheConstants.SECOND_OF_HALF_HOUR); + return R.ok(token); + } +} diff --git a/src/main/java/com/lz/modules/app/dto/CommandDto.java b/src/main/java/com/lz/modules/app/dto/CommandDto.java new file mode 100644 index 00000000..0d26f407 --- /dev/null +++ b/src/main/java/com/lz/modules/app/dto/CommandDto.java @@ -0,0 +1,11 @@ +package com.lz.modules.app.dto; + +import lombok.Data; + +@Data +public class CommandDto { + private String command; + private String username; + private String password; + private String token; +} diff --git a/src/main/java/com/lz/modules/app/dto/RecordDto.java b/src/main/java/com/lz/modules/app/dto/RecordDto.java new file mode 100644 index 00000000..b733a5f8 --- /dev/null +++ b/src/main/java/com/lz/modules/app/dto/RecordDto.java @@ -0,0 +1,15 @@ +package com.lz.modules.app.dto; + +import com.lz.common.annotation.TaskHeader; +import lombok.Data; + +@Data +public class RecordDto { + @TaskHeader("索引") + private int index; + @TaskHeader("Id") + private Long id; + @TaskHeader("内容") + private String content; + +} diff --git a/src/main/resources/logback-dev.xml b/src/main/resources/logback-dev.xml index 7004bf98..bef79e60 100644 --- a/src/main/resources/logback-dev.xml +++ b/src/main/resources/logback-dev.xml @@ -3,7 +3,7 @@ - +