在线翻译

1 需求分析

前端页面选择语言,输入文字,发送给服务器端,服务器端调用翻译 API 接口,将翻译结果传递至前端页面进行显示。

1.1 前端界面案例

1.2 参考资料

有道翻译 API:http://fanyi.youdao.com/openapi

百度翻译 API:https://api.fanyi.baidu.com/

1.3 各项功能

1.3.1 下拉菜单

下拉菜单的选项和个国语言的代码都是在页面加载的时候向后端发起请求,在数据中查找的,都是动态生成的。

1.3.2 翻译

当输入中文时,可以点击不同的选项,翻译为对应的语言。

例如:

中文 == 英文

中文 == 日文

2 系统设计

2.1 用户用例图

页面加载,初始化下拉菜单。

用户点击翻译按钮,发送请求获取翻译信息

图 2-1 用户用例图

2.2 ER 图

数据库设计 1 张表,语言表,对应的 ER 图如图 3-1 所示。

LangName:语言名字

LangCode: 语言代码(对应百度 AP)

图 3-1 数据库 ER 图

2.3 UML 类图(Class Diagram)

对于翻译功能模块,共设计如下 6 个类。

Entity 实体类 Lang.java:与数据库结构进行映射的类。主要由属性,setter, getter 方法组成,Entity 类中的属性与表中的字段相对应,每一个 Entity 类的对象都表示表中的每一条记录

pojo 对象类:
·Trans.java 为用户的翻译值对象,属性 query,from,to,分别表示请求翻译,翻译源语言,翻译目标语言。
·TransData.java:为值对象,属性 ser,dst,为原文与译文
·TransResult.java:为值对象,里面包含 TransData.java,从 API 请求的内容要用此对象存

Mapper 接口 LangMapper.java:主要定义操作的接口,定义一系列数据库的原子性操作,例如增删改查(通常称为 CRUD)等。

Serivce 层:主要处理业务逻辑,对于数据层的原子操作进行整合。在 TransService 里面调用百度 API 接口。

Controller 层:前端控制器,里面都是前需要请求调用的接口,主要包括前端下拉菜单的请求接口和前端翻译按钮的点击事件请求。

各类的结构及类之间的关系如图 2-5 所示:

图 2-5 翻译功能类图

2.4 UML 时序图(Sequence Diagram)

2.4.1 翻译

2.4.2 模块

每个功能按编号往后递增绘图

2.4.3 模块

每个功能按编号往后递增绘图

3 系统实现

3.1 项目结构

3.2 百度 API

在项目下新建 Source Folder,名为 resources

3.2.1 百度 API 相关

TransApi.java

@Component
public class TransApi {private static final String TRANS_API_HOST = "http://api.fanyi.baidu.com/api/trans/vip/translate";private static String appid = "20201213000646199";private static String securityKey = "qgXPVgAa6onAAbtZ5NjP";public TransApi(){}public TransApi(String appid, String securityKey) {this.appid = appid;this.securityKey = securityKey;}/*** 获得翻译结果* @param query* @param from* @param to* @return*/public String getTransResult(String query, String from, String to) throws IOException {Map<String, String> params = buildParams(query, from, to);JSONObject jsonObject = null;//当请求翻译内容过长 用postif (query.length() >= 2000){//post请求方式jsonObject = HttpUtil.doPostStr(TRANS_API_HOST, params);}else {//get请求方式String url = getUrlWithQueryString(TRANS_API_HOST, params);jsonObject = HttpUtil.doGetStr(url);}if (jsonObject.get("error_code")!=null) {return "翻译失败,原因:"+jsonObject.get("error_msg");}else{TransResult transResult = JSON.parseObject(jsonObject.toString(), TransResult.class);String s = JSON.toJSONString(transResult);return s;
//            System.out.println("transResult:"+s);
//            return " 翻译结果 "+transResult.getTrans_result().get(0).getDst();}}/*** 构建参数map** @param query* @param from* @param to* @return* @throws UnsupportedEncodingException*/private static Map<String, String> buildParams(String query, String from, String to){Map<String, String> params = new HashMap<String, String>();params.put("q", query);params.put("from", from);params.put("to", to);params.put("appid", appid);// 随机数String salt = String.valueOf(System.currentTimeMillis());params.put("salt", salt);// 签名String src = appid + query + salt + securityKey; // 加密前的原文params.put("sign", MD5.md5(src));return params;}/*** 拼接url get方式拼接参数  返回url** @param url* @param params* @return*/public static String getUrlWithQueryString(String url, Map<String, String> params) {if (params == null) {return url;}StringBuilder builder = new StringBuilder(url);if (url.contains("?")) {builder.append("&");} else {builder.append("?");}int i = 0;for (String key : params.keySet()) {String value = params.get(key);if (value == null) { // 过滤空的keycontinue;}if (i != 0) {builder.append('&');}builder.append(key);builder.append('=');builder.append(encode(value));i++;}return builder.toString();}/*** 对输入的字符串进行URL编码, 即转换为%20这种形式** @param input 原文* @return URL编码. 如果编码失败, 则返回原文*/public static String encode(String input) {if (input == null) {return "";}try {return URLEncoder.encode(input, "utf-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return input;}
}

MD5.java

/*** MD5编码相关的类* * @author wangjingtao* */
public class MD5 {// 首先初始化一个字符数组,用来存放每个16进制字符private static final char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd','e', 'f' };/*** 获得一个字符串的MD5值* * @param input 输入的字符串* @return 输入字符串的MD5值* @throws UnsupportedEncodingException * */public static String md5(String input){if (input == null)return null;try {// 拿到一个MD5转换器(如果想要SHA1参数换成”SHA1”)MessageDigest messageDigest = MessageDigest.getInstance("MD5");// 输入的字符串转换成字节数组byte[] inputByteArray = input.getBytes(StandardCharsets.UTF_8);// inputByteArray是输入字符串转换得到的字节数组messageDigest.update(inputByteArray);// 转换并返回结果,也是字节数组,包含16个元素byte[] resultByteArray = messageDigest.digest();// 字符数组转换成字符串返回return byteArrayToHex(resultByteArray);} catch (NoSuchAlgorithmException e) {return null;}}/*** 获取文件的MD5值* * @param file* @return*/public static String md5(File file) {try {if (!file.isFile()) {System.err.println("文件" + file.getAbsolutePath() + "不存在或者不是文件");return null;}FileInputStream in = new FileInputStream(file);String result = md5(in);in.close();return result;} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}public static String md5(InputStream in) {try {MessageDigest messagedigest = MessageDigest.getInstance("MD5");byte[] buffer = new byte[1024];int read = 0;while ((read = in.read(buffer)) != -1) {messagedigest.update(buffer, 0, read);}in.close();String result = byteArrayToHex(messagedigest.digest());return result;} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}private static String byteArrayToHex(byte[] byteArray) {// new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))char[] resultCharArray = new char[byteArray.length * 2];// 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去int index = 0;for (byte b : byteArray) {resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];resultCharArray[index++] = hexDigits[b & 0xf];}// 字符数组组合成字符串返回return new String(resultCharArray);}}

HttpUtil.java

/*** 请求工具类*/
public class HttpUtil {/***  get 请求* @param url* @return* @throws IOException*/public static JSONObject doGetStr(String url) throws IOException {CloseableHttpClient httpClient = HttpClients.createDefault();HttpGet httpGet = new HttpGet(url);CloseableHttpResponse response = httpClient.execute(httpGet);HttpEntity entity = response.getEntity();if (entity != null) {String content = EntityUtils.toString(entity,StandardCharsets.UTF_8) ;return JSONObject.parseObject(content);}return null;}/*** post 请求 String装填* @param url* @param reqContent* @return* @throws IOException*/public static JSONObject doPostStr(String url,String reqContent) throws IOException {CloseableHttpClient httpClient = HttpClients.createDefault();HttpPost httpPost = new HttpPost(url);if (!StringUtils.isEmpty(reqContent)) {httpPost.setEntity(new StringEntity(reqContent,"UTF-8"));}CloseableHttpResponse response = httpClient.execute(httpPost);HttpEntity entity = response.getEntity();if (entity != null) {String resContent = EntityUtils.toString(entity,"UTF-8") ;return JSONObject.parseObject(resContent);}return null;}/*** post 请求 map装填* @param url* @param reqContent* @return* @throws IOException*/public static JSONObject doPostStr(String url,Map<String,String> reqContent) throws IOException {CloseableHttpClient httpClient = HttpClients.createDefault();HttpPost httpPost = new HttpPost(url);//装填参数List<NameValuePair> nvps = new ArrayList<NameValuePair>();if (reqContent != null) {for (Map.Entry<String, String> entry : reqContent.entrySet()) {nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));}}//设置参数到请求对象中httpPost.setEntity(new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8));CloseableHttpResponse response = httpClient.execute(httpPost);HttpEntity entity = response.getEntity();if (entity != null) {String resContent = EntityUtils.toString(entity, StandardCharsets.UTF_8);return JSONObject.parseObject(resContent);}return null;}
}

3.3 common(公共部分)相关

R.java(返回结果集)

描述该文件作用,并对里面的配置进行解释

/*** 这里我们用到了一个R的类,这个用于我们的异步统一返回的结果封装。* 一般来说,结果里面有几个要素必要的* <p>* 是否成功,可用code表示(如200表示成功,400表示异常)* 结果消息* 结果数据*/
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class R implements Serializable {private int code; //200是正常  非200表示异常private String msg;private Object data;public static R succ(Object data) {R r = new R().setCode(200).setData(data).setMsg("操作成功");return r;}public static R succ(String msg,Object data) {R r = new R().setCode(200).setData(data).setMsg(msg);return r;}public static R succ(int code,String msg, Object data){R r = new R().setCode(code).setData(data).setMsg(msg);return r;}public static R fail(String msg) {R r = new R().setCode(-1).setData(null).setMsg(msg);return r;}public static R fail(String msg,Object data) {R r = new R().setCode(-1).setData(data).setMsg(msg);return r;}public static R fail(int i, String message, Object data) {R r = new R().setCode(i).setData(data).setMsg(message);return r;}
}

3.4 JavaConfig 相关

描述该文件作用,并对里面的配置进行解释

MybatisPlusConfig.java

@Configuration
@EnableTransactionManagement // 开启事务管理
@MapperScan("com.shm.mapper")
public class MybatisPlusConfig {}

swaggerConfig.java

@Configuration
@EnableSwagger2
public class swaggerConfig {@Beanpublic ApiInfo apiInfo(){//作者信息Contact contact = new Contact("小明", "", "862924968@qq.com");return new ApiInfo("SwaggerAPI文档","小明学长","1.0","urn:tos",contact,null,null,new ArrayList<VendorExtension>());}
}

3.5 application.yml 配置

描述该文件作用,并对里面的关键代码进行解释

# 配置数据源
spring:application:name: mybatis-plusdatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/translate-api?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghaiusername: rootpassword: root
# mybatis 配置
mybatis-plus:mapper-locations: classpath:mapper/*.xmlconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志实现类map-underscore-to-camel-case: true                     # 驼峰转换type-aliases-package: com.shm.entity

3.6 实体类相关

Lang.java

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_lang")
public class Lang implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;@TableField("langName")private String langName;@TableField("langCode")private String langCode;}

Trans.java:

描述该文件作用,并对里面的关键代码进行解释

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Trans {private String query;private String from;private String to;
}

transData.java:

描述该文件作用,并对里面的关键代码进行解释

@Data
public class TransData {/*** 原文*/private String src;/*** 译文*/private String dst;
}

TransResult.java:

@Data
public class TransResult {/***翻译源语言*/private String from;/***译文语言*/private String to;/***翻译结果*/private List<TransData> trans_result;
}

3.6 Mapper 接口与 Mapper.xml

描述该文件作用,并对里面的关键代码进行解释

这里我使用的是 Mybatis-plus ,基本的 CRUD 都不用自己手写,所以文件里面是空的,但是不可以没有。

LanngMapper.java

public interface LangMapper extends BaseMapper<Lang> {}

LangMapper.xml

<?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.shm.mapper.LangMapper"></mapper>

3.7 Serivce 接口与实现

LangService.java

public interface LangService extends IService<Lang> {}

LangServiceImpl.java

@Service
public class LangServiceImpl extends ServiceImpl<LangMapper, Lang> implements LangService {}

TrangService.java

@Service
public class TransService {@AutowiredTransApi transApi;public TransResult result(Trans trans) {TransResult transResult = null;try {String str = transApi.getTransResult(trans.getQuery(), trans.getFrom(), trans.getTo());System.*out*.println(str);transResult = JSON.*parseObject*(str, TransResult.class);} catch (IOExceptioe) {e.printStackTrace();}returtransResult;}
}

3.8 Controller 控制器层

LangController.java

@RestController
@RequestMapping("/lang")
@CrossOrigin
public class LangController {@Autowiredprivate LangService langService;/*** 获取全部语言名称与代码* @return*/@GetMapping("all")public R langAll(){List<Lang> langs = langService.getBaseMapper().selectList(null);return R.succ(200,"操作成功",langs);}}

TranslateController.java

@RestController
@RequestMapping("/lang")
@CrossOrigin
public class LangController {@Autowiredprivate LangService langService;/*** 获取全部语言名称与代码* @return*/@GetMapping("all")public R langAll(){List<Lang> langs = langService.getBaseMapper().selectList(null);return R.succ(200,"操作成功",langs);}}

3.8 用户界面 vue.js

描述该文件作用,并对里面的关键代码进行解释

<script>let vue = new Vue({el:'#app',data:{/* 翻译处理query: 被翻译的内容from:语言本来类型to: 要翻译的类型*/trans:{query: '',from: 'auto',to:'en'},/*  */text: '',btn_group: '中文 == 英语',langs:[],textVal: 0},methods:{/* 获取翻译内容 */translate(){if(this.trans.query == null || this.trans.query === ''){alert('请输入翻译内容')}else{axios.post('http://localhost:8080/trans',this.trans).then(response=>{this.text = response.data.data.trans_result[0].dst}).catch(error=>{alert('发生未知错误!'+error )this.text=''})}},/* 页面加载时,获取数据库内容 */getLang(){const _this = thisaxios.get('http://localhost:8080/lang/all').then(res=>{//赋值this.langs = res.data.data}).catch(error=>{console.log('发生未知错误!'+error)this.text=''})},/* 获取下拉框信息 */getLangCode(code){this.btn_group = '中文 ==' + code.langNamethis.trans.to = code.langCode}},created() {this.getLang()}})
</script>

4 系统测试

设计测试用例,给出程序每个功能模块的运行结果截图。

5 系统总结

主要问题的解决过程、系统存在的不足,本门课程的收获,课程的建议,以后的发展方向,自评成绩。

主要是前端的问题,对于前端 bootStrop,Vue.js 运用还是有些生疏,请求到数据之后,对于数据在页面上的渲染,还有数据在 js 里面使用存在一些问题。

目前此系统的下拉菜单只显示中文转换为其他国家的语言,但是默认我是使用的自动检测语言,在不点击下拉框的情况下,只要是百度 API 上面有的语言都能转换为英文,但是点击了之后,在 vue 里面我把自动检测语言的默认值替代了,我没有在数据库里面加自动检测的代码,默认值我是写在 vue 里面写死的,这是问题之一。

下拉菜单还有一个问题,在页面加载的时候就会像服务器发送请求,然后去数据库中进行查询,如果频繁的刷新页面的时候,就会频繁的对数据库进行操纵,这无疑加大了开销。其实针对此问题我已经想到了解决方案:我们可以把菜单数据从数据库读取之后存到 Redis 缓存中,我们发出请求操作的时候,直接对缓存进行操作,然后设置 Spring boot 定时任务,定期的在数据中查找数据,存入 Redis。这样大大的减少了服务器的开销。

还有就是此项目数据前后端分离项目,其实只能算是半个,对于跨域的问题,我也只是一知半解,这个问题发生的时候我没有查资料,以为是请求有问题,一直报错。之后我查阅资料之后,有几套解决问题的方案,时间关系我用的是最简单的,在 controller 控制器中加入“@CrossOrigin”注解,然后请求就成功了,我对于这个原理还不是很懂。

前端项目我还不懂如何部署到 nginx 服务器上面。

上面的两个问题,由于时间和技术的关系,目前还没有实施在项目中,只是有了大概的思路。在后续我一定多多补充这方面知识。

以后我会主要学习 Spring boot 相关内容,传统的 SSM 也像之前的 SSH 一样,会过时。JSP 也过时了,可以使用 thymeleaf 模板引擎替代 JSP 模板。其实对于前后端分离和跟 vue.js 集成效果最好的还是使用 vue cli,后面我也会重点学习的。还有 Java 基础部分,很多都忘了,例如反射,线程,网络编程,IO,也需要补。

♻️ 资源

大小: 1.55MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87404249

基于Java实现在线翻译【100010578】相关推荐

  1. 基于JAVA彩票在线购买系统计算机毕业设计源码+系统+lw文档+部署

    基于JAVA彩票在线购买系统计算机毕业设计源码+系统+lw文档+部署 技术栈 项目架构:B/S架构 开发语言:Java语言 开发软件:idea eclipse 前端技术:Layui.HTML.CSS. ...

  2. 基于Java毕业设计在线直播平台源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计在线直播平台源码+系统+mysql+lw文档+部署软件 基于Java毕业设计在线直播平台源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B/S架构 开发语言: ...

  3. 基于Java毕业设计在线交易系统源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计在线交易系统源码+系统+mysql+lw文档+部署软件 基于Java毕业设计在线交易系统源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B/S架构 开发语言: ...

  4. 基于Java毕业设计在线云音乐系统源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计在线云音乐系统源码+系统+mysql+lw文档+部署软件 基于Java毕业设计在线云音乐系统源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B/S架构 开发语 ...

  5. 基于java的在线考试系统设计(含源文件)

    欢迎添加微信互相交流学习哦! 项目源码:https://gitee.com/oklongmm/biye 摘 要 本系统是一个基于java的在线考试系统.它的用户由学生.教师和系统管理员组成.学生登陆系 ...

  6. linux(ubuntu)下基于java的在线音乐仿qq播放器,

    linux下基于java的在线音乐仿qq播放器,界面挺漂亮,界面全都是本人自己用java来画的,主要是我自己喜欢用ubuntu,但是由于没有人去做它的播放器,就自己来了,可以在线,有专辑图片,播放列表 ...

  7. 基于JAVA计算机在线学习管理系统-计算机毕业设计源码+系统+mysql数据库+lw文档+部署

    基于JAVA计算机在线学习管理系统-计算机毕业设计源码+系统+mysql数据库+lw文档+部署 基于JAVA计算机在线学习管理系统-计算机毕业设计源码+系统+mysql数据库+lw文档+部署 本源码技 ...

  8. 基于JAVA简易在线教学系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署

    基于JAVA简易在线教学系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署 基于JAVA简易在线教学系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署 本源码技术栈: 项目架构 ...

  9. 基于Java毕业设计在线玩具租赁系统源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计在线玩具租赁系统源码+系统+mysql+lw文档+部署软件 基于Java毕业设计在线玩具租赁系统源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B/S架构 开 ...

最新文章

  1. 【备忘1】防止表格/层 被撑破的CSS控制代码
  2. 欧几里得算法与唯一分解定理
  3. 《系统集成项目管理工程师》必背100个知识点-01项目特点
  4. LeetCode_97.交错字符串_没懂
  5. mysql解锁_mysql 解锁
  6. element ui 多个子组件_ElementUI 技术揭秘(2) 组件库的整体设计
  7. Android5.0水波纹效果ripple实现
  8. java 常用汉字_中国常用汉字有多少
  9. 你可能需要的各个行业年度总结 ppt 模板
  10. xp系统计算机启动时灰色界面,XP系统任务管理器是灰色的打不开怎么办
  11. DFS:拯救少林神棍(Sticks)[四轮剪枝操作]
  12. 计算机无法识别u盘,电脑无法读取u盘怎么处理_电脑不能读取u盘如何解决
  13. python最长的单词判断_Python 找出英文单词列表(list)中最长单词链
  14. 一文看尽 6篇 CVPR2021 伪装目标检测、旋转目标检测论文
  15. 用altium designer 如何按1:1比例输出PCB图?
  16. MCNP6中Fmesh卡使用简单感想
  17. Axon框架使用指南(二):入门
  18. MySQL中的LEFT JOIN ON (where)查询
  19. 数据分析中的哑变量问题,该怎么处理?
  20. ws550 第三方固件_华为WS550如何固件升级

热门文章

  1. linux VCS+verdi运行UVM实战(第二章)中的例子
  2. @angular/http和@angular/common/http 区别
  3. out了吧,这份最新阿里、腾讯、华为、字节跳动等大厂的薪资和职级对比,你都没看过?
  4. BZOJ 4888 [Tjoi2017] 异或和
  5. Fabric2.2 error 总结:WARN 0cf access denied: channel expected MSP ID Org1MSP, received Org3MSP channel
  6. 西藏春运送服务 让旅客带着温暖出发
  7. 对excel的完美操作
  8. FD650B数码管驱动
  9. 计算机专业所属院校,全国计算机专业强的大学院校盘点
  10. 基于CNI保护Kubernetes集群中的主机