引入项目

  • html页面放在模板引擎文件夹templates下,这样能使用模板引擎的功能。

登录页面国际化

  • 国际化:编写国际化配置文件

    1.编写国际化配置文件,抽取页面需要显示的国际化消息

    2.SpringBoot自动配置好了管理国际化资源文件的组件

@Bean
@ConfigurationProperties(
prefix = "spring.messages"
)
public MessageSourceProperties messageSourceProperties() {
return new MessageSourceProperties();
} @Bean
public MessageSource messageSource(MessageSourceProperties properties) {
/*
* ResourceBoundleMessageSource extends AbstractResourceBasedMessageSource implements BeanClassLoaderAware
* 该实现类允许用户通过beanName指定一个资源名:包括类路径的全限定资源名
* 或者通过beanName指定一组资源名
*/
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) {
/*
* setBasenames 设置国际化资源文件去掉语言国家代码的基础名,
* 国际化资源文件可以直接放在类路径下叫 messages.properties,
* 也可以在配置文件中指定基础名 spring.messages.basename
*/
String basename = context.getEnvironment().getProperty("spring.messages.basename", "messages");
messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
}
if (properties.getEncoding() != null) {
messageSource.setDefaultEncoding(properties.getEncoding().name());
}
/*
* 如果没有找到特定语言环境的文件,是否返回系统区域设置
* 默认为true
* 如果是关闭的,将会使用唯一的默认文件:比如baseName的“message”的 message.properties
*/
messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
Duration cacheDuration = properties.getCacheDuration();
if (cacheDuration != null) {
messageSource.setCacheMillis(cacheDuration.toMillis());
}
/*
* 设置是否始终应用消息格式组件,解析没有参数的消息
* 比如:MessageFormat希望单引号被转义为""",
* 如果消息文本全部使用这样的转义编写,即使没有定义参数占位符,也需要将此标志设为true
* 否则,只有具有实际意义的参数消息文本才会用MessageFormat的转义来编写
*/
messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
/*
* 是否使用消息代码作为默认消息,而不是抛出NoSuchMessageException异常,
* 适用于开发和调试,默认值为false
*/
messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
return messageSource;
}

MessageSource解析:

  • MessageSource架构图:

    • MessageSource: 抽象化的消息接口
    • HierarchicalMessageSource: 分层的消息源接口,可获取父消息源
    • MessageSourceSupport: 消息源解析的抽象类,通过指定"消息格式化组件MessageFormat"格式化消息
    • DelegatingMessageSource: 消息源解析委派类. 用户未指定消息源解析类时,SpringContext默认使用这个类. 功能比较简单:将字符串和参数数组格式化为一个消息字符串
    • AbstractMessageSource: 支持"配置文件"的方式国际化资源的抽象类. 内部提供一个与区域设置无关的公共消息配置文件,消息代码为关键字
    • StaticMessageSource: 主要用于程序测试. 允许通过编程的方式提供国际化信息
    • ResourceBundleMessageSource: 该实现类允许用户通过beanName指定一个资源名,包括类的全限定资源名. 或者通过beanName指定一组资源名. 不同的区域获取加载不同资源文件,以达到国际化的目的
    • ReloadableResourceBundleMessageSource:
      • ReloadableResourceBundleMessageSource和ResourceBundleMessageSource的区别:

        • 加载资源类型及方式:

          • ReloadResourceBundleMessageSource依托SpringResourceLoader加载Resource资源,功能更加强大,支持 .class.properties文件
          • ResourceBundleMessageSource依托JDK自带的ResourceBundle加载资源,支持绝对路径和工程路径,支持 .class.properties文件
        • 缓存时间:
          • ReloadResourceBundleMessageSource每次加载都会记录每个资源加载的时间点,在缓存资源过期后会再次比较文件的修改时间,如果不变则不需要加载,同时刷新本次加载时间点
          • ResourceBundleMessageSource主要利用ResourceBundle.Control实现简单的自动加载
        • 编码方式:
          • ReloadResourceBundleMessageSource不仅可以指定统一的默认编码方式,也同时支持为每个文件单独制定编码方式

MessageSource接口:

方法 描述
String getMessage(String code, Object[] args, String defaultMessge, Locale locale) 获取消息,如果没有找到消息,就返回默认值
String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException 获取消息,如果无法找到消息,则视为错误
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException 尝试使用传入的{@code MessageSourceResolvable}参数中包含的所有属性来解析消息. 必须在此方法上抛出{@code NoSuchMessageException}, 因为在调用此方法时,无法确定可解析的{@code defaultMessage}属性是否为空

MessageSourceResolvable解析消息要素的包装接口和类:

方法 描述
String[] getCode() 返回用于解决此消息的代码,按照这些代码应该尝试的顺序. 因此,最后的一个代码将是默认代码
Object[] getArguments() 返回要用于解析此消息的参数数组
String getDefaultMessage() 返回要用于解析此消息的默认消息

HierarchicalMessageSource消息源分层接口:

方法 描述
void setParentMessageSource(MessageSource parent) 设置将用于解决次对象无法解析的消息的父级
参数parent是将用于解析此对象无法解析的消息的父MessageSource.可能是{@code null},在这种情况下不需要解决
MessageSource getParentMessageSource() 返回当前MessageSource的父级,否则返回{@Code null}

MessageSourceSupport用于支持消息源解析的抽象类:

方法 描述
void setAlwaysUseMessageFormat(boolean alwaysUseMessageFormat) 设置是否始终应用消息格式组件,解析没有参数的消息
比如: MessageFromat希望单引号转义为"""
如果消息文本全部用这样的转义编写,即使没有定义参数占位符,只需要将此标志设为"true"
否则,只有具有实际参数的消息文本才会用MessageFormat转义类编写
boolean isAlwaysUseMessageFormat() 返回是否应用消息格式组件,解析没有参数的消息
String renderDefaultMessage(String defaultMessage, Object[] args, Locale locale) 渲染给定的默认消息字符串
String formatMessage(String msg, Object[] args, Locale locale) 渲染给定的消息字符串
MessageFormat createMessageFormat(String msg, Locale locale) 为给定的消息和区域设置创建一个MessageFormat

DelegatingMessageSource消息源解析委派类:

方法 描述
String getMessage(String code, Object[] args, String defaultMessage, Locale locale) 解析消息
父消息解析源不为null时,则采用父消息源解析消息.否则使用自身消息源解析消息
String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException 解析消息
如果父消息解析源不为null时,则采用父消息源解析消息,否则抛出异常
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException 解析消息
如果父消息解析源不为null时,则采用父消息源解析消息,否则使用自身消息源解析消息

AbstractMessageSourc抽象类Spring中支持配置文件的方式国际化资源的抽象类:

方法 描述
void setUseCodeAsDafaultMessage(boolean useCodeAsDefaultMessage) 设置是否使用消息代码作为默认消息,而不是抛出NoSuchMessageException.默认为false
String getMessageInternal(String code, Object[] args, Locale locale) 将给定的代码和参数解析为给定的区域中设置的消息,如果没有找到则返回{@code null}
String getMessageFromPArent(String code, Object[] args, Locale locale) 如果父MessageSource中存在消息则尝试从父MessageSource检索给定的消息
String getDefaultMessage(String code) 返回默认消息
Object[] resolveArgements(Object[] args, Locale locale) 通过给定的参数数组搜索,找到MessageSourceResolve对象并解析
String resolveCodeWithoutArguments(String code, Locale locale) 解析不带参数的消息

StaticMessageSource是AbstractMessageSource允许通过编程的方式提供国际化信息:

方法 描述
void addMessage(String code, Locale locale, String msg) 将给定的消息与给定的代码相关联
void addMessage(Map<String, String> messages, Locale locale) 批量将给定的消息与给定的代码相关联

ResourceBundleMessageSource是AbstractMessageSource的实现类,允许用户通过beanName指定一个资源名- 包括类路径的全限定名, 或者通过beanNames指定一组资源名:

方法 描述
void setBaseName(String basename) 设置资源文件
void setBaseNames(String... basenames) 批量设置资源文件
void setDefaultEncoding(String defaultEncoding) 设置用于解析绑定的资源文件的默认字符集
void setFallBackToSystemLocale(boolean fallbackToSystemLocale) 如果没有找到特定语言环境的文件,是否返回到系统区域设置
默认为true. 如果为false,唯一的备用文件将是默认文件
void setCacheSeconds(int cacheSeconds) 设置缓存加载绑定的资源文件的秒数
String resolveCodeWithoutArguments(String code, Locale locale) 将给定的消息代码解析为已注册资源包中的key,按照原样返回捆绑包中的值,不使用MessageFormat解析
MessageFormat resolveCode(String code, Locale locale) 将给定的消息代码解析为注册资源包中的key,每个消息代码使用缓存的MessageFormat实例
ResourceBundle getResourceBundle(String baseName, Locale locale) 为给定的baseName和代码返回一个ResourceBundle,从缓存中提取已生成的MessageFormat
ResourceBundle doGetBundle(String baseName, Locale locale) throws MissingResourceException 获取给定baseName和locale设置的资源包
MessageFormat getMessageFormat(ResourceBundle resourceBundle, String code, Locale locale) throws Missing ResourceException 为给定的包和代码返回一个MessageFormat,从缓存中提取已生成的MessageFormats
String getStringOrNull(ResourceBundle resourceBundle, String key) 获取资源包中指定key所对应的值

ReloadableResourceBundleMessageSource实现类允许用户通过beanName指定一个资源名,包括类路径和全限定名.或者通过beanNames指定一组资源名:

方法 描述
String resolveCodeWithoutArguments(String code, Locale locale) 将消息代码解析为检索到的包文件中的key,按原样返回包中找到的值,不使用MessageFormat解析
MessageFormat resolveCode(String code, Locale locale) 将给定的消息代码解析为检索到的包文件中的key,每个消息代码使用缓存的MessageFormat实例
PropertiesHolder getMergedProperties(Locale locale) 获取locale所对应的持有properties对象
List< String > calculateAllFilenames(String basename, Locale locale) 计算给定的捆绑包基础名称和区域设置的所有文件名
将计算给定区域设置的文件名,系统区域设置默认文件
List < String > calculateFilenamesForLocale(String basename, Locale locale) 计算给定捆绑基础包名称和区域设置的文件名
Properties loadProperties(Resource resource, String filename) 解析给定的resource资源,返回对应的properties对象
void clearCache() 清除所有资源包对应的properties文件
void clearCacheIncludingAncestors() 清除当前MessageSource及所有父资源的缓存
  • MessageFormat消息组件格式化: 主要就是将消息串,参数格式化成字符串

3.在页面获取国际化的值

标签体中:
th:text="#{}"
th:placeholder="#{}"
非标签体,行内表达式
[[#{}]]
  • 国际化原理:国际化中Locale(区域信息对象);LocaleResolver(获取区域信息对象)
        @Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "spring.mvc",
name = {"locale"}
)
// 默认的区域信息解析器就是根据请求头的区域信息获取Locale进行国际化解析
public LocaleResolver localeResolver() {
if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
} else {
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
} public Locale resolveLocale(HttpServletRequest request) {
Locale defaultLocale = this.getDefaultLocale();
if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
return defaultLocale;
} else {
Locale requestLocale = request.getLocale();
List<Locale> supportedLocales = this.getSupportedLocales();
if (!supportedLocales.isEmpty() && !supportedLocales.contains(requestLocale)) {
Locale supportedLocale = this.findSupportedLocale(request, supportedLocales);
if (supportedLocale != null) {
return supportedLocale;
} else {
return defaultLocale != null ? defaultLocale : requestLocale;
}
} else {
return requestLocale;
}
}
}

登录

  • 开发期间模板引擎修改以后,要想能够实时生效

    1.禁用模板引擎缓存-spring.thymeleaf.cache=false

    2.页面修改完以后ctrl+F9,进行重新编译
  • 登录错误消息的显示
th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"

拦截器

  • 通过拦截器进行登录检查

RESTful

  • 普通 CRUD:URI,/资源名称/资源标识
  • RESTful CRUD:以HTTP请求方式区分对资源的CRUD操作
普通 CRUD(URI来区分操作) RESTful CRUD
查询 getEmp emp--GET
添加 addEmp?xxx emp--POST
修改 updateEmp?id=xx&xxx emp/{id}--PUT
删除 deleteEmp?id=xx emp/{id}--DELETE
  • 举例:
请求URI 请求方式
查询所有员工 emps GET
查询某个员工(来到修改页面) emp/{id} GET
进入添加页面 emp GET
添加员工 emp POST
进入修改页面(查出员工信息进行回显) emp/{id} GET
修改员工 emp/{id} PUT
删除员工 emp/{id} DELETE

thymeleaf对公共页面元素抽取

  • 抽取公共片段
<div th:fragment="copy">

</div>
  • 引入公共片段
<div th:insert="~{footer :: copy}"></div>

引入公共片段的两种方式:
~{templatename::selector} 模板名::选择器
~{templatename::fragmentname} 模板名::片段名
其中模板名(公共片段来源的文件名)会使用thymeleaf的前后缀配置规则进行解析
  • 引入公共片段的th属性:

    1.th:insert -将公共片段整个插入到声明引入的元素中

    2.th:replace-将声明引入的元素替换为公共片段

    3.th:include-将被引入的片段的内容包含进这个标签中
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
  • 使用th属性进行引入公共片段时,可以不用写 ~ {},只有行内写法[[~ {}]],[(~{})]要写

列表 CRUD

C:

  • redirect:表示重定向到一个地址 / 代表当前项目路径
  • forward:表示转发到一个地址
  • SpringMVC自动将请求参数和入参对象的属性进行一一绑定.要求就是请求参数的名字name和JavaBean入参的对象里的属性名一致.
  • 问题:提交的数据格式不对:生日日期==日期格式化:SpringMVC将页面提交的数据需要转换为指定的类型.

U:

  • 请求URI和数据id通过 + 拼接字符串
  • 页面发送PUT请求:

    1.在SpringMVC中配置HiddenHttpMethodFilter,可以修改页面请求,SpringBoot已经自动配置好

    2.页面创建一个POST表单

    3.创建一个input项,name="_method";值就是指定的请求方式

错误处理机制

  • SpringBoot默认的错误处理机制

    1.浏览器访问时,返回一个默认的错误页面:错误状态码,错误类型,错误提示信息,错误时间.

    浏览器发送请求的请求头: text.html.

    2.如果是其它客户端访问,返回默认的一个json数据

    客户端发送请求的请求头:/*

    3.原理:可以参照ErrorMvcAutoConfiguration

    给容器中添加了如下组件:

    1.DefaultErrorAttributes:在页面共享错误信息
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> errorAttributes = new LinkedHashMap();
errorAttributes.put("timestamp", new Date());
this.addStatus(errorAttributes, webRequest);
this.addErrorDetails(errorAttributes, webRequest, includeStackTrace);
this.addPath(errorAttributes, webRequest);
return errorAttributes;
}

2.BasicErrorController:处理默认/error请求

@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {
private final ErrorProperties errorProperties; public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {
this(errorAttributes, errorProperties, Collections.emptyList());
} public BasicErrorController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {
super(errorAttributes, errorViewResolvers);
Assert.notNull(errorProperties, "ErrorProperties must not be null");
this.errorProperties = errorProperties;
} public String getErrorPath() {
return this.errorProperties.getPath();
} @RequestMapping(
produces = {"text/html"}
)
//产生html数据,处理浏览器发送的请求
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = this.getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
// 去哪个页面作为错误页面,包含页面地址和页面内容
ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
return modelAndView != null ? modelAndView : new ModelAndView("error", model);
} @RequestMapping //产生json数据,处理其它客户端请求
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = this.getStatus(request);
return new ResponseEntity(body, status);
}

3.ErrorPageCustomizer:系统出现4开头和5开头的错误,该组件生效,定制错误响应规则.就会来到/error请求.

	@Value("${error.path:/error}")
private String path = "/error"; //系统出现错误以后来到error请求进行处理

4.DefaultErrorViewResolver:

 public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
ModelAndView modelAndView = this.resolve(String.valueOf(status.value()), model);
if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
} return modelAndView;
} private ModelAndView resolve(String viewName, Map<String, Object> model) {
// 默认SpringBoot可以找到页面-error/404
String errorViewName = "error/" + viewName;
// 如果模板引擎可以解析这个页面地址就使用模板引擎解析
TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);
// 模板引擎可用的话返回到errorViewName指定的视图地址;如果模板引擎不可用,就在静态资源文件夹下找errorViewName对应的页面.假如静态资源文件夹没有对应的页面则返回null
return provider != null ? new ModelAndView(errorViewName, model) : this.resolveResource(errorViewName, model);
}

错误处理步骤:

  • 系统出现4开头和5开头的错误,该组件生效,定制错误响应规则.就会来到/error请求,就会被BasicErrorController处理.
  • 响应页面:去哪个页面是由DefaultErrorViewResolver解析得到的
 protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
Iterator var5 = this.errorViewResolvers.iterator(); ModelAndView modelAndView;
do {
if (!var5.hasNext()) {
return null;
} ErrorViewResolver resolver = (ErrorViewResolver)var5.next();
modelAndView = resolver.resolveErrorView(request, status, model);
} while(modelAndView == null); return modelAndView;
}
  • 如何定制错误响应

    • 如何定制错误页面

      • 模板引擎有的情况下:

        1.error/错误状态码,只要将错误页面命名为"错误状态码.html"放在模板引擎文件夹里的error文件夹下,发生此状态码的错误就会来到对应的页面

        2.可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误 - 精确优先,即优先寻找精确的错误状态码.html

        3.页面能获取哪些信息:

        • timstamp: 时间戳
        • status: 状态码
        • error: 错误提示
        • exception: 异常对象
        • message: 异常消息
        • errors: JSR303数据校验错误
      • 模板引擎没有的情况下:

        1.模板引擎找不到错误页面,就在静态资源文件夹下找
      • 模板引擎没有,静态资源文件夹也没有的情况下:

        1.默认来到SpringBoot的错误提示页面
    • 如何定制错误的json数据:

      1.自定义异常处理并返回定制的json数据
@ControllerAdvice
public class MyExceptionHandler { //没有自适应效果-浏览器和客户端都是返回的json数据
@ResponseBody
@ExceptionHandler(RuntimeException.class)
public Map<String,Object> handleException(Exception e){
Map<String,Object> map=new HashMap<>();
map.put("code","运行异常");
map.put("message",e.getMessage());
return map; }
}

2.转发到forward:/error进行自适应响应效果处理

@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public String handleException(Exception e, HttpServletRequest request){
Map<String,Object> map=new HashMap<>();
// 传入自己的错误状态码,否则就不会进入定制错误页面的解析流程--------Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
request.setAttribute("javax.servlet.error.status_code","500");
map.put("code","运行异常");
map.put("message",e.getMessage());
//转发到/error,实现自适应效果
return "forward:/error"; }
}

3.将定制数据携带出去:出现错误以后,会来到/error请求,这个请求会被BasicErrorController处理,响应的数据是由getErrorAttributes(由AbstractErrorController(ErrorController)规定的方法)得到的

  • 可以编写一个继承AbstractErrorController的子类实现类,放在容器中
  • 页面上能用的数据,json上返回的数据都是通过errorAttributes.getErrorAttributes得到的,也就是容器中DefaultErrorAttributes.getErrorAttributes()进行数据处理的
  • 响应是自适应的,可以通过定制ErrorAtrributes改变需要返回的内容.
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
//返回值map是页面和json能获取的所有字段
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> map=super.getErrorAttributes(webRequest, includeStackTrace);
map.put("company","oxford");
//异常处理器携带的数据
Map<String,Object> ext=(Map<String, Object>) webRequest.getAttribute("ext",0);
map.put("ext",ext);
return map;
}
}

微服务架构Day04-SpringBoot之web开发的更多相关文章

  1. iUAP云运维平台v3.0全面支持基于K8s的微服务架构

    什么是微服务架构? 微服务(MicroServices)架构是当前互联网业界的一个技术热点,业内各公司也都纷纷开展微服务化体系建设.微服务架构的本质,是用一些功能比较明确.业务比较精练的服务去解决更大 ...

  2. 用友iuap云运维平台支持基于K8s的微服务架构

    什么是微服务架构? 微服务(MicroServices)架构是当前互联网业界的一个技术热点,业内各公司也都纷纷开展微服务化体系建设.微服务架构的本质,是用一些功能比较明确.业务比较精练的服务去解决更大 ...

  3. Aibabelx-shop 大型微服务架构系列实战之技术选型

    一.本项目涉及编程语言java,scala,python,涉及的技术如下: 1.微服务架构: springboot springcloud mybatisplus shiro 2.全文检索技术 sol ...

  4. (五):C++分布式实时应用框架——微服务架构的演进

    C++分布式实时应用框架--微服务架构的演进 上一篇:(四):C++分布式实时应用框架--状态中心模块 版权声明:本文版权及所用技术归属smartguys团队所有,对于抄袭,非经同意转载等行为保留法律 ...

  5. SpringBoot微服务架构下的MVC模型总结

    SpringBoot微服务架构下的MVC模型产生的原因: 微服务概念改变着软件开发领域,传统的开源框架结构开发,由于其繁琐的配置流程 , 复杂的设置行为,为项目的开发增加了繁重的工作量,微服务致力于解 ...

  6. 使用Redis为注册中心的Dubbo微服务架构(基于SpringBoot)

    title: 使用Redis为注册中心的Dubbo微服务架构(基于SpringBoot) date: 2019-07-30 14:06:29 categories: 架构 author: mrzhou ...

  7. .net core 微服务架构-docker的部署-包括网关服务(Ocelot)+认证服务(IdentityServer4)+应用服务(asp.net core web api)

    本文主要介绍通过Docker来部署通过.Net Core开发的微服务架构,部署的微服务主要包括统一网关(使用Ocelot开发).统一认证(IdentityServer4).应用服务(asp.net c ...

  8. Re:从 0 开始的微服务架构--(三)微服务架构 API 的开发与治理--转

    原文来自:聊聊架构公众号 前面的文章中有说到微服务的通信方式,Martin Folwer 先生在他对微服务的定义中也提到“每个服务运行在其独立的进程中,服务与服务间采用 轻量级的通信机制 互相协作(通 ...

  9. spring-boot+spring-cloud+maven-module 一个 maven多模块的微服务架构模版

    spring-boot-cloud-module spring-boot+spring-cloud+maven-module 一个 maven多模块的微服务架构模版. 新手上路的绝佳模版,只有必要的配 ...

  10. 基于.net的微服务架构的开发测试环境运维实践

    眼下,做互联网应用,最火的架构是微服务,最热的研发管理就是DevOps, 没有之一.微服务.DevOps已经被大量应用,它们已经像传说中的那样,可以无所不能.特来电云平台,通过近两年多的实践,发现完全 ...

随机推荐

  1. java.net.NoRouteToHostException: 没有到主机的路由

    今天在配置Jenkins 的云服务器的时候提示:java.net.NoRouteToHostException: 没有到主机的路由,网上查到的没有主机路由问题提到的大多是防火墙问题. 查看防火墙状态: ...

  2. ElasticSearch Python 基本操作

    创建索引 from elasticsearch import Elasticsearch es = Elasticsearch('192.168.149.96:9200') mappings = { ...

  3. 研发流程 接口定义&开发&前后端联调 线上日志观察 模型变动

    阿里等大厂的研发流程,进去前先了解一下_我们一起进大厂 - SegmentFault 思否 https://segmentfault.com/a/1190000021831640 接口定义 测试用例评 ...

  4. 等待 Redis 应答 Redis pipeline It's not just a matter of RTT

    小结: 1.When pipelining is used, many commands are usually read with a single read() system call, and ...

  5. loj10161 叶子的颜色

    CQOI 2009 给一棵有 mm 个节点的无根树,你可以选择一个度数大于 11 的节点作为根,然后给一些节点(根.内部节点.叶子均可)着以黑色或白色.你的着色方案应保证根节点到各叶子节点的简单路径上 ...

  6. 使用JSONObject解析和生成json

    创建JSON 引用org.json包,推荐通过maven引用 1.直接构建 JSONObject obj = new JSONObject(); obj.put("sex", &q ...

  7. 404 GET /nbextensions/jupyter-js-widgets/extension.js

    数据科学交流群,群号:189158789,欢迎各位对数据科学感兴趣的小伙伴的加入! 解决办法: 首先要确定你安装和配置nbextensions时有没有加--user,如果当时没加这里就不用加,否则不一 ...

  8. SonarQube+jenkins-自动化持续代码扫描

    SonarQube+jenkins-自动化持续代码扫描 1.SonarQube 1.1 SonarQube介绍 1.1.1 SonarQube 工作流程 1. 2 Docker方式安装SonarQub ...

  9. 【Android初级】如何实现一个比相册更高大上的左右滑动特效(附源码)

    在Android里面,想要实现一个类似相册的左右滑动效果,我们除了可以用Gallery.HorizontalScrollView.ViewPager等控件,还可以用一个叫做 ViewFlipper 的 ...

  10. HashMap 和 Hashtable两者的区别以和解释

    HashMap 和 Hashtable 是 Java 开发程序员必须要掌握的,也是在各种 Java 面试场合中必须会问到的. 但你对这两者的区别了解有多少呢? 现在,栈长我给大家总结一下,或许有你不明 ...