首页 文章 精选 留言 我的

精选列表

搜索[响应],共10004篇文章
优秀的个人博客,低调大师

SpringBoot2编写第一个Controller,响应你的http请求并返回结果

前言: SpringBoot的Controller模块用的是SpringMvc,所以用法和MVC没有差异。 本文章主要讲解 1.如何接收一个请求 2.如何获取请求的参数 3.常用的两种返回值JSONObject和ModelAndView 4.GET请求和POST请求 5.获取路径参数 6.HttpServletRequest和HttpServletResponse对象 编码 1.新建一个HelloController.java类,代码和结构如图所示 java 复制代码 package org.xujun.springboot.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("hello") public String hello() { return "hello springboot"; } } 运行项目,并且访问[http://127.0.0.1:8080/hello]。结果如下图所示 2.请求并带参数,添加一个方法 java 复制代码 @GetMapping("hello") public String data(String name, Integer age) { System.out.println(name); System.out.println(age); return name; } 其中name和age为参数的Key,只要Key对应上即可获取到对应的值。要注意@GetMapping("data")中的URI必须不同,不然启动会报错。 运行项目,并且访问\[http://127.0.0.1:8080/data?name=xujun?age=18]。结果如下图所示 3.常用的两种返回值ajax和ModelAndView 通常我们会有两种常用的返回值,JSONObject用于相应ajax请求,ModelAndView用于输出一HTML个是的页面 输出JSONObject 本次使用的JSONObject包为阿里巴巴的fastjson包,因此先引入fastjson的jar包 打开pom.xml添加依赖 xml 复制代码 <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency> 如图: 然后编写Controller的方法 java 复制代码 @GetMapping("json") public JSONObject json() { JSONObject data = new JSONObject(); data.put("name", "xujun"); data.put("age", 18); return data; } 运行项目,并且访问[http://127.0.0.1:8080/json]。结果如下图所示 输出ModelAndView 由于ModelAndView用于输出页面的,所以我们需要配置SpringMvc的模板解析引擎,本次采用的模板解析引擎为Freemarker(对此模板解析引擎不推荐用JSP,后期会有文章讲解如何换模板引擎),因此先要引入Freemarker引擎的jar包。 打开pom.xml添加依赖 xml 复制代码 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> 如图: 然后配置Freemarker模板解析引擎 打开application.properties添加 sh 复制代码 # Freemarker配置 # spring.freemarker.enabled : Freemarker是否启用 # spring.freemarker.template-loader-path : 载入路径 # spring.freemarker.prefix : 模板文件前缀 # spring.freemarker.suffix : 模板文件后缀 # spring.freemarker.content-type : 上下文类型 # spring.freemarker.charset : 字符编码 # spring.freemarker.settings.tag_syntax : 设置标签类型([],<>) # spring.freemarker.settings.date_format : Date格式化 # spring.freemarker.settings.time_format : Time格式化 # spring.freemarker.settings.datetime_format : Datetime格式化 spring.freemarker.enabled=true spring.freemarker.template-loader-path=classpath:/static/views/ spring.freemarker.prefix= spring.freemarker.suffix=.html spring.freemarker.content-type=text/html spring.freemarker.charset=UTF-8 spring.freemarker.settings.tag_syntax=auto_detect spring.freemarker.settings.date_format=yyyy-MM-dd spring.freemarker.settings.time_format=HH:mm:ss spring.freemarker.settings.datetime_format=yyyy-MM-dd HH:mm:ss 如图: 接着在resources/static/views编写一个Freemarker模板的html页面 新建一个index.html html 复制代码 <!DOCTYPE html> <html lang="zh-cn"> <head> <title>index</title> </head> <body> hello freemarker </body> </html> 如图: 最后编写Controller方法 java 复制代码 @GetMapping("index") public ModelAndView index() { ModelAndView mv = new ModelAndView(); mv.setViewName("index"); return mv; } 其中mv.setViewName("index");中index为模板的名字,因为前缀后缀在配置文件中已经配置,所以在此配置模板名字即可 运行项目,并且访问[http://127.0.0.1:8080/index]。结果如下图所示 4.GET请求和POST请求 由于请求方式有GET和POST,所以SpringMVC这边也有对应的注解与其对应,参考如下 @GetMapping 仅接收GET请求 @PostMapping 仅接收POST请求 @RequestMapping GET或POST请求都可接收 替换Controller方法头部对应注解即可 5.获取路径参数 有时候我们需要把URL中的某个部分取下来当作参数那就可以采用@PathVariable来绑定url参数 首先编写Controller方法 java 复制代码 @GetMapping("/list-{index}.html") public String url(@PathVariable String index) { return index; } 其中{index}为占位符,这样就可以将list-1.html中的1取出赋值到String index中。 运行项目,并且访问[http://127.0.0.1:8080/list-1.html]。结果如下图所示 6.HttpServletRequest和HttpServletResponse对象 有时候我们会在Controller中用到HttpServletRequest和HttpServletResponse对象,在Servlet中,doGet和doPost方法默认提供这两个对象,在SpringMVC中却没有。其实不然,要使用这两个对象,只要在对应的Controller方法的形参中添加这两个对象,SpringMVC就会自动注入。 如图: 总结:本文主要讲解了SpringBoot的Controller编写,由于SpringBoot采用SpringMvc框架,所以掌握SpringMvc写法即可,主要变化在于静态资源存放位置从WebContent/webapp转移到resources目录下,其他都大同小异了。

优秀的个人博客,低调大师

OnItemClickListener不响应

根原因:listview(或其他有adapter的view)没有获得焦点 列子: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"//误点一:fill_parent android:orientation="vertical" android:descendantFocusability="blocksDescendants"//误点二 > 正确应该是 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > 切记: adapter的xml的主layout(RelativeLayout)不能用fill_parent 原因有二。 一: 原因:在adapter的xml中设置了 android:descendantFocusability="blocksDescendants" 注释:下面的item就是ListView的item android:beforeFocusability viewgroup在子项处理之前获得焦点 android:afterFocusability viewGroup在子项处理之后获得焦点 android:blocksFocusability viewGroup阻止子项获得焦点(以此子项的子项就能获得焦点) 二:在layout_......设置了fill_parent, 三 Android 长按setOnItemLongClickListener 注意细节 原理是fill_parent原来就是要求本layout全屏,但listview(或其他有adapter的view)限制item的高宽。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 gridview.setOnItemLongClickListener( new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub Log.e( "setOnItemLongClickListener" , "setOnItemLongClickListener" ); return true ; } }); gridview.setOnItemClickListener( new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { Log.e( "setOnItemClickListener" , "setOnItemClickListener" ); } }); 1.如果返回false那么onItemClick仍然会被调用。而且是先调用onItemLongClick,然后调用onItemClick。 如果返回true那么click就会被吃掉,onItemClick就不会再被调用了。 2.监听onItemClick以及onItemLongClick影响弹出菜单吗? onItemClick不影响;onItemLongClick如果返回true那么就会吃掉click事件,导致菜单不能弹出。 3.如何让包含button的item也能弹出菜单,回调onItemClick以及onItemLongClick的监听器呢? 需要设置Button属性:android:focusable="false" android:focusable="false"android:longClickable="true" android:longClickable="true"否则无法收到onItemLongClick 本文转自lilin9105 51CTO博客,原文链接:http://blog.51cto.com/7071976/1216753,如需转载请自行联系原作者

优秀的个人博客,低调大师

通过 MapReduce 降低服务响应时间

在微服务中开发中,api网关扮演对外提供restful api的角色,而api的数据往往会依赖其他服务,复杂的api更是会依赖多个甚至数十个服务。虽然单个被依赖服务的耗时一般都比较低,但如果多个服务串行依赖的话那么整个api的耗时将会大大增加。 那么通过什么手段来优化呢?我们首先想到的是通过并发来的方式来处理依赖,这样就能降低整个依赖的耗时,Go基础库中为我们提供了WaitGroup工具用来进行并发控制,但实际业务场景中多个依赖如果有一个出错我们期望能立即返回而不是等所有依赖都执行完再返回结果,而且WaitGroup中对变量的赋值往往需要加锁,每个依赖函数都需要添加Add和Done对于新手来说比较容易出错 基于以上的背景,go-zero框架中为我们提供了并发处理工具MapReduce,该工具开箱即用,不需要做什么初始化,我们通过下图看下使用MapReduce和没使用的耗时对比: 相同的依赖,串行处理的话需要200ms,使用MapReduce后的耗时等于所有依赖中最大的耗时为100ms,可见MapReduce可以大大降低服务耗时,而且随着依赖的增加效果就会越明显,减少处理耗时的同时并不会增加服务器压力 并发处理工具MapReduce MapReduce是Google提出的一个软件架构,用于大规模数据集的并行运算,go-zero中的MapReduce工具正是借鉴了这种架构思想 go-zero框架中的MapReduce工具主要用来对批量数据进行并发的处理,以此来提升服务的性能 我们通过几个示例来演示MapReduce的用法 MapReduce主要有三个参数,第一个参数为generate用以生产数据,第二个参数为mapper用以对数据进行处理,第三个参数为reducer用以对mapper后的数据做聚合返回,还可以通过opts选项设置并发处理的线程数量 场景一: 某些功能的结果往往需要依赖多个服务,比如商品详情的结果往往会依赖用户服务、库存服务、订单服务等等,一般被依赖的服务都是以rpc的形式对外提供,为了降低依赖的耗时我们往往需要对依赖做并行处理 funcproductDetail(uid,pidint64)(*ProductDetail,error){ varpdProductDetail err:=mr.Finish(func()(errerror){ pd.User,err=userRpc.User(uid) return },func()(errerror){ pd.Store,err=storeRpc.Store(pid) return },func()(errerror){ pd.Order,err=orderRpc.Order(pid) return }) iferr!=nil{ log.Printf("productdetailerror:%v",err) returnnil,err } return&pd,nil } 该示例中返回商品详情依赖了多个服务获取数据,因此做并发的依赖处理,对接口的性能有很大的提升 场景二: 很多时候我们需要对一批数据进行处理,比如对一批用户id,效验每个用户的合法性并且效验过程中有一个出错就认为效验失败,返回的结果为效验合法的用户id funccheckLegal(uids[]int64)([]int64,error){ r,err:=mr.MapReduce(func(sourcechan<-interface{}){ for_,uid:=rangeuids{ source<-uid } },func(iteminterface{},writermr.Writer,cancelfunc(error)){ uid:=item.(int64) ok,err:=check(uid) iferr!=nil{ cancel(err) } ifok{ writer.Write(uid) } },func(pipe<-chaninterface{},writermr.Writer,cancelfunc(error)){ varuids[]int64 forp:=rangepipe{ uids=append(uids,p.(int64)) } writer.Write(uids) }) iferr!=nil{ log.Printf("checkerror:%v",err) returnnil,err } returnr.([]int64),nil } funccheck(uidint64)(bool,error){ //dosomethingcheckuserlegal returntrue,nil } 该示例中,如果check过程出现错误则通过cancel方法结束效验过程,并返回error整个效验过程结束,如果某个uid效验结果为false则最终结果不返回该uid MapReduce使用注意事项 mapper和reducer中都可以调用cancel,参数为error,调用后立即返回,返回结果为nil, error mapper中如果不调用writer.Write则item最终不会被reducer聚合 reducer中如果不调用writer.Wirte则返回结果为nil, ErrReduceNoOutput reducer为单线程,所有mapper出来的结果在这里串行聚合 实现原理分析: MapReduce中首先通过buildSource方法通过执行generate(参数为无缓冲channel)产生数据,并返回无缓冲的channel,mapper会从该channel中读取数据 funcbuildSource(generateGenerateFunc)chaninterface{}{ source:=make(chaninterface{}) gofunc(){ deferclose(source) generate(source) }() returnsource } 在MapReduceWithSource方法中定义了cancel方法,mapper和reducer中都可以调用该方法,调用后主线程收到close信号会立马返回 cancel:=once(func(errerror){ iferr!=nil{ retErr.Set(err) }else{ //默认的error retErr.Set(ErrCancelWithNil) } drain(source) //调用close(ouput)主线程收到Done信号,立马返回 finish() }) 在mapperDispatcher方法中调用了executeMappers,executeMappers消费buildSource产生的数据,每一个item都会起一个goroutine单独处理,默认最大并发数为16,可以通过WithWorkers进行设置 varwgsync.WaitGroup deferfunc(){ wg.Wait()//保证所有的item都处理完成 close(collector) }() pool:=make(chanlang.PlaceholderType,workers) writer:=newGuardedWriter(collector,done)//将mapper处理完的数据写入collector for{ select{ case<-done://当调用了cancel会触发立即返回 return casepool<-lang.Placeholder://控制最大并发数 item,ok:=<-input if!ok{ <-pool return } wg.Add(1) gofunc(){ deferfunc(){ wg.Done() <-pool }() mapper(item,writer)//对item进行处理,处理完调用writer.Write把结果写入collector对应的channel中 }() } } reducer单goroutine对数mapper写入collector的数据进行处理,如果reducer中没有手动调用writer.Write则最终会执行finish方法对output进行close避免死锁 gofunc(){ deferfunc(){ ifr:=recover();r!=nil{ cancel(fmt.Errorf("%v",r)) }else{ finish() } }() reducer(collector,writer,cancel) }() 在该工具包中还提供了许多针对不同业务场景的方法,实现原理与MapReduce大同小异,感兴趣的同学可以查看源码学习 MapReduceVoid 功能和MapReduce类似但没有结果返回只返回error Finish 处理固定数量的依赖,返回error,有一个error立即返回 FinishVoid 和Finish方法功能类似,没有返回值 Map 只做generate和mapper处理,返回channel MapVoid 和Map功能类似,无返回 本文主要介绍了go-zero框架中的MapReduce工具,在实际的项目中非常实用。用好工具对于提升服务性能和开发效率都有很大的帮助,希望本篇文章能给大家带来一些收获。 项目地址 github.com/tal-tech/go-zero 欢迎使用 go-zero 并 star 支持我们! 微信交流群 关注『微服务实践』公众号并回复 进群 获取社区群二维码。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册