Browse Source

查询问题、反馈问题、搜索问题

git-svn-id: svn+ssh://10.10.101.21/source/platform/platform-b2b@1293 f3bf4e98-0cf0-11e4-a00c-a99a8b9d557d
luoq 10 years ago
parent
commit
4227cd00d0

+ 113 - 0
src/main/java/com/uas/platform/b2b/controller/QuestionController.java

@@ -0,0 +1,113 @@
+package com.uas.platform.b2b.controller;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.uas.platform.b2b.core.util.SearchKeyUtils;
+import com.uas.platform.b2b.model.Question;
+import com.uas.platform.b2b.service.QuestionService;
+import com.uas.platform.core.model.PageInfo;
+import com.uas.platform.core.model.PageParams;
+
+/**
+ * 
+ * @author luoq
+ *
+ */
+@Controller
+@RequestMapping("/serve/question")
+public class QuestionController {
+	
+	@Autowired
+	private QuestionService questionService;
+	
+	/**
+	 * author luoq
+	 * 查找常见问题
+	 * @param hot
+	 * @param isAuthed
+	 * @param params
+	 * @return
+	 */
+	@RequestMapping(method = RequestMethod.GET)
+	@ResponseBody
+	public Page<Question> getCommonQuestions(Long hot ,boolean isAuthed, PageParams params){
+		PageInfo pageInfo = new PageInfo(params);
+		return questionService.findCommonQuestion(hot, isAuthed, pageInfo);
+	}
+	
+	/**
+	 * author luoq
+	 * 按类别查找问题
+	 * @param classId
+	 * @param isAuthed
+	 * @param params
+	 * @return
+	 */
+	@RequestMapping(value = "/class",method = RequestMethod.GET)
+	@ResponseBody
+	public Page<Question> getClassQuestions(Long classId, boolean isAuthed, PageParams params){
+		PageInfo pageInfo = new PageInfo(params);
+		return questionService.findByClassId(classId, isAuthed, pageInfo);
+	}
+	
+	/**
+	 * author luoq
+	 * 查找单个问题
+	 * @param questionId
+	 * @return
+	 */
+	@RequestMapping(value = "/solution", method = RequestMethod.GET)
+	@ResponseBody
+	public Question getQuestion(Long questionId){
+		questionService.updateHot(questionId);	//hot值加1
+		return questionService.findById(questionId);
+	}
+	
+	/**
+	 * author luoq
+	 * 根据用户的输入搜索问题(未分词)
+	 * @param question
+	 * @return
+	 * @throws UnsupportedEncodingException
+	 */
+	@RequestMapping(value = "/search", method = RequestMethod.GET)
+	@ResponseBody
+	public List<Question> searchQuestions(String question, Double similarity) throws UnsupportedEncodingException{
+		return questionService.search(SearchKeyUtils.decodeURL(question), similarity);
+	}
+	
+	/**
+	 * 问题反馈
+	 * @param classId
+	 * @param isPublic
+	 * @param title
+	 * @return
+	 */
+	@RequestMapping(value = "/feedback", method = RequestMethod.POST)
+	public ResponseEntity<String> feedBack(Long classId, Long isPublic, String title, Long userUU){
+		questionService.feedBackQuestion(classId, isPublic, SearchKeyUtils.decodeURL(title), userUU);
+		return new ResponseEntity<String>(HttpStatus.OK);
+	}
+	
+	/**
+	 * 获取我的反馈记录
+	 * @param params
+	 * @return
+	 */
+	@RequestMapping(value = "/myFeedback", method = RequestMethod.GET)
+	@ResponseBody
+	public Page<Question> getMyFeedback(Long userUU, PageParams params){
+		PageInfo pageInfo = new PageInfo(params);
+		return questionService.findByUserUU(userUU, pageInfo);
+	}
+}

+ 96 - 0
src/main/java/com/uas/platform/b2b/core/util/CosineSimilarityAlgorithm.java

@@ -0,0 +1,96 @@
+package com.uas.platform.b2b.core.util;
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+//余弦相似度算法,比较两个字符串的相似度
+public class CosineSimilarityAlgorithm {
+	//返回两个字符串的相似度
+    public static double getSimilarity(String str1, String str2) {
+        if (str1 != null && str1.trim().length() > 0 && str2 != null&& str2.trim().length() > 0) {
+             
+            Map<Integer, int[]> AlgorithmMap = new HashMap<Integer, int[]>();
+             
+            //将两个字符串中的中文字符以及出现的总数封装到,AlgorithmMap中
+            for (int i = 0; i < str1.length(); i++) {
+                char d1 = str1.charAt(i);
+                if(isChinese(d1)){
+                    int charIndex = getGB2312Id(d1);
+                    if(charIndex != -1){
+                        int[] fq = AlgorithmMap.get(charIndex);
+                        if(fq != null && fq.length == 2){
+                            fq[0]++;
+                        }else {
+                            fq = new int[2];
+                            fq[0] = 1;
+                            fq[1] = 0;
+                            AlgorithmMap.put(charIndex, fq);
+                        }
+                    }
+                }
+            }
+ 
+            for (int i = 0; i < str2.length(); i++) {
+                char d2 = str2.charAt(i);
+                if(isChinese(d2)){
+                    int charIndex = getGB2312Id(d2);
+                    if(charIndex != -1){
+                        int[] fq = AlgorithmMap.get(charIndex);
+                        if(fq != null && fq.length == 2){
+                            fq[1]++;
+                        }else {
+                            fq = new int[2];
+                            fq[0] = 0;
+                            fq[1] = 1;
+                            AlgorithmMap.put(charIndex, fq);
+                        }
+                    }
+                }
+            }
+             
+            Iterator<Integer> iterator = AlgorithmMap.keySet().iterator();
+            double sqstr1 = 0;
+            double sqstr2 = 0;
+            double denominator = 0; 
+            while(iterator.hasNext()){
+                int[] c = AlgorithmMap.get(iterator.next());
+                denominator += c[0]*c[1];
+                sqstr1 += c[0]*c[0];
+                sqstr2 += c[1]*c[1];
+            }
+             
+            return denominator / Math.sqrt(sqstr1*sqstr2);
+        } else {
+            throw new NullPointerException(
+                    " the Document is null or have not cahrs!!");
+        }
+    }
+    //判断是否汉字
+    public static boolean isChinese(char ch) {
+        return (ch >= 0x4E00 && ch <= 0x9FA5);
+ 
+    }
+ 
+    /**
+     * 根据输入的Unicode字符,获取它的GB2312编码或者ascii编码,
+     * @param ch 输入的GB2312中文字符或者ASCII字符(128个)
+     * @return   在GB2312中的位置,-1表示该字符不认识
+     */
+    public static short getGB2312Id(char ch) {
+        try {
+            byte[] buffer = Character.toString(ch).getBytes("GB2312");
+            if (buffer.length != 2) {
+            	 // 正常情况下buffer应该是两个字节,否则说明ch不属于GB2312编码,故返回'?',此时说明不认识该字符
+                return -1;
+            }
+            int b0 = (int) (buffer[0] & 0x0FF) - 161; // 编码从A1开始,因此减去0xA1=161
+            int b1 = (int) (buffer[1] & 0x0FF) - 161; // 第一个字符和最后一个字符没有汉字,因此每个区只收16*6-2=94个汉字
+            return (short) (b0 * 94 + b1);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return -1;
+    }
+}

+ 69 - 0
src/main/java/com/uas/platform/b2b/dao/QuestionDao.java

@@ -0,0 +1,69 @@
+package com.uas.platform.b2b.dao;
+
+import java.util.List;
+
+
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.uas.platform.b2b.model.Question;
+
+@Repository
+public interface QuestionDao extends JpaSpecificationExecutor<Question>,JpaRepository<Question,Long> {
+	
+	/**
+	 * 根据hot值和isPublic值查找常见问题(未登录,只能查看公开的问题)
+	 * @param hot
+	 * @param pageable
+	 * @return
+	 */
+	@Query("from Question q where q.hot > :hot and isPublic = 1")
+	Page<Question> findCommonAndPublic(@Param("hot") Long hot, Pageable pageable);
+	
+	/**
+	 * 根据hot值查找常见问题(已登录,公开与否都可查看)
+	 * @param hot
+	 * @param pageable
+	 * @return
+	 */
+	@Query("from Question q where q.hot > :hot")
+	Page<Question> findCommonQuestion(@Param("hot") Long hot, Pageable pageable);
+	
+	/**
+	 * 查找某类问题(未登录,只能查看公开的问题)
+	 * @param classId
+	 * @param isPublic
+	 * @param pageable
+	 * @return
+	 */
+	Page<Question> findByClassIdAndIsPublic(Long classId, Long isPublic, Pageable pageable);
+	
+	/**
+	 * 查找某类问题(已登录,公开与否都可查看)
+	 * @param classId
+	 * @param pageable
+	 * @return
+	 */
+	Page<Question> findByClassId(Long classId, Pageable pageable);
+	
+	/**
+	 * 根据id查找单个问题
+	 * @param questionId
+	 * @return
+	 */
+	@Query("from Question q where q.id = :questionId")
+	public List<Question> findQuestion(@Param("questionId") Long questionId);
+	
+	/**
+	 * 查找单个用户的所有反馈问题
+	 * @param userUU
+	 * @param pageable
+	 * @return
+	 */
+	Page<Question> findByCreateUserUU(Long userUU, Pageable pageable);
+}

+ 215 - 0
src/main/java/com/uas/platform/b2b/model/Question.java

@@ -0,0 +1,215 @@
+package com.uas.platform.b2b.model;
+
+
+import java.util.Date;
+
+import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+/**
+ * 问题实体类
+ * @author luoq
+ *
+ */
+@Entity
+@Table(name = "service$questions")
+@Cacheable
+@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "com.uas.platform.b2b.model.Question")
+public class Question {
+	
+	@Id
+	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "service$question_gen")
+	@SequenceGenerator(name = "service$question_gen", sequenceName = "service$question_seq", allocationSize = 1)
+	@Column(name = "que_id")
+	private Long id;
+	
+	/**
+	 * 问题类别
+	 */
+	@Column(name = "que_class")
+	private Long classId;
+	
+	/**
+	 * 问题标题
+	 */
+	@Column(name = "que_title")
+	private String title;
+	
+	/**
+	 * 问题解决方案
+	 */
+	@Column(name = "que_solution")
+	private String solution;
+	
+	/**
+	 * 问题热度
+	 */
+	@Column(name = "que_hot")
+	private Long hot;
+	
+	/**
+	 * 问题反馈者
+	 */
+	@OneToOne(cascade = { CascadeType.REFRESH })
+	@JoinColumn(name = "que_createUser", insertable = false, updatable = false)
+	private UserBaseInfo createUser;
+	
+	/**
+	 * 问题反馈者UU
+	 */
+	@Column(name = "que_createUser")
+	private Long createUserUU;
+	
+	/**
+	 * 问题反馈时间
+	 */
+	@Column(name = "que_createTime")
+	private Date createTime;
+	
+	/**
+	 * 问题回复者
+	 */
+	@OneToOne(cascade = { CascadeType.REFRESH })
+	@JoinColumn(name = "que_replyUser", insertable = false, updatable = false)
+	private UserBaseInfo replyUser;
+	
+	/**
+	 * 问题回复者UU
+	 */
+	@Column(name = "que_replyUser")
+	private Long replyUserUU;
+	/**
+	 * 回复时间
+	 */
+	@Column(name = "que_replyTime")
+	private Date replyTime;
+	
+	/**
+	 * 是否公开
+	 */
+	@Column(name = "isPublic")
+	private Long isPublic;
+	
+	/**
+	 * 是否已解答
+	 */
+	@Column(name = "isResolved")
+	private Long isResolved;
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getClassId() {
+		return classId;
+	}
+
+	public void setClassId(Long classId) {
+		this.classId = classId;
+	}
+
+	public String getTitle() {
+		return title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public String getSolution() {
+		return solution;
+	}
+
+	public void setSolution(String solution) {
+		this.solution = solution;
+	}
+
+	public Long getHot() {
+		return hot;
+	}
+
+	public void setHot(Long hot) {
+		this.hot = hot;
+	}
+
+	public UserBaseInfo getCreateUser() {
+		return createUser;
+	}
+
+	public void setCreateUser(UserBaseInfo createUser) {
+		this.createUser = createUser;
+	}
+
+	public Long getCreateUserUU() {
+		return createUserUU;
+	}
+
+	public void setCreateUserUU(Long createUserUU) {
+		this.createUserUU = createUserUU;
+	}
+
+	public Date getCreateTime() {
+		return createTime;
+	}
+
+	public void setCreateTime(Date createTime) {
+		this.createTime = createTime;
+	}
+
+	public UserBaseInfo getReplyUser() {
+		return replyUser;
+	}
+
+	public void setReplyUser(UserBaseInfo replyUser) {
+		this.replyUser = replyUser;
+	}
+
+	public Long getReplyUserUU() {
+		return replyUserUU;
+	}
+
+	public void setReplyUserUU(Long replyUserUU) {
+		this.replyUserUU = replyUserUU;
+	}
+
+	public Date getReplyTime() {
+		return replyTime;
+	}
+
+	public void setReplyTime(Date replyTime) {
+		this.replyTime = replyTime;
+	}
+
+	public Long getIsPublic() {
+		return isPublic;
+	}
+
+	public void setIsPublic(Long isPublic) {
+		this.isPublic = isPublic;
+	}
+
+	public Long getIsResolved() {
+		return isResolved;
+	}
+
+	public void setIsResolved(Long isResolved) {
+		this.isResolved = isResolved;
+	}
+
+}

+ 66 - 0
src/main/java/com/uas/platform/b2b/service/QuestionService.java

@@ -0,0 +1,66 @@
+package com.uas.platform.b2b.service;
+
+
+import java.util.List;
+
+import org.springframework.data.domain.Page;
+
+import com.uas.platform.b2b.model.Question;
+import com.uas.platform.core.model.PageInfo;
+
+public interface QuestionService {
+	
+	/**
+	 * 通过hot值查找常见问题
+	 * @param hot
+	 * @param isAuthed
+	 * @param pageInfo
+	 * @return
+	 */
+	public Page<Question> findCommonQuestion(Long hot, boolean isAuthed, final PageInfo pageInfo);
+	
+	/**
+	 * 分类查找问题
+	 * @param classId
+	 * @param pageInfo
+	 * @return
+	 */
+	public Page<Question> findByClassId(Long classId, boolean isAuthed, final PageInfo pageInfo);
+	
+	/**
+	 * 通过id查找问题
+	 * @param id
+	 * @return
+	 */
+	Question findById(Long questionId);
+	
+	/**
+	 * 搜索问题
+	 * @param question
+	 * @return
+	 */
+	List<Question> search(String question, Double similarity);
+
+	/**
+	 * 更新问题的热度值(加1)
+	 * @param questionId
+	 */
+	void updateHot(Long questionId);
+
+	/**
+	 * 反馈问题 
+	 * @param classId
+	 * @param isPublic
+	 * @param title
+	 */
+	public void feedBackQuestion(Long classId, Long isPublic, String title, Long userUU);
+	
+	/**
+	 * 查找某用户的反馈问题
+	 * @param userUU
+	 * @param pageInfo
+	 * @return
+	 */
+	Page<Question> findByUserUU(Long userUU, PageInfo pageInfo);
+
+}

+ 112 - 0
src/main/java/com/uas/platform/b2b/service/impl/QuestionServiceImpl.java

@@ -0,0 +1,112 @@
+package com.uas.platform.b2b.service.impl;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+import com.uas.platform.b2b.core.util.CosineSimilarityAlgorithm;
+import com.uas.platform.b2b.dao.QuestionDao;
+import com.uas.platform.b2b.model.Question;
+import com.uas.platform.b2b.service.QuestionService;
+import com.uas.platform.core.model.PageInfo;
+
+@Service
+public class QuestionServiceImpl implements QuestionService {
+
+	@Autowired
+	private QuestionDao questionDao;
+	
+	/**
+	 * 查找常见问题
+	 */
+	@Override
+	public Page<Question> findCommonQuestion(Long hot, boolean isAuthed, final PageInfo pageInfo) {
+		if(isAuthed){	//已登录
+			return questionDao.findCommonQuestion(hot, pageInfo);
+		}else{			//未登录
+			return questionDao.findCommonAndPublic(hot, pageInfo);
+		}
+	}
+	
+	/**
+	 * 分类查找问题
+	 */
+	@Override
+	public Page<Question> findByClassId(Long classId, boolean isAuthed, final PageInfo pageInfo) {
+		if(isAuthed){	//已登录
+			return questionDao.findByClassId(classId, pageInfo);
+		}else{			//未登录
+			return questionDao.findByClassIdAndIsPublic(classId, (long) 1, pageInfo);
+		}
+		
+	}
+
+	/**
+	 * 查找单个问题
+	 */
+	@Override
+	public Question findById(Long questionId) {
+		List<Question> questions = questionDao.findQuestion(questionId);
+		if (questions.size() > 0)
+			return questions.get(0);
+		return null;
+	}
+	
+	/**
+	 * 更新问题的热度值
+	 * @param questionId
+	 */
+	@Override
+	public void updateHot(Long questionId) {
+		List<Question> questions = questionDao.findQuestion(questionId);
+		if(questions.size() > 0){
+			questions.get(0).setHot(questions.get(0).getHot()+1);
+			questionDao.save(questions.get(0));
+		}
+	}
+	
+	/**
+	 * 搜索问题(未分词)
+	 */
+	@Override
+	public List<Question> search(String question, Double similarity) {
+		List<Question> questions = questionDao.findAll();
+		List<Question> result = new ArrayList<Question>();
+		for(int i = 0; i < questions.size(); i++){
+			if(CosineSimilarityAlgorithm.getSimilarity(question, questions.get(i).getTitle()) > similarity){
+				result.add(questions.get(i));
+			}
+		}
+		if (result.size() > 0)
+			return result;
+		return null;
+	}
+	
+	/**
+	 * 问题反馈
+	 */
+	@Override
+	public void feedBackQuestion(Long classId, Long isPublic, String title, Long userUU){
+		Question question = new Question();
+		question.setClassId(classId);
+		question.setIsPublic(isPublic);
+		question.setTitle(title);
+		question.setCreateUserUU(userUU);
+		question.setCreateTime(new Date());
+		question.setHot((long) 1);	//新问题热度值默认为1
+		question.setIsResolved((long) 0);	//新问题默认未解决
+		questionDao.save(question);
+	}
+	
+	/**
+	 * 查找某用户的反馈问题
+	 */
+	@Override
+	public Page<Question> findByUserUU(Long userUU, final PageInfo pageInfo){
+		return questionDao.findByCreateUserUU(userUU, pageInfo);
+	}
+}