স্প্রিং বুট যুক্ত এইচটিটিপি অনুরোধ ইন্টারসেপ্টর


107

বসন্ত বুট অ্যাপ্লিকেশনটিতে HTTPRequest ইন্টারসেপ্টর যুক্ত করার সঠিক উপায় কী? আমি যা করতে চাই তা হ'ল প্রতিটি http অনুরোধের লগ অনুরোধ এবং প্রতিক্রিয়া।

স্প্রিং বুট ডকুমেন্টেশন এ বিষয়টিকে মোটেই আচ্ছাদন করে না। ( http://docs.spring.io/spring-boot/docs/current/references/htmlsingle/ )

বসন্তের পুরানো সংস্করণগুলির সাথে কীভাবে একই কাজ করা যায় সে সম্পর্কে আমি কিছু ওয়েব নমুনা পেয়েছি, তবে সেগুলি অ্যাপ্লিকেশনকন্টেক্সট.এমএমএল নিয়ে কাজ করে। সাহায্য করুন.


হাই @ ishষিপ 89 ... আমি HandlerInterceptorসফলভাবে প্রয়োগ করেছি । এটা ঠিক কাজ করছে। কেবল সমস্যাটি হ'ল, internal HandlerInterceptorএটি দ্বারা পরিচালিত হওয়ার আগে কেউ কেউ ব্যতিক্রম ছুঁড়ে মারে custom HandlerInterceptorafterCompletion()পরে ত্রুটি HandlerInterceptor অভ্যন্তরীণ বাস্তবায়ন দ্বারা নিক্ষিপ্ত হয় পদ্ধতি যা উপেক্ষিত বলা হয়। আপনি কি এই জন্য সমাধান আছে?
চেতন ওসওয়াল

উত্তর:


155

যেহেতু আপনি স্প্রিং বুট ব্যবহার করছেন, আমি ধরে নিয়েছি আপনি যেখানে সম্ভব সেখানে স্প্রিংয়ের অটো কনফিগারেশনের উপর নির্ভর করতে পছন্দ করেন। আপনার ইন্টারসেপ্টরের মতো অতিরিক্ত কাস্টম কনফিগারেশন যুক্ত করতে, কেবল একটি কনফিগারেশন বা বিন এর সরবরাহ করুন WebMvcConfigurerAdapter

এখানে একটি কনফিগার শ্রেণীর উদাহরণ রয়েছে:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

  @Autowired 
  HandlerInterceptor yourInjectedInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(...)
    ...
    registry.addInterceptor(getYourInterceptor()); 
    registry.addInterceptor(yourInjectedInterceptor);
    // next two should be avoid -- tightly coupled and not very testable
    registry.addInterceptor(new YourInterceptor());
    registry.addInterceptor(new HandlerInterceptor() {
        ...
    });
  }
}

দ্রষ্টব্য , আপনি যদি এমভিসি-র জন্য স্প্রিং বুটস অটো কনফিগারেশন রাখতে চান তবে এটি @EableWebMvc- এর মাধ্যমে এটিকে টীকায়িত করবেন না ।


নিস! ভাল লাগছে! রেজিস্ট্রি.এইডিআইন্টারসেপ্টারে (...) ভিতরে যা যায় তার কোনও উদাহরণ? "..." এর একটি নমুনা জানতে আগ্রহী
ishষিপি 89

6
আপনার ইনজেক্টেড ইন্সেপ্টারে কমপিউটার টিকা ব্যবহার করুন
পাওলো বিয়াবতি

1
@ ishষিপ 89 এই উদাহরণটির জন্য দেখুন: এমকিওং
ভ্লাদ ম্যানুয়েল

4
আমি ভুল পান The type WebMvcConfigurerAdapter is deprecated। আমি স্প্রিং ওয়েব এমভিসি 5.0.6
জন হেন্কেল

7
স্প্রিং 5 এ, কেবল ওয়েবএমভিসি কনফিগুরির অ্যাডাপ্টার বাড়ানোর পরিবর্তে ওয়েবএমভিসি কনফিগারার বাস্তবায়ন করুন। যেহেতু জাভা 8 ইন্টারফেসগুলি ডিফল্ট প্রয়োগগুলি মঞ্জুর করে, তাই অ্যাডাপ্টারের ব্যবহারের আর প্রয়োজন হয় না (যার কারণে এটি অবনমিত হয়)।
এডগ্রাফ

88

WebMvcConfigurerAdapterস্প্রিং 5 এর সাথে অবমূল্যায়ন করা হবে এর জাভাডোক থেকে :

@ 5.0 হিসাবে নির্ধারিত {@ লিঙ্ক ওয়েবএমভিসি কনফিগারার default এর ডিফল্ট পদ্ধতি রয়েছে (একটি জাভা 8 বেসলাইন দ্বারা সম্ভব হয়েছে) এবং এই অ্যাডাপ্টারের প্রয়োজন ছাড়াই সরাসরি প্রয়োগ করা যেতে পারে

উপরে উল্লিখিত হিসাবে, আপনার কী করা উচিত তা হ'ল পদ্ধতি বাস্তবায়ন WebMvcConfigurerএবং ওভাররাইড addInterceptors

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyCustomInterceptor());
    }
}

10
কারণ এটি বাস্তবায়নের অনুপস্থিত আপনার উত্তর অসম্পূর্ণMyCustomInterceptor
peterchaula

33

একটি বসন্ত বুট অ্যাপ্লিকেশনটিতে ইন্টারসেপটর যুক্ত করতে, নিম্নলিখিতটি করুন

  1. একটি ইন্টারসেপ্টর ক্লাস তৈরি করুন

    public class MyCustomInterceptor implements HandlerInterceptor{
    
        //unimplemented methods comes here. Define the following method so that it     
        //will handle the request before it is passed to the controller.
    
        @Override
        public boolean preHandle(HttpServletRequest request,HttpServletResponse  response){
        //your custom logic here.
            return true;
        }
    }
  2. একটি কনফিগারেশন ক্লাস সংজ্ঞায়িত করুন

    @Configuration
    public class MyConfig extends WebMvcConfigurerAdapter{
        @Override
        public void addInterceptors(InterceptorRegistry registry){
            registry.addInterceptor(new MyCustomInterceptor()).addPathPatterns("/**");
        }
    }
  3. এটাই. এখন আপনার সমস্ত অনুরোধগুলি মাই কাস্টমআইন্টারসেপ্টরের প্রি হ্যান্ডেল () পদ্ধতির অধীনে সংজ্ঞায়িত যুক্তির মধ্য দিয়ে যাবে।


1
কিছু সাধারণ বৈধতা করার জন্য সাইনআপ অনুরোধগুলি আমার অ্যাপ্লিকেশনটিতে এসে বাধা দেওয়ার জন্য আমি এই পথ অনুসরণ করেছি। তবে সমস্যাটি হচ্ছে আমি getReader() has already been called for this requestত্রুটি পেয়েছি। আসল অনুরোধের একটি অনুলিপি ব্যবহার না করে এ থেকে ওঠার সহজ উপায় কি আছে?
উইগমেজে

প্রি-হ্যান্ডলারটি যখন ডাকা হয়, তখন অনুরোধের বডিটি উপলব্ধ হয় না, তবে কেবলমাত্র পরামিতি থাকে, অনুরোধের বডিটিতে বৈধতা দেওয়ার জন্য, পছন্দসই উপায় হ'ল Aspect J ব্যবহার করে তৈরি করাAdvice
হিমা

12

যেহেতু এর সমস্ত প্রতিক্রিয়াগুলি এখন ওয়েবএমভিসিআইন্টারফেসের পরিবর্তে (দীর্ঘমেয়াদী @sebdooe দ্বারা উল্লিখিত) এখনকার দীর্ঘ-অবমানিত বিমূর্ত ওয়েবএমভিসি কনফিগারার অ্যাডাপ্টারের ব্যবহার করে, তাই এখানে একটি ইন্টারসেপ্টর সহ স্প্রিংবুট (২.১.৪) অ্যাপ্লিকেশনটির জন্য একটি সর্বনিম্ন উদাহরণ রয়েছে:

Minimal.java:

@SpringBootApplication
public class Minimal
{
    public static void main(String[] args)
    {
        SpringApplication.run(Minimal.class, args);
    }
}

MinimalController.java:

@RestController
@RequestMapping("/")
public class Controller
{
    @GetMapping("/")
    @ResponseBody
    public ResponseEntity<String> getMinimal()
    {
        System.out.println("MINIMAL: GETMINIMAL()");

        return new ResponseEntity<String>("returnstring", HttpStatus.OK);
    }
}

Config.java:

@Configuration
public class Config implements WebMvcConfigurer
{
    //@Autowired
    //MinimalInterceptor minimalInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(new MinimalInterceptor());
    }
}

MinimalInterceptor.java:

public class MinimalInterceptor extends HandlerInterceptorAdapter
{
    @Override
    public boolean preHandle(HttpServletRequest requestServlet, HttpServletResponse responseServlet, Object handler) throws Exception
    {
        System.out.println("MINIMAL: INTERCEPTOR PREHANDLE CALLED");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
    {
        System.out.println("MINIMAL: INTERCEPTOR POSTHANDLE CALLED");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception
    {
        System.out.println("MINIMAL: INTERCEPTOR AFTERCOMPLETION CALLED");
    }
}

বিজ্ঞাপন হিসাবে কাজ করে

আউটপুট আপনাকে এমন কিছু দেবে:

> Task :Minimal.main()

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.4.RELEASE)

2019-04-29 11:53:47.560  INFO 4593 --- [           main] io.minimal.Minimal                       : Starting Minimal on y with PID 4593 (/x/y/z/spring-minimal/build/classes/java/main started by x in /x/y/z/spring-minimal)
2019-04-29 11:53:47.563  INFO 4593 --- [           main] io.minimal.Minimal                       : No active profile set, falling back to default profiles: default
2019-04-29 11:53:48.745  INFO 4593 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-04-29 11:53:48.780  INFO 4593 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-04-29 11:53:48.781  INFO 4593 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.17]
2019-04-29 11:53:48.892  INFO 4593 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-04-29 11:53:48.893  INFO 4593 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1269 ms
2019-04-29 11:53:49.130  INFO 4593 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-04-29 11:53:49.375  INFO 4593 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-04-29 11:53:49.380  INFO 4593 --- [           main] io.minimal.Minimal                       : Started Minimal in 2.525 seconds (JVM running for 2.9)
2019-04-29 11:54:01.267  INFO 4593 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-04-29 11:54:01.267  INFO 4593 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-04-29 11:54:01.286  INFO 4593 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 19 ms
MINIMAL: INTERCEPTOR PREHANDLE CALLED
MINIMAL: GETMINIMAL()
MINIMAL: INTERCEPTOR POSTHANDLE CALLED
MINIMAL: INTERCEPTOR AFTERCOMPLETION CALLED

তবে এর জন্য আপনাকে ওয়েবএমভিসি কনফিগারার থেকে সমস্ত পদ্ধতি প্রয়োগ করতে হবে, তাই না?
স্টিভেন

না, এটির একটি (জাভা 8) খালি ডিফল্ট বাস্তবায়নগুলির সাথে ইন্টারফেস
টম

9

আমার ওয়েবএমভিসি কনফিগুরির অ্যাডাপ্টারটিকে হ্রাস করা একই সমস্যা ছিল। আমি উদাহরণগুলি অনুসন্ধান করার সময়, আমি খুব কমই প্রয়োগ করা কোড খুঁজে পেলাম। এখানে ওয়ার্কিং কোডের একটি অংশ রয়েছে।

একটি ক্লাস তৈরি করুন যা হ্যান্ডলারআইন্টারসেপ্টর অ্যাডাপ্টার প্রসারিত করে

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import me.rajnarayanan.datatest.DataTestApplication;
@Component
public class EmployeeInterceptor extends HandlerInterceptorAdapter {
    private static final Logger logger = LoggerFactory.getLogger(DataTestApplication.class);
    @Override
    public boolean preHandle(HttpServletRequest request, 
            HttpServletResponse response, Object handler) throws Exception {

            String x = request.getMethod();
            logger.info(x + "intercepted");
        return true;
    }

}

তারপরে WebMvcConfigurer ইন্টারফেস প্রয়োগ করুন

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import me.rajnarayanan.datatest.interceptor.EmployeeInterceptor;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    EmployeeInterceptor employeeInterceptor ;

    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(employeeInterceptor).addPathPatterns("/employee");
    }
}

4
সংকলন সমস্যা ছাড়াই আপনি কীভাবে কেবল একটি ইন্টারফেসে একটি পদ্ধতিকে ওভাররাইড করতে পারেন?
xetra11

1
@ xetra11 আমি এই ক্ষেত্রে ব্যবহার না করা অন্যান্য সমস্ত পদ্ধতির পরিবর্তে কেবল একটি পদ্ধতি প্রয়োগ করতে পারি কিনা তা দেখার চেষ্টা করছি। এটা কি সম্ভব? আপনি কি এটি বুঝতে পেরেছেন?
ব্যবহারকারী09

3
@arjun অন্যদের হিসাবে প্রয়োগ করা হয় ডিফল্ট পদ্ধতি এই যুক্তি হল, সুবিধামত, জাভা 8. ধন্যবাদ নথিভুক্ত অননুমোদিত ক্লাসে।
বব

7

আপনি ওপেন সোর্স স্প্রিংস্যান্ডউইচ লাইব্রেরিটি ব্যবহার করেও বিবেচনা করতে পারেন যা আপনাকে আপনার স্প্রিং বুট কন্ট্রোলারে সরাসরি টীকা দিতে দেয় যা ইন্টারসেপ্টরগুলি প্রয়োগ করতে পারে, একইভাবে আপনি নিজের ইউআরএল রুটগুলি টিকিয়ে রাখেন।

এইভাবে, চারপাশে ভাসমান কোনও টাইপো-প্রোন স্ট্রিং নেই - স্প্রিংসানডউইচের পদ্ধতি এবং শ্রেণীর টিকাগুলি সহজেই রিফ্যাক্টরিংয়ে বেঁচে থাকে এবং কোথায় কী প্রয়োগ করা হচ্ছে তা পরিষ্কার করে দেয়। (প্রকাশ: আমি লেখক)

http://springsandwich.com/


দারুণ লাগছে! আমি সিআইয়ের অধীনে যে প্রকল্পগুলি নির্মাণ করছে বা হিরোকু দিয়ে মোতায়েন করছে তাদের প্রকল্পগুলির জন্য সহজতর করার জন্য স্প্রিংসানডউইচকে মভেন সেন্ট্রালে উপলব্ধ থাকার জন্য জিজ্ঞাসা করে একটি সমস্যা তৈরি করেছি।
ব্রেন্ডন ডুগান

গ্রেট। এটি কি মাভেন কেন্দ্রীয় ভান্ডারগুলিতে পাওয়া যায়? আপনার গিট সংগ্রহস্থল এবং রেফারেন্সের রেফারেন্স সহ আমার ওয়েবসাইটে পুনরায় ব্লগিং স্প্রিংসডউইচ ডটকম
অর্পণ দাশ

1
স্প্রিংসস্যান্ডউইচ এখন মাভেন সেন্ট্রাল
ম্যাগনাস

1

নীচে আমি প্রতিটি HTTP অনুরোধটি বেরোনোর ​​আগে এবং প্রতিক্রিয়াটি ফিরে আসার আগে আটকাতে ব্যবহার করি implementation এই প্রয়োগের সাথে সাথে আমার একটি একক পয়েন্টও রয়েছে যেখানে আমি অনুরোধের সাথে কোনও শিরোনামের মানটি পাস করতে পারি।

public class HttpInterceptor implements ClientHttpRequestInterceptor {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public ClientHttpResponse intercept(
        HttpRequest request, byte[] body,
        ClientHttpRequestExecution execution
) throws IOException {
    HttpHeaders headers = request.getHeaders();
    headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
    headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
    traceRequest(request, body);
    ClientHttpResponse response = execution.execute(request, body);
    traceResponse(response);
    return response;
}

private void traceRequest(HttpRequest request, byte[] body) throws IOException {
    logger.info("===========================Request begin======================================");
    logger.info("URI         : {}", request.getURI());
    logger.info("Method      : {}", request.getMethod());
    logger.info("Headers     : {}", request.getHeaders() );
    logger.info("Request body: {}", new String(body, StandardCharsets.UTF_8));
    logger.info("==========================Request end=========================================");
}

private void traceResponse(ClientHttpResponse response) throws IOException {
    logger.info("============================Response begin====================================");
    logger.info("Status code  : {}", response.getStatusCode());
    logger.info("Status text  : {}", response.getStatusText());
    logger.info("Headers      : {}", response.getHeaders());
    logger.info("=======================Response end===========================================");
}}

নীচে বিশিষ্ট টেম্পলেট বিন

@Bean
public RestTemplate restTemplate(HttpClient httpClient)
{
    HttpComponentsClientHttpRequestFactory requestFactory =
            new HttpComponentsClientHttpRequestFactory();
    requestFactory.setHttpClient(httpClient);
    RestTemplate restTemplate=  new RestTemplate(requestFactory);
    List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
    if (CollectionUtils.isEmpty(interceptors))
    {
        interceptors = new ArrayList<>();
    }
    interceptors.add(new HttpInterceptor());
    restTemplate.setInterceptors(interceptors);

    return restTemplate;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.