【SSM分布式架构电商项目

阅读: 评论:0

【SSM分布式架构电商项目

【SSM分布式架构电商项目

对外的接口服务

我们把上一篇:【SSM分布式架构电商项目-14】后台CMS内容管理系统管理前台首页广告里面的ContentController拷贝到api包下,对外提供接口服务:

package com.ller.api;import org.springframework.beans.factory.annotation.Autowired;
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.RequestParam;import com.taotaomon.bean.EasyUIResult;
import com.taotao.manage.service.ContentService;@RequestMapping("api/content")
@Controller
public class ApiContentController {@Autowiredprivate ContentService contentService;/***  根据内容分类id查询分类列表*  * @param categoryId* @param page* @param rows* @return*/@RequestMapping(method = RequestMethod.GET)public ResponseEntity<EasyUIResult> queryListByCategoryId(@RequestParam("categoryId") Long categoryId,@RequestParam(value = "page", defaultValue = "1") Integer page,@RequestParam(value = "rows", defaultValue = "10") Integer rows) {try {EasyUIResult easyUIResult = tService.queryListByCategoryId(categoryId, page, rows);return ResponseEntity.ok(easyUIResult);} catch (Exception e) {e.printStackTrace();}return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);}
}

测试:

访问接口服务的方式

方式有2种:
1、 js访问
a) 有跨域 – jsonp解决
b) 无跨域 – ajax解决
2、 Java代码访问
a) Httpclient

Httpclient

导入依赖

DoGET

package cn.itcast.httpclient;import org.apache.hods.CloseableHttpResponse;
import org.apache.hods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;public class DoGET {public static void main(String[] args) throws Exception {// 创建Httpclient对象CloseableHttpClient httpclient = ateDefault();// 创建http GET请求HttpGet httpGet = new HttpGet("=java");CloseableHttpResponse response = null;try {// 执行请求response = ute(httpGet);// 判断返回状态是否为200if (StatusLine().getStatusCode() == 200) {String content = Entity(), "UTF-8");System.out.println("内容:"+content);}} finally {if (response != null) {response.close();}httpclient.close();}}}

带有参数的GET请求

package cn.itcast.httpclient;import java.URI;import org.apache.hods.CloseableHttpResponse;
import org.apache.hods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;public class DoGETParam {public static void main(String[] args) throws Exception {// 创建Httpclient对象CloseableHttpClient httpclient = ateDefault();// 定义请求的参数URI uri = new URIBuilder("").setParameter("categoryId", "33").setParameter("page", "1").setParameter("rows", "1").build();System.out.println(uri);// 创建http GET请求HttpGet httpGet = new HttpGet(uri);CloseableHttpResponse response = null;try {// 执行请求response = ute(httpGet);// 判断返回状态是否为200if (StatusLine().getStatusCode() == 200) {String content = Entity(), "UTF-8");System.out.println(content);}} finally {if (response != null) {response.close();}httpclient.close();}}}

DoPOST

package cn.itcast.httpclient;import java.util.ArrayList;
import java.util.List;import org.apache.http.NameValuePair;
import org.apache.ity.UrlEncodedFormEntity;
import org.apache.hods.CloseableHttpResponse;
import org.apache.hods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.ssage.BasicNameValuePair;
import org.apache.http.util.EntityUtils;public class DoPOSTParam {public static void main(String[] args) throws Exception {// 创建Httpclient对象CloseableHttpClient httpclient = ateDefault();// 创建http POST请求HttpPost httpPost = new HttpPost("");// 伪装成浏览器httpPost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36");// 设置2个post参数,一个是scope、一个是qList<NameValuePair> parameters = new ArrayList<NameValuePair>(0);parameters.add(new BasicNameValuePair("scope", "project"));parameters.add(new BasicNameValuePair("q", "java"));parameters.add(new BasicNameValuePair("fromerr", "7nXH76r7"));// 构造一个form表单式的实体UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);// 将请求实体设置到httpPost对象中httpPost.setEntity(formEntity);CloseableHttpResponse response = null;try {// 执行请求response = ute(httpPost);// 判断返回状态是否为200if (StatusLine().getStatusCode() == 200) {String content = Entity(), "UTF-8");System.out.println(content);}} finally {if (response != null) {response.close();}httpclient.close();}}}

带有参数的POST请求

 public static void main(String[] args) throws Exception {// 创建Httpclient对象CloseableHttpClient httpclient = ateDefault();// 创建http POST请求HttpPost httpPost = new HttpPost("");// 伪装成浏览器httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36");// 设置2个post参数,一个是scope、一个是qList<NameValuePair> parameters = new ArrayList<NameValuePair>(0);parameters.add(new BasicNameValuePair("scope", "project"));parameters.add(new BasicNameValuePair("q", "java"));parameters.add(new BasicNameValuePair("fromerr", "7nXH76r7"));// 构造一个form表单式的实体UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);// 将请求实体设置到httpPost对象中httpPost.setEntity(formEntity); CloseableHttpResponse response = null;try {// 执行请求response = ute(httpPost);// 判断返回状态是否为200if (StatusLine().getStatusCode() == 200) {String content = Entity(), "UTF-8");System.out.println(content);}} finally {if (response != null) {response.close();}httpclient.close();}}

连接管理器


注意:

package cn.itcast.httpclient;import org.apache.hods.CloseableHttpResponse;
import org.apache.hods.HttpGet;
import org.HttpClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;public class HttpConnectManager {public static void main(String[] args) throws Exception {PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();// 设置最大连接数cm.setMaxTotal(200);// 设置每个主机地址的并发数cm.setDefaultMaxPerRoute(20);doGet(cm);doGet(cm);}public static void doGet(HttpClientConnectionManager cm) throws Exception {CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();// 创建http GET请求HttpGet httpGet = new HttpGet("/");CloseableHttpResponse response = null;try {// 执行请求response = ute(httpGet);// 判断返回状态是否为200if (StatusLine().getStatusCode() == 200) {String content = Entity(), "UTF-8");System.out.println("内容长度:" + content.length());}} finally {if (response != null) {response.close();}// 此处不能关闭httpClient,如果关闭httpClient,连接池也会销毁// httpClient.close();}}}

定期关闭无效连接

public class ClientEvictExpiredConnections {public static void main(String[] args) throws Exception {PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();// 设置最大连接数cm.setMaxTotal(200);// 设置每个主机地址的并发数cm.setDefaultMaxPerRoute(20);new IdleConnectionEvictor(cm).start();}public static class IdleConnectionEvictor extends Thread {private final HttpClientConnectionManager connMgr;private volatile boolean shutdown;public IdleConnectionEvictor(HttpClientConnectionManager connMgr) {Mgr = connMgr;}@Overridepublic void run() {try {while (!shutdown) {synchronized (this) {wait(5000);// 关闭失效的连接connMgr.closeExpiredConnections();}}} catch (InterruptedException ex) {// 结束}}public void shutdown() {shutdown = true;synchronized (this) {notifyAll();}}}}

设置请求参数

Httpclient和Spring的整合

<beans xmlns=""xmlns:context="" xmlns:p=""xmlns:aop="" xmlns:tx=""xmlns:xsi=""xsi:schemaLocation=" .0.xsd .0.xsd .0.xsd  .0.xsd .0.xsd"><bean id="connectionManager"class="org.apache.PoolingHttpClientConnectionManager"><!-- 最大连接数 --><property name="maxTotal" value="${http.maxTotal}" /><!-- 设置每个主机地址的并发数 --><property name="defaultMaxPerRoute" value="${http.defaultMaxPerRoute}" /></bean><!-- Httpclient对象的构建器 --><bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder"><property name="connectionManager" ref="connectionManager" /></bean><!-- Httpclient对象 --><!-- 注意:该对象为多例 --><bean class="org.apache.http.impl.client.CloseableHttpClient"factory-bean="httpClientBuilder" factory-method="build" scope="prototype"></bean><!-- 请求配置的构建器 --><bean id="requestConfigBuilder" class="org.apache.fig.RequestConfig.Builder"><!-- 创建连接的最长时间 --><property name="connectTimeout" value="${tTimeout}" /><!-- 从连接池中获取到连接的最长时间 --><property name="connectionRequestTimeout" value="${tionRequestTimeout}" /><!-- 数据传输的最长时间 --><property name="socketTimeout" value="${http.socketTimeout}" /><!-- 提交请求前测试连接是否可用 --><property name="staleConnectionCheckEnabled" value="${http.staleConnectionCheckEnabled}" /></bean><!-- 请求配置对象 --><bean class="org.apache.fig.RequestConfig"factory-bean="requestConfigBuilder" factory-method="build" /><!-- 定期清理无效连接 --><bean class="com.taotaomon.httpclient.IdleConnectionEvictor"><constructor-arg index="0" ref="connectionManager"/></bean></beans>

分析:
我们先配置连接管理器:PoolingHttpClientConnectionManager

之后我们需要拿到CloseableHttpClient:

 CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();

这里分两步,先是HttpClients.custom(),然后并设置setConnectionManager(cm)。
第二步使用build()方法生成CloseableHttpClient 对象。

第一步:

我们可以看到在第一步HttpClients.custom().setConnectionManager(cm)最后返回的是HttpClientBuilder对象,所以我们先来配置HttpClientBuilder的bean

第二步:使用build()方法:

接下来我们要配置请求参数:

   // 构建请求配置信息RequestConfig config = RequestConfig.custom().setConnectTimeout(1000) // 创建连接的最长时间.setConnectionRequestTimeout(500) // 从连接池中获取到连接的最长时间.setSocketTimeout(10 * 1000) // 数据传输的最长时间.setStaleConnectionCheckEnabled(true) // 提交请求前测试连接是否可用.build();

这里我们也分两步:第一步先是RequestConfig.custom()得到org.apache.fig.RequestConfig.Builder,并且设置其属性,第二步通过build()方法得到RequestConfig 对象。


所以我们先配置 org.apache.fig.RequestConfig.Builder

之后我们在给它设置属性:

第二步:通过build方法得到RequestConfig

接下来我们还要配置定期清理无用连接,我们在common中加入:

package com.taotaomon.httpclient;import org.HttpClientConnectionManager;public class IdleConnectionEvictor extends Thread {private final HttpClientConnectionManager connMgr;private volatile boolean shutdown;public IdleConnectionEvictor(HttpClientConnectionManager connMgr) {Mgr = connMgr;// 启动当前线程this.start();}@Overridepublic void run() {try {while (!shutdown) {synchronized (this) {wait(5000);// 关闭失效的连接connMgr.closeExpiredConnections();}}} catch (InterruptedException ex) {// 结束}}public void shutdown() {shutdown = true;synchronized (this) {notifyAll();}}
}

然后我们在配置文件中配置:

然后我们要加入外部配置文件:

在Spring配置中,加载外部配置文件:

封装ApiService

我们来封装使用HttpClient的通用Service,我们把它放在common中。

package com.taotaomon.service;import java.io.IOException;
import java.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.fig.RequestConfig;
import org.apache.ity.UrlEncodedFormEntity;
import org.apache.hods.CloseableHttpResponse;
import org.apache.hods.HttpGet;
import org.apache.hods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.ity.ContentType;
import org.ity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.ssage.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.taotaomon.httpclient.HttpResult;@Service
public class ApiService implements BeanFactoryAware {@Autowired(required = false)private RequestConfig requestConfig;private BeanFactory beanFactory;/*** GET请求地址,响应200,返回响应的内容,响应为404、500返回null* * @param url* @return* @throws ClientProtocolException* @throws IOException*/public String doGet(String url) throws ClientProtocolException, IOException {// 创建http GET请求HttpGet httpGet = new HttpGet(url);httpGet.questConfig);CloseableHttpResponse response = null;try {// 执行请求response = getHttpclient().execute(httpGet);// 判断返回状态是否为200if (StatusLine().getStatusCode() == 200) {Entity(), "UTF-8");}} finally {if (response != null) {response.close();}}return null;}/*** 带有参数的GET请求* * @param url* @param params* @return* @throws ClientProtocolException* @throws IOException* @throws URISyntaxException*/public String doGet(String url, Map<String, String> params) throws ClientProtocolException, IOException,URISyntaxException {// 定义请求的参数URIBuilder builder = new URIBuilder(url);for (Map.Entry<String, String> entry : Set()) {builder.Key(), Value());}return this.doGet(builder.build().toString());}/*** 带有参数的POST请求* * @param url* @param params* @return* @throws ClientProtocolException* @throws IOException*/public HttpResult doPost(String url, Map<String, String> params) throws ClientProtocolException,IOException {// 创建http POST请求HttpPost httpPost = new HttpPost(url);httpPost.questConfig);if (null != params) {List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);for (Map.Entry<String, String> entry : Set()) {parameters.add(new Key(), Value()));}// 构造一个form表单式的实体UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);// 将请求实体设置到httpPost对象中httpPost.setEntity(formEntity);}CloseableHttpResponse response = null;try {// 执行请求response = getHttpclient().execute(httpPost);HttpEntity entity = Entity();if (null == entity) {return new StatusLine().getStatusCode(), null);}return new StatusLine().getStatusCode(), Entity(), "UTF-8"));} finally {if (response != null) {response.close();}}}/*** 带有json参数的POST请求* * @param url* @param params* @return* @throws ClientProtocolException* @throws IOException*/public HttpResult doPostJson(String url, String json) throws ClientProtocolException,IOException {// 创建http POST请求HttpPost httpPost = new HttpPost(url);httpPost.questConfig);if (null != json) {StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);// 将请求实体设置到httpPost对象中httpPost.setEntity(stringEntity);}CloseableHttpResponse response = null;try {// 执行请求response = getHttpclient().execute(httpPost);HttpEntity entity = Entity();if (null == entity) {return new StatusLine().getStatusCode(), null);}return new StatusLine().getStatusCode(), Entity(), "UTF-8"));} finally {if (response != null) {response.close();}}}/*** 没有参数的POST请求* * @param url* @return* @throws ClientProtocolException* @throws IOException*/public HttpResult doPost(String url) throws ClientProtocolException, IOException {return this.doPost(url, null);}private CloseableHttpClient getHttpclient() {return Bean(CloseableHttpClient.class);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {// 该方法是在Spring容器初始化时会调用该方法,传入beanFactorythis.beanFactory = beanFactory;}
}

异常处理:

get返回值是根据状态码为200则返回数据,状态码不为200则返回null。post的返回值必须返回响应状态码和内容,比如返回状态码为201的时候同时也会返回内容,所以我们构造一个对象来返回:

package com.taotaomon.httpclient;public class HttpResult {private Integer code;private String body;public HttpResult() {}public HttpResult(Integer code, String body) {de = code;this.body = body;}public Integer getCode() {return code;}public void setCode(Integer code) {de = code;}public String getBody() {return body;}public void setBody(String body) {this.body = body;}}

然后我们再来看一个单例对象中如何使用多例的对象的问题:

原本我们应该这样写:

然后我们通过注入的httpclient使用得到CloseableHttpResponse对象。但是因为我们注解@Service的ApiService是单例的,只会实例化一次,实例化一次的时候只会注入一次httpclient,那么我们的httpclient就变成单例的了。然而我们的httpclient必须是个多例对象。那我们可能会想把ApiService变成多例的,加@Scope(“prototype”)就可以了。那么如果有其他的Service或者Controller要调用这个ApiService是不是也是同样的情况,也是在单例对象中使用多例对象。所以这个方法不可行。那么我们如何在单例对象中使用多例对象?
解决方法就是:httpclient这个对象不能注入,而是每次使用的时候,通过容器里面去获取,因为在容器里面指定httpclient是多例的。
所以主要的代码截图下:


通过以上步骤就可以达到在单例对象中使用多例对象。

本文发布于:2024-02-01 03:16:40,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170672860033484.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:分布式   架构   项目   SSM
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23