SpringMVC+Maven开发最小“自然语言理解”项目攻略(附源码打包下载及详细说明)

来源:互联网 发布:克里斯 洛克 知乎 编辑:程序博客网 时间:2024/06/06 08:37
 

[置顶] SpringMVC+Maven开发最小“自然语言理解”项目攻略(附源码打包下载及详细说明)


Spring MVC概述

Spring MVC框架是一个开源的Java平台,为开发强大的基于Java的Web应用程序提供全面的基础架构支持非常容易和非常快速。

Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构和用于开发灵活和松散耦合的Web应用程序的组件。

MVC模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时提供这些元素之间的松散耦合。

  • 模型(Model)封装了应用程序数据,通常它们将由POJO类组成。

  • 视图(View)负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出。

  • 控制器(Controller)负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。

项目源码详细介绍

该项目实现了智能解析用户输入语句的语义,输出结果以JSON格式展示。 
源码下载:SpringMVCDemoNLI

1、 创建目录结构

创建一个Maven工程为:SpringMVCDemoNLI。下图为最终的目录结构:

2、 配置pom.xml

<?xml version="1.0"?><project    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"    xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">    <modelVersion>4.0.0</modelVersion>    <groupId>com.demo</groupId>    <artifactId>SpringMVCDemoNLI</artifactId>    <packaging>war</packaging>    <version>0.0.1-SNAPSHOT</version>    <name>SpringMVCDemoNLI Maven Webapp</name>    <url>http://maven.apache.org</url>    <properties>        <springframework.version>4.0.6.RELEASE</springframework.version>        <hibernate.validator.version>5.1.2.Final</hibernate.validator.version>        <javax.validation.version>1.1.0.Final</javax.validation.version>        <!-- 主要依赖库的版本定义 -->        <httpclient.version>4.5.3</httpclient.version>        <commons-lang3.version>3.5</commons-lang3.version>        <commons-codec.version>1.10</commons-codec.version>        <commons-logging.version>1.2</commons-logging.version>        <httpcore.version>4.4.6</httpcore.version>        <taglibs-standard.version>1.2.5</taglibs-standard.version>        <fastjson.version>1.2.34</fastjson.version>    </properties>    <dependencies>        <!-- Spring dependencies -->        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-core</artifactId>            <version>${springframework.version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-web</artifactId>            <version>${springframework.version}</version>        </dependency>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-webmvc</artifactId>            <version>${springframework.version}</version>        </dependency>        <!-- httpclient -->        <dependency>            <groupId>commons-codec</groupId>            <artifactId>commons-codec</artifactId>            <version>${commons-codec.version}</version>        </dependency>        <dependency>            <groupId>org.apache.commons</groupId>            <artifactId>commons-lang3</artifactId>            <version>${commons-lang3.version}</version>        </dependency>        <dependency>            <groupId>commons-logging</groupId>            <artifactId>commons-logging</artifactId>            <version>${commons-logging.version}</version>        </dependency>        <dependency>            <groupId>org.apache.httpcomponents</groupId>            <artifactId>httpcore</artifactId>            <version>${httpcore.version}</version>        </dependency>        <dependency>            <groupId>org.apache.httpcomponents</groupId>            <artifactId>httpclient</artifactId>            <version>${httpclient.version}</version>        </dependency>        <dependency>            <groupId>org.apache.httpcomponents</groupId>            <artifactId>httpmime</artifactId>            <version>${httpclient.version}</version>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>${fastjson.version}</version>        </dependency>        <!-- jsr303 validation dependencies -->        <dependency>            <groupId>javax.validation</groupId>            <artifactId>validation-api</artifactId>            <version>${javax.validation.version}</version>        </dependency>        <dependency>            <groupId>org.hibernate</groupId>            <artifactId>hibernate-validator</artifactId>            <version>${hibernate.validator.version}</version>        </dependency>        <!-- Servlet dependencies -->        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>javax.servlet-api</artifactId>            <version>3.1.0</version>        </dependency>        <dependency>            <groupId>javax.servlet.jsp</groupId>            <artifactId>javax.servlet.jsp-api</artifactId>            <version>2.3.1</version>        </dependency>        <dependency>            <groupId>javax.servlet</groupId>            <artifactId>jstl</artifactId>            <version>1.2</version>        </dependency>    </dependencies>    <build>        <defaultGoal>compile</defaultGoal>        <pluginManagement>            <plugins>                               <plugin>                    <groupId>org.apache.maven.plugins</groupId>                    <artifactId>maven-compiler-plugin</artifactId>                    <configuration>                        <source>1.7</source>                        <target>1.7</target>                    </configuration>                </plugin>            </plugins>        </pluginManagement>        <finalName>SpringMVCDemoNLI</finalName>    </build></project>

3、创建POJO/域对象

保存用户提交的数据,并使用验证注释验证属性。

package com.demo.model;import java.io.Serializable;import javax.validation.constraints.Size;public class CorpusInfo implements Serializable {    /**     *      */    private static final long serialVersionUID = 1L;    @Size(min=2, max=30)    private String corpus;    public String getCorpus() {        return corpus;    }    public void setCorpus(String corpus) {        this.corpus = corpus;    }    @Override    public String toString() {        return "";    }}

4、添加控制器

控制器处理GET和POST请求。

@Controller表明这个类是一个控制器在处理具有模式映射的@RequestMapping请求。这里使用 ‘/’, 它被作为默认的控制器。

方法inputCorpus注解为RequestMethod.GET服务默认是GET请求,并呈现包含空白表单的网页。

方法nliProcess注解为RequestMethod.POST服务处理表单提交POST请求。

@Valid要求spring来验证相关的对象(CorpusInfo)。

package com.demo.controller;import javax.validation.Valid;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.validation.BindingResult;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import com.demo.model.CorpusInfo;import com.demo.util.NLIProcess;@Controller@RequestMapping("/")public class DemoController {    private NLIProcess nli = new NLIProcess();    @RequestMapping(method = RequestMethod.GET)    public String inputCorpus(ModelMap model) {        CorpusInfo cinfo = new CorpusInfo();        model.addAttribute("cinfo", cinfo);        return "enroll";    }    @RequestMapping(method=RequestMethod.POST)    public String nliProcess(@Valid  @ModelAttribute("cinfo") CorpusInfo cinfo,            BindingResult result, ModelMap model) {        if (result.hasErrors()) {            return "enroll";        }        model.addAttribute("answer", nli.getAnswer(cinfo.getCorpus()));        return "success";    }}

nli.getAnswer(cinfo.getCorpus())实现语义解析,这里是使用的欧拉蜜开放平台智能语义解析。

package com.demo.util;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import org.apache.http.HttpEntity;import org.apache.http.NameValuePair;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;import com.alibaba.fastjson.JSONException;import com.alibaba.fastjson.JSONObject;public class NLIProcess {    private static final String url = "https://cn.olami.ai/cloudservice/api";    private static final String Appkey = "fcf20941682b494e9db8c23c14deeb74";    private static final String Appsecret = "1bcbbe1fb5924185a13c9b5f6d548ee0";    private static final String api = "nli";        private JSONObject process (String input) {        JSONObject NLIresult = new JSONObject();        List<NameValuePair> params = new ArrayList<NameValuePair>();        params.add(new BasicNameValuePair("appkey", Appkey));        params.add(new BasicNameValuePair("api", api));        long timestamp = Calendar.getInstance().getTimeInMillis();        params.add(new BasicNameValuePair("timestamp", String.valueOf(timestamp)));        params.add(new BasicNameValuePair("sign", generateSign(timestamp)));        JSONObject request = new JSONObject();        JSONObject data = new JSONObject();        try {            data.put("input_type", 0);            data.put("text", input);            request.put("data_type", "stt");            request.put("data", data);        } catch (JSONException e1) {            e1.printStackTrace();            return NLIresult;        }        params.add(new BasicNameValuePair("rq", request.toString()));        params.add(new BasicNameValuePair("cusid", "asdfghj"));        CloseableHttpClient httpclient = HttpClients.createDefault();        HttpPost httppost = new HttpPost(url);        try {            httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));            CloseableHttpResponse response = httpclient.execute(httppost);            try {                HttpEntity entity = response.getEntity();                if (entity != null) {                    String contnt = EntityUtils.toString(entity);                    NLIresult = JSONObject.parseObject(contnt);                }            } finally {                response.close();            }        } catch (Exception e) {            e.printStackTrace();            return NLIresult;        } finally {            try {                httpclient.close();            } catch (Exception e) {                e.printStackTrace();            }        }        return NLIresult;    }    private String generateSign(long timestamp) {        String sign = Appsecret + "api=" + api + "appkey=" + Appkey + "timestamp=" + timestamp + Appsecret;        return MD5String(sign);    }    public String MD5String(String str) {        try {            MessageDigest msgDigest = MessageDigest.getInstance("MD5");            msgDigest.reset();            msgDigest.update(str.getBytes("UTF-8"));            byte[] byteArrary = msgDigest.digest();            StringBuffer md5StrBuff = new StringBuffer();            for (int i = 0; i < byteArrary.length; i++) {                String tmp = Integer.toHexString(0xFF & byteArrary[i]);                if (tmp.length() == 1) {                    md5StrBuff.append(0).append(tmp);                } else {                    md5StrBuff.append(tmp);                }            }            return md5StrBuff.toString();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();            return null;        } catch (UnsupportedEncodingException e) {            e.printStackTrace();            return null;        }    }    public String getAnswer(String corpus){        if(corpus != null && !corpus.equals("")){            JSONObject jsObj = process(corpus);            return formatJson(jsObj);        }        return "请输入正确的语料!";    }    private static String appendJson(String str, int count) {        String retStr = "<br>";        for (int i = 0; i < count; i++) {            retStr += str;        }        return retStr;    }    /**     * 将json转成便于阅读的格式     * @param oldJson     * @return     */    public static String formatJson(JSONObject old) {        int i = 0;        String space = "&nbsp;&nbsp;";        String formatJson = "";        int indentCount = 0;        Boolean isStr = false;        String currChar = "";        String oldJson = old.toString();        for (i = 0; i < oldJson.length(); i++) {            currChar = oldJson.substring(i, i + 1);            switch (currChar) {            case "{":            case "[":                if (!isStr) {                    indentCount++;                    formatJson += currChar + appendJson(space, indentCount);                } else {                    formatJson += currChar;                }                break;            case "}":            case "]":                if (!isStr) {                    indentCount--;                    formatJson += appendJson(space, indentCount) + currChar;                } else {                    formatJson += currChar;                }                break;            case ",":                if (!isStr) {                    formatJson += "," + appendJson(space, indentCount);                } else {                    formatJson += currChar;                }                break;            case ":":                if (!isStr) {                    formatJson += ": ";                } else {                    formatJson += currChar;                }                break;            case " ":            case "\n":            case "\t":                if (isStr) {                    formatJson += currChar;                }                break;            case "\"":                if (i > 0 && !oldJson.substring(i - 1, i).equals("\\")) {                    isStr = !isStr;                }                formatJson += currChar;                break;            default:                formatJson += currChar;                break;            }        }        return formatJson;    }}

5、添加配置类

@Configuration指示该类包含注解为@Bean生产Bean管理是由Spring容器的一个或多个 bean 的方法。

@EnableWebMvc 等效于 mvc:annotation-driven 在XML文件中。

@ComponentScan 等效于 context:component-scan base-package=”…” 提供具有到哪里查找管理Spring beans/类。

方法ViewResolver 配置一个 ViewResolver 用来找出真正的视图。

方法 addResourceHandlers 配置 ResourceHandler 静态资源。例子中,将css文件放在 Web应用程序的 /static/css 目录中。

package com.demo.configuration;import org.springframework.context.MessageSource;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.support.ResourceBundleMessageSource;import org.springframework.web.servlet.ViewResolver;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import org.springframework.web.servlet.view.InternalResourceViewResolver;import org.springframework.web.servlet.view.JstlView;@Configuration@EnableWebMvc@ComponentScan(basePackages = "com.demo")public class DemoConfiguration extends WebMvcConfigurerAdapter {    @Bean    public ViewResolver viewResolver() {        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();        viewResolver.setViewClass(JstlView.class);        viewResolver.setPrefix("/WEB-INF/views/");        viewResolver.setSuffix(".jsp");        return viewResolver;    }    @Bean    public MessageSource messageSource() {        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();        messageSource.setBasename("messages");        return messageSource;    }    @Override    public void addResourceHandlers(ResourceHandlerRegistry registry) {        registry.addResourceHandler("/static/**").addResourceLocations("/static/");    }}

方法messageSource 配置消息包,以支持[国际化]消息属性文件。Spring 将搜索应用程序类路径中一个名为messages.properties文件:

Size.cinfo.corpus=corpus must be between {2} and {1} characters long

6、添加视图(JSP页面)

添加两个JSP页面。第一个将包含一个表单,从用户接收输入,第二个是当表单输入验证成功时会显示成功消息给用户。

WEB-INF/views/enroll.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"    pageEncoding="utf-8"%><%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><html><head><meta http-equiv="Content-Type" content="text/html; charset=Utf-8"><title>智能语义解析——基于欧拉蜜开放平台</title><link href="<c:url value='/static/css/custom.css' />" rel="stylesheet"></link></head><body>    <div class="form-container">        <h1>智能语义理解</h1>        <form:form method="POST" modelAttribute="cinfo"            class="form-horizontal">            <div class="row">                <label class="form-group col-md-1" for="corpus">输入语句:</label>                <div class="form-group col-md-2">                    <form:input type="text" path="corpus" id="corpus"                        class="form-control input-sm" />                        <div class="has-error">                            <form:errors path="corpus" class="help-inline" />                        </div>                </div>                <div class="form-group floatRight">                    <input type="submit" value="send" class="btn btn-primary btn-sm">                </div>            </div>                      <div class="row" style="color:#006600">                <label class="form-group col-md-1" for="corpus"><br>目前支持的语义解析领域有以下六个模块:</label>            </div>                      <div class="row" style="color:#006600">                <label class="form-group col-md-1" for="corpus">新闻:</label>                <div class="form-group col-md-2">                <br>                    app:news<br>                    语料示例:<br>                    今天的新闻<br>                    有哪些娱乐新闻<br>                    我要看新闻 <br>                    新闻头条<br>                </div>            </div>                      <div class="row" style="color:#006600">                <label class="form-group col-md-1" for="corpus">星座:</label>                <div class="form-group col-md-2">                <br>                    app:horoname<br>                    语料示例:<br>                    天蝎座的运势<br>                    天蝎座的本月运势<br>                    帮我查查明日运势,天蝎座的<br>                </div>            </div>                      <div class="row" style="color:#006600">                <label class="form-group col-md-1" for="corpus">公交:</label>                <div class="form-group col-md-2">                <br>                    app:busline<br>                    语料示例:<br>                    615路的行车路线<br>                    112路有哪些站点<br>                    张江南环线停靠哪些站<br>                    110路的公交路线<br>                </div>            </div>                      <div class="row" style="color:#006600">                <label class="form-group col-md-1" for="corpus">成语:</label>                <div class="form-group col-md-2">                <br>                    app:idioms<br>                    语料示例:<br>                    告诉我画龙点睛是什么意思<br>                    画龙点睛的含义<br>                    有没有哪个成语叫龙什么的<br>                    带龙的成语有哪些<br>                </div>            </div>                      <div class="row" style="color:#006600">                <label class="form-group col-md-1" for="corpus">笑话:</label>                <div class="form-group col-md-2">                <br>                    app:joke<br>                    语料示例:<br>                    讲笑话<br>                    给我讲个笑话吧<br>                    来张趣图<br>                    我要看笑话<br>                </div>            </div>                  <div class="row" style="color:#006600">                <label class="form-group col-md-1" for="corpus">解梦:</label>                <div class="form-group col-md-2">                <br>                    app:oneiromancy<br>                    语料示例:<br>                    给我查查梦到了黄金有什么寓意<br>                    昨天做梦梦到黄金了<br>                    梦到黄金了有什么说法<br>                    我昨天做了一个关于黄金的梦<br>                </div>            </div>                  </form:form>    </div></body></html>

WEB-INF/views/success.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"    pageEncoding="utf-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>智能语义解析——基于欧拉蜜开放平台</title><link href="<c:url value='/static/css/custom.css' />" rel="stylesheet"></link></head><body>    <div class="success">        <div style="color:#006600">            news支持类别有:头条(importnews),娱乐(ent),体育(sports),军事(mil),金融(finance),财经(fortune),教育(edu),法治(fz),健康(health),社会(society)。<br>            horoname支持查询的运势有:今日运势、明日运势、本周运势、本月运势、今年运势。<br> <br>            app:模块名称。 <br> modifier:表示一句话的操作意图。 如语句 查看娱乐新闻 的意图为 查,            即用“query”来表示。 <br> slot:表示需要从语料中提取出来的关键字。 如语句 查看娱乐新闻 的意图已知道是            查,而查什么则是由slot来补充,即slot名字为type,值为从语料中提取出来的词语“娱乐”。<br>            更多详细介绍可参考:            <a href="https://cn.olami.ai/wiki/?mp=nli&content=nli_response_result.html">https://cn.olami.ai/wiki/?mp=nli&content=nli_response_result.html</a>        </div>        <br>        <br> ${answer}    </div></body></html>

static/css/custom.css

.form-container {  position:fiexd;  width:30%;  margin-left: 20px;  margin-top: 20px;  margin-bottom: 20px;  padding: 10px;  background-color: #E8E1E1;  border: 1px solid #ddd;  border-radius: 4px;}  .form-group {    display: inline-block;    margin-bottom: 0;    vertical-align: middle;  }.input-sm {  width: 400px;  height: 30px;  padding: 5px 10px;  font-size: 12px;  line-height: 1.5;  border-radius: 3px;}.floatRight{    float:right;    margin-right: 18px;}.row {  margin-right: 15px;  margin-left: 15px;}.col-md-1, .col-md-2 {  position: relative;  min-height: 1px;  padding-right: 5px;  padding-left: 5px;}.has-error{    color:red;}.success{  position:fiexd;  width:50%;  margin-left: 50px;  margin-top:20px;  padding: 20px;  background-color: #E8E1E1;  border: 1px solid #ddd;  border-radius: 4px;}

7、添加初始化器类

package com.demo.configuration;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRegistration;import org.springframework.web.WebApplicationInitializer;import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;import org.springframework.web.servlet.DispatcherServlet;public class DemoInitializer implements WebApplicationInitializer {    public void onStartup(ServletContext container) throws ServletException {        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();        ctx.register(DemoConfiguration.class);        ctx.setServletContext(container);        ServletRegistration.Dynamic servlet = container.addServlet(                "dispatcher", new DispatcherServlet(ctx));        servlet.setLoadOnStartup(1);        servlet.addMapping("/");    }}

8、构建和部署应用程序

运行应用程序,访问URL:http://localhost:8080/SpringMVCDemoNLI

得到的初始页面如下图所示:

提交不正确输入时,会得到验证错误(在 message.properties 中用户定义的消息)

提交成功后跳转页面如下:

阅读全文
0 0
原创粉丝点击