Spring MVC框架是一个开源的Java平台,为开发强大的基于Java的Web应用程序提供全面的基础架构支持非常容易和非常快速。
Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构和用于开发灵活和松散耦合的Web应用程序的组件。
MVC模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时提供这些元素之间的松散耦合。
该项目实现了智能解析用户输入语句的语义,输出结果以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 = " ";
- 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 中用户定义的消息)
提交成功后跳转页面如下:
来源: http://blog.csdn.net/u011827504/article/details/77869104