一、创建web项目

1、打开idea软件,点击界面上的Create New Project
image.png
2、进入如下界面。选中 java Enterprise,配置jdk,tomcat,勾选Web Application案例,注意勾选生成web.xml文件
image.png
image.png
image.png
image.png
3、指定项目的名称及项目文件的保存地址
image.png
4、创建成功
image.png
5、创建class文件和lib文件夹 点击项目的WEF-INF文件夹 ,右键,New → Directory 创建两个文件夹,classes(用来存放编译后输出的class文件) 和 lib(用于存放第三方jar包)
image.png
6、配置classes文件夹路径    File → 选择 Project Structure → 选择 Module → 选择Paths →
选择 “Use module compile output path” ->
将Output path和Test output path都选择刚刚创建的classes文件夹。
image.png
智能客服自动回复 - 图10
7、配置lib文件夹路径   点击Paths旁边的Dependencies 点击右边的”+”号 → 选择”Jars or Directories” -> 将Output path和Test output path都选择刚刚创建的classes文件夹 → 选择”Jar Directory” 然后一路OK就行了.
image.png
选择刚刚创建的lib文件夹
image.png
image.png

二、tomcat项目部署

1.配置tomcat 点击Run ,选择Edit Configurations.
image.png
智能客服自动回复 - 图15
点击右上角的三角形,运行
智能客服自动回复 - 图16
智能客服自动回复 - 图17

三、创建servlet

src–>New–>Create New Servlet
智能客服自动回复 - 图18
智能客服自动回复 - 图19
servlet中简单代码

  1. /**
  2. * 通过urlPatterns指定映射地址或者在web.xml文件中配置
  3. */
  4. @WebServlet(name = "helloServlet",urlPatterns = {"/hello"})
  5. public class HelloServlet extends HttpServlet {
  6. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  7. throws ServletException, IOException {
  8. }
  9. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  10. throws ServletException, IOException {
  11. System.out.println("hello serlvet");
  12. request.getRequestDispatcher("/index.jsp").forward(request,response);
  13. }
  14. }

3.测试 运行tomcat访问测试:http://localhost:8080/hello
智能客服自动回复 - 图20
智能客服自动回复 - 图21

四、页面图片准备

1.同一放在web文件夹下 格式如下
image.png
2.lib的导入
image.png
3.代码实现

  1. public class Robot {
  2. private String url;
  3. private String apiKey;
  4. private String userId;
  5. public Robot() {
  6. }
  7. public Robot(String url, String apiKey) {
  8. this.url = url;
  9. this.apiKey = apiKey;
  10. }
  11. public String getUrl() {
  12. return url;
  13. }
  14. public void setUrl(String url) {
  15. this.url = url;
  16. }
  17. public String getApiKey() {
  18. return apiKey;
  19. }
  20. public void setApiKey(String apiKey) {
  21. this.apiKey = apiKey;
  22. }
  23. public String getUserId() {
  24. return userId;
  25. }
  26. public void setUserId(String userId) {
  27. this.userId = userId;
  28. }
  29. //处理请求信息
  30. private String before(String msg) {
  31. //请求参数格式为 json
  32. /**
  33. * reqType; 输入类型:0-文本(默认)、1-图片、2-音频
  34. * perception 输入信息
  35. * userInfo 用户参数
  36. * inputText 文本信息
  37. * selfInfo 客户端属性
  38. * location 地理位置信息
  39. * city 所在城市
  40. * province 省份
  41. * street 街道
  42. * apiKey 机器人标识
  43. * userId 用户唯一标识
  44. *
  45. * */
  46. return "{'reqType':0,'" +
  47. "perception':{'inputText':{'text':" + msg + "}," +
  48. "'selfInfo':{'location':{'city':\"北京\",'province':\"北京\",'street':\"信息路\"}}}," +
  49. "'userInfo':{'apiKey':" + this.getApiKey() + ",'userId':'" + this.getUserId() + "'}}";
  50. }
  51. //聊天
  52. public String Chat(String msg) {
  53. //JSON字符串转JSONObject对象
  54. JSONObject jsonObject = JSONUtil.parseObj(before(msg));
  55. //Http请求类用于构建Http请求并同步获取结果,此类通过CookieManager持有域名对应的Cookie值,再次请求时会自动附带Cookie信息
  56. //Rest模式,此时body需要传入一个JSON或者XML字符串,Hutool会自动绑定其对应的Content-Type
  57. //传入路径与我们传入的JSONObject对象,获取请求响应的结果
  58. String result2 = HttpRequest.post(this.getUrl()).body(jsonObject.toString()).timeout(20000).execute().body();
  59. //JSON字符串转JSONObject对象 然后得到结果 转化成string
  60. return JSONUtil.parseObj(result2).get("results").toString(); //获取返回的结果信息
  61. }
  62. }
  1. @WebServlet(name = "sentServlet", urlPatterns = "/sent/chat")
  2. public class SentMassage extends HttpServlet {
  3. public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  4. doGet(request, response);
  5. }
  6. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  7. response.setCharacterEncoding("utf-8");
  8. response.setCharacterEncoding("utf-8");
  9. response.setContentType("application/json;charset=utf-8");
  10. String inputText = request.getParameter("inputText");
  11. System.out.println(inputText);
  12. Robot robot = new Robot();
  13. robot.setUrl(Changeless.URL);
  14. robot.setApiKey(Changeless.API_ID_2);
  15. robot.setUserId(Changeless.USER_ID);
  16. JSONArray objects = JSONUtil.parseArray(robot.Chat(inputText));
  17. ArrayList<JSONObject> jsonObjectArrayLists = new ArrayList<>();
  18. for (Object jsonObject : objects) {
  19. jsonObjectArrayLists.add((JSONObject) JSONUtil.parseObj(jsonObject).get("values"));
  20. }
  21. System.out.println(jsonObjectArrayLists);
  22. /*将list集合转成json*/
  23. String result = JSONUtil.parseArray(JSON.toJSONString(jsonObjectArrayLists)).toString();
  24. /*返回数据*/
  25. response.getWriter().write(result);
  26. }
  27. }

五、Java基础代码实现

  1. public class TestRobot {
  2. public static void main(String[] args) throws Exception {
  3. Scanner sc = new Scanner(System.in);
  4. while (true) {
  5. String our = sc.nextLine();
  6. String result = getChat(our);
  7. System.out.println("机器人:" + result);
  8. }
  9. }
  10. public static String getChat(String result) throws Exception {
  11. // 请求URL
  12. //afccb0beff0d4d12a45f3d25ced655db
  13. //597b34bea4ec4c85a775c469c84b6817
  14. String url = "http://openapi.tuling123.com/openapi/api/v2";
  15. // 图灵机器人API接口 每天只能5000次调用,建议自己去申请一个,免费的:)
  16. String apiKey = "597b34bea4ec4c85a775c469c84b6817";
  17. // 请求参数
  18. Map<String, Object> paramMap = new HashMap<>();
  19. paramMap.put("reqType", "0"); // 输入类型:0-文本(默认)、1-图片、2-音频
  20. // 输入信息
  21. Map<String, Object> perception = new HashMap<>();
  22. Map<String, String> inputText = new HashMap<>();
  23. inputText.put("text", result);
  24. Map<String, Object> selfInfo = new HashMap<>();
  25. Map<String, String> location = new HashMap<>();
  26. location.put("city", "北京");
  27. location.put("province", "北京");
  28. location.put("street", "建材城西路");
  29. selfInfo.put("location", location);
  30. perception.put("inputText", inputText);
  31. perception.put("selfInfo", selfInfo);
  32. // 用户信息
  33. Map<String, String> userInfo = new HashMap<>();
  34. userInfo.put("apiKey", apiKey);
  35. userInfo.put("userId", "123456");
  36. paramMap.put("perception", perception);
  37. paramMap.put("userInfo", userInfo);
  38. // 把map参数,转成json
  39. String jsonData = JSONUtil.toJSON(paramMap);
  40. // System.out.println("jsonData:" + jsonData);
  41. String r2 = HttpUtil.post(url,null,jsonData);
  42. return getResult(r2, "results");
  43. }
  44. // {"intent":{"actionName":"","code":10020,"intentName":""},"results":[{"groupType":1,"resultType":"text","values":{"text":"你好"}}]}
  45. private static String getResult(String json, String key) {
  46. List<String> list = JSONUtil.getList(json, key, String.class);
  47. String result = list.get(0);
  48. String values = JSONUtil.getString(result, "values");
  49. String text = JSONUtil.getString(values, "text");
  50. return text;
  51. }
  52. }

五、客户端与服务器

15.6.4 示例一:单个客户端与服务器单次通信

需求:客户端连接服务器,连接成功后给服务发送“lalala”,服务器收到消息后,给客户端返回“欢迎登录”,客户端接收消息后,断开连接

客户端示例代码

  1. import java.io.InputStream;
  2. import java.io.OutputStream;
  3. import java.net.Socket;
  4. public class Client {
  5. public static void main(String[] args) throws Exception {
  6. // 1、准备Socket,连接服务器,需要指定服务器的IP地址和端口号
  7. Socket socket = new Socket("127.0.0.1", 8888);
  8. // 2、获取输出流,用来发送数据给服务器
  9. OutputStream out = socket.getOutputStream();
  10. // 发送数据
  11. out.write("lalala".getBytes());
  12. //会在流末尾写入一个“流的末尾”标记,对方才能读到-1,否则对方的读取方法会一致阻塞
  13. socket.shutdownOutput();
  14. //3、获取输入流,用来接收服务器发送给该客户端的数据
  15. InputStream input = socket.getInputStream();
  16. // 接收数据
  17. byte[] data = new byte[1024];
  18. StringBuilder s = new StringBuilder();
  19. int len;
  20. while ((len = input.read(data)) != -1) {
  21. s.append(new String(data, 0, len));
  22. }
  23. System.out.println("服务器返回的消息是:" + s);
  24. //4、关闭socket,不再与服务器通信,即断开与服务器的连接
  25. //socket关闭,意味着InputStream和OutputStream也关闭了
  26. socket.close();
  27. }
  28. }

服务器端示例代码

  1. import java.io.InputStream;
  2. import java.io.OutputStream;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. public class Server {
  6. public static void main(String[] args)throws Exception {
  7. //1、准备一个ServerSocket对象,并绑定8888端口
  8. ServerSocket server = new ServerSocket(8888);
  9. System.out.println("等待连接....");
  10. //2、在8888端口监听客户端的连接,该方法是个阻塞的方法,如果没有客户端连接,将一直等待
  11. Socket socket = server.accept();
  12. System.out.println("一个客户端连接成功!!");
  13. //3、获取输入流,用来接收该客户端发送给服务器的数据
  14. InputStream input = socket.getInputStream();
  15. //接收数据
  16. byte[] data = new byte[1024];
  17. StringBuilder s = new StringBuilder();
  18. int len;
  19. while ((len = input.read(data)) != -1) {
  20. s.append(new String(data, 0, len));
  21. }
  22. System.out.println("客户端发送的消息是:" + s);
  23. //4、获取输出流,用来发送数据给该客户端
  24. OutputStream out = socket.getOutputStream();
  25. //发送数据
  26. out.write("欢迎登录".getBytes());
  27. out.flush();
  28. //5、关闭socket,不再与该客户端通信
  29. //socket关闭,意味着InputStream和OutputStream也关闭了
  30. socket.close();
  31. //6、如果不再接收任何客户端通信,可以关闭ServerSocket
  32. server.close();
  33. }
  34. }

15.6.5 示例二:多个客户端与服务器之间的多次通信

通常情况下,服务器不应该只接受一个客户端请求,而应该不断地接受来自客户端的所有请求,所以Java程序通常会通过循环,不断地调用ServerSocket的accept()方法。

如果服务器端要“同时”处理多个客户端的请求,因此服务器端需要为每一个客户端单独分配一个线程来处理,否则无法实现“同时”。

咱们之前学习IO流的时候,提到过装饰者设计模式,该设计使得不管底层IO流是怎样的节点流:文件流也好,网络Socket产生的流也好,程序都可以将其包装成处理流,甚至可以多层包装,从而提供更多方便的处理。

案例需求:多个客户端连接服务器,并进行多次通信

  • 每一个客户端连接成功后,从键盘输入英文单词或中国成语,并发送给服务器
  • 服务器收到客户端的消息后,把词语“反转”后返回给客户端
  • 客户端接收服务器返回的“词语”,打印显示
  • 当客户端输入“stop”时断开与服务器的连接
  • 多个客户端可以同时给服务器发送“词语”,服务器可以“同时”处理多个客户端的请求

客户端示例代码

  1. import java.io.BufferedReader;
  2. import java.io.InputStream;
  3. import java.io.InputStreamReader;
  4. import java.io.OutputStream;
  5. import java.io.PrintStream;
  6. import java.net.Socket;
  7. import java.util.Scanner;
  8. public class Client2 {
  9. public static void main(String[] args) throws Exception {
  10. // 1、准备Socket,连接服务器,需要指定服务器的IP地址和端口号
  11. Socket socket = new Socket("127.0.0.1", 8888);
  12. // 2、获取输出流,用来发送数据给服务器
  13. OutputStream out = socket.getOutputStream();
  14. PrintStream ps = new PrintStream(out);
  15. // 3、获取输入流,用来接收服务器发送给该客户端的数据
  16. InputStream input = socket.getInputStream();
  17. BufferedReader br = new BufferedReader(new InputStreamReader(input));
  18. Scanner scanner = new Scanner(System.in);
  19. while(true){
  20. System.out.println("输入发送给服务器的单词或成语:");
  21. String message = scanner.nextLine();
  22. if(message.equals("stop")){
  23. socket.shutdownOutput();
  24. break;
  25. }
  26. // 4、 发送数据
  27. ps.println(message);
  28. // 接收数据
  29. String feedback = br.readLine();
  30. System.out.println("从服务器收到的反馈是:" + feedback);
  31. }
  32. //5、关闭socket,断开与服务器的连接
  33. scanner.close();
  34. socket.close();
  35. }
  36. }

服务器端示例代码

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.PrintStream;
  5. import java.net.ServerSocket;
  6. import java.net.Socket;
  7. public class Server2 {
  8. public static void main(String[] args) throws IOException {
  9. // 1、准备一个ServerSocket
  10. ServerSocket server = new ServerSocket(8888);
  11. System.out.println("等待连接...");
  12. int count = 0;
  13. while(true){
  14. // 2、监听一个客户端的连接
  15. Socket socket = server.accept();
  16. System.out.println("第" + ++count + "个客户端"+socket.getInetAddress().getHostAddress()+"连接成功!!");
  17. ClientHandlerThread ct = new ClientHandlerThread(socket);
  18. ct.start();
  19. }
  20. //这里没有关闭server,永远监听
  21. }
  22. static class ClientHandlerThread extends Thread{
  23. private Socket socket;
  24. public ClientHandlerThread(Socket socket) {
  25. super();
  26. this.socket = socket;
  27. }
  28. public void run(){
  29. try{
  30. //(1)获取输入流,用来接收该客户端发送给服务器的数据
  31. BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  32. //(2)获取输出流,用来发送数据给该客户端
  33. PrintStream ps = new PrintStream(socket.getOutputStream());
  34. String str;
  35. // (3)接收数据
  36. while ((str = br.readLine()) != null) {
  37. //(4)反转
  38. StringBuilder word = new StringBuilder(str);
  39. word.reverse();
  40. //(5)返回给客户端
  41. ps.println(word);
  42. }
  43. System.out.println(socket.getInetAddress().getHostAddress()+"正常退出");
  44. }catch(Exception e){
  45. System.out.println(socket.getInetAddress().getHostAddress()+"意外退出");
  46. }finally{
  47. try {
  48. //(6)断开连接
  49. socket.close();
  50. } catch (IOException e) {
  51. e.printStackTrace();
  52. }
  53. }
  54. }
  55. }
  56. }