বসন্তে ফিল্টারগুলিতে নিক্ষিপ্ত ব্যতিক্রমগুলি কীভাবে পরিচালনা করবেন?


119

আমি 5XX ত্রুটি কোডগুলি পরিচালনা করার জন্য জেনেরিক উপায়টি ব্যবহার করতে চাই, আসুন বিশেষত কেসটি যখন আমার পুরো বসন্তের অ্যাপ্লিকেশন জুড়ে থাকে তখন কেসটি বলে। আমি একটি স্ট্যাক ট্রেস পরিবর্তে একটি সুন্দর ত্রুটি json চাই।

কন্ট্রোলারদের জন্য আমার @ControllerAdviceআলাদা ব্যতিক্রমগুলির জন্য একটি ক্লাস রয়েছে এবং এটি ডিবি অনুরোধের মাঝামাঝি স্থানে থামছে এমনটিও ধরা পড়ছে। তবে এটি সব নয়। আমি একটি কাস্টম CorsFilterপ্রসারিত করতে OncePerRequestFilterএবং সেখানে যখন আমি কল doFilterকরি আমি পাই CannotGetJdbcConnectionExceptionএবং এটি দ্বারা পরিচালিত হবে না happen@ControllerAdvice । আমি অনলাইনে বেশ কয়েকটি জিনিস পড়েছি যা আমাকে আরও বিভ্রান্ত করেছে।

সুতরাং আমার অনেক প্রশ্ন আছে:

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

এটি মোকাবেলার জন্য কোনও ভাল উপায় আছে? ধন্যবাদ


4
আমরা স্প্রিং বুটের বেসিক এররার কন্ট্রোলারকে ওভাররাইড করতে পারি। আমি এটি সম্পর্কে এখানে ব্লগ করেছি: Naturalprogrammer.com/blog/1685463/…
সঞ্জয়

উত্তর:


92

সুতরাং আমি এই কি করেছি:

আমি এখানে ফিল্টারগুলি সম্পর্কে বেসিকগুলি পড়েছি এবং আমি বুঝতে পেরেছিলাম যে আমাকে একটি কাস্টম ফিল্টার তৈরি করতে হবে যা ফিল্টার চেইনে প্রথম হবে এবং সেখানে ঘটে যাওয়া সমস্ত রানটাইম ব্যতিক্রমগুলি ধরার চেষ্টা করব catch তারপরে আমি নিজে নিজে জসন তৈরি করে প্রতিক্রিয়াতে রেখেছি।

সুতরাং এখানে আমার কাস্টম ফিল্টার:

public class ExceptionHandlerFilter extends OncePerRequestFilter {

    @Override
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            filterChain.doFilter(request, response);
        } catch (RuntimeException e) {

            // custom error response class used across my project
            ErrorResponse errorResponse = new ErrorResponse(e);

            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            response.getWriter().write(convertObjectToJson(errorResponse));
    }
}

    public String convertObjectToJson(Object object) throws JsonProcessingException {
        if (object == null) {
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(object);
    }
}

এবং তারপরে আমি এটির আগে ওয়েব.এক্সএমএল এ যুক্ত করেছি CorsFilter। এবং এটি কাজ করে!

<filter> 
    <filter-name>exceptionHandlerFilter</filter-name> 
    <filter-class>xx.xxxxxx.xxxxx.api.controllers.filters.ExceptionHandlerFilter</filter-class> 
</filter> 


<filter-mapping> 
    <filter-name>exceptionHandlerFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

<filter> 
    <filter-name>CorsFilter</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 

<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

আপনি কি আপনার ত্রুটিপূর্বক শ্রেণি পোস্ট করতে পারেন?
শিব কুমার

4
@ শিভাকুমার ত্রুটি রিসপন্স ক্লাসটি সম্ভবত একটি সাধারণ ডিটিও যা সাধারণ কোড / বার্তার বৈশিষ্ট্যযুক্ত।
রতিজাস

35

আমি @ কোপেলিতসার উত্তরের ভিত্তিতে একটি সমাধান সরবরাহ করতে চেয়েছিলাম । প্রধান পার্থক্য হচ্ছে:

  1. ব্যবহার করে নিয়ামক ব্যতিক্রম হ্যান্ডলিং পুনরায় ব্যবহার HandlerExceptionResolver
  2. এক্সএমএল কনফিগারেশনের মাধ্যমে জাভা কনফিগারেশন ব্যবহার করা হচ্ছে

প্রথমত, আপনাকে অবশ্যই নিশ্চিত করতে হবে যে আপনার একটি ক্লাস রয়েছে যা নিয়মিত রেস্ট কন্ট্রোলার / কন্ট্রোলার (যেটি দিয়ে বর্ণিত @RestControllerAdviceবা @ControllerAdviceপদ্ধতিতে বর্ণিত একটি শ্রেণি) তে ঘটে যাওয়া ব্যতিক্রমগুলি পরিচালনা করে @ExceptionHandler। এটি একটি নিয়ামক হিসাবে ঘটে যাওয়া আপনার ব্যতিক্রমগুলি পরিচালনা করে। রেস্ট কন্ট্রোলার অ্যাডভাইস ব্যবহার করে এখানে একটি উদাহরণ দেওয়া হল:

@RestControllerAdvice
public class ExceptionTranslator {

    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorDTO processRuntimeException(RuntimeException e) {
        return createErrorDTO(HttpStatus.INTERNAL_SERVER_ERROR, "An internal server error occurred.", e);
    }

    private ErrorDTO createErrorDTO(HttpStatus status, String message, Exception e) {
        (...)
    }
}

স্প্রিং সিকিউরিটি ফিল্টার চেইনে এই আচরণটির পুনঃব্যবহার করতে আপনাকে একটি ফিল্টার সংজ্ঞায়িত করতে হবে এবং আপনার সুরক্ষা কনফিগারেশনে এটি আবদ্ধ করতে হবে। ফিল্টারটিকে উপরের সংজ্ঞায়িত ব্যতিক্রম হ্যান্ডলিংয়ে ব্যতিক্রম পুনর্নির্দেশ করা দরকার। এখানে একটি উদাহরণ:

@Component
public class FilterChainExceptionHandler extends OncePerRequestFilter {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        try {
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            log.error("Spring Security Filter Chain Exception:", e);
            resolver.resolveException(request, response, null, e);
        }
    }
}

তারপরে তৈরি ফিল্টারটি সিকিউরিটি কনফিগারেশনে যুক্ত করা দরকার। আপনাকে খুব তাড়াতাড়ি শৃঙ্খলে আটকানো দরকার, কারণ সমস্ত পূর্ববর্তী ফিল্টার ব্যতিক্রম ধরা পড়বে না। আমার ক্ষেত্রে এটির আগে যুক্ত করা যুক্তিসঙ্গত ছিল LogoutFilterঅফিসিয়াল ডক্সে ডিফল্ট ফিল্টার চেইন এবং তার ক্রম দেখুন । এখানে একটি উদাহরণ:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private FilterChainExceptionHandler filterChainExceptionHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(filterChainExceptionHandler, LogoutFilter.class)
            (...)
    }

}

প্রতিশ্রুতিবদ্ধ মনে হচ্ছে ... বৈধতা প্রদানকারীদের দ্বারা নিক্ষিপ্ত ব্যতিক্রমগুলি পরিচালনা করতে আপনি কীভাবে এটি সংশোধন করবেন ? তারা চালানোর আগেController
হনজা জিদেক

FilterChainExceptionHandlerকেবল রানটাইম ব্যতিক্রমগুলির জন্য কাজ করবে। চেক করা ব্যতিক্রমগুলির জন্য কী করবেন যেমন MethodArgumentNotValidException, ServletRequestBindingException.etc
আয়মান প্যাটেল

4
আপনি আমার দিনকে অনেক ধন্যবাদ জানিয়েছিলেন, আমি এর সাথে মোকাবিলা করার জন্য অনেক সময় ব্যয় করেছি কিন্তু শেষে আমি এটি দেখেছি এবং এটি দুর্দান্ত কাজ করেছে
Az.MaYo

19

আমি নিজেই এই সমস্যাটি জুড়ে এসেছি এবং একটি নিবন্ধিত ফিল্টার নিক্ষেপ ExceptionControllerকরার @ControllerAdviseজন্য আমার সাথে মন্তব্য করা আমার পুনঃব্যবহারের জন্য নীচের পদক্ষেপগুলি সম্পাদন করেছি Exceptions

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

{
  "status": 400,
  "message": "some exception thrown when executing the request"
}

যাইহোক, আমি আমার ব্যবহার করতে সক্ষম হয়েছি ExceptionHandlerএবং পদক্ষেপে নীচে প্রদর্শিত হিসাবে আমাকে কিছুটা অতিরিক্ত করতে হয়েছিল:

পদক্ষেপ


  1. আপনার একটি কাস্টম ফিল্টার রয়েছে যা ব্যতিক্রম ছুঁড়ে ফেলতে পারে বা নাও পারে
  2. আপনার কাছে একটি স্প্রিং কন্ট্রোলার রয়েছে যা @ControllerAdviseঅর্থ MyExceptionController ব্যবহার করে ব্যতিক্রমগুলি পরিচালনা করে

কোডের উদাহরণ

//sample Filter, to be added in web.xml
public MyFilterThatThrowException implements Filter {
   //Spring Controller annotated with @ControllerAdvise which has handlers
   //for exceptions
   private MyExceptionController myExceptionController; 

   @Override
   public void destroy() {
        // TODO Auto-generated method stub
   }

   @Override
   public void init(FilterConfig arg0) throws ServletException {
       //Manually get an instance of MyExceptionController
       ApplicationContext ctx = WebApplicationContextUtils
                  .getRequiredWebApplicationContext(arg0.getServletContext());

       //MyExceptionHanlder is now accessible because I loaded it manually
       this.myExceptionController = ctx.getBean(MyExceptionController.class); 
   }

   @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        try {
           //code that throws exception
        } catch(Exception ex) {
          //MyObject is whatever the output of the below method
          MyObject errorDTO = myExceptionController.handleMyException(req, ex); 

          //set the response object
          res.setStatus(errorDTO .getStatus());
          res.setContentType("application/json");

          //pass down the actual obj that exception handler normally send
          ObjectMapper mapper = new ObjectMapper();
          PrintWriter out = res.getWriter(); 
          out.print(mapper.writeValueAsString(errorDTO ));
          out.flush();

          return; 
        }

        //proceed normally otherwise
        chain.doFilter(request, response); 
     }
}

এবং এখন নমুনা স্প্রিং কন্ট্রোলার যা Exceptionসাধারণ ক্ষেত্রে পরিচালনা করে (যেমন ব্যতিক্রমগুলি সাধারণত ফিল্টার স্তরে নিক্ষেপ করা হয় না, আমরা ফিল্টারে ফেলে দেওয়া ব্যতিক্রমগুলির জন্য ব্যবহার করতে পারি)

//sample SpringController 
@ControllerAdvice
public class ExceptionController extends ResponseEntityExceptionHandler {

    //sample handler
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ExceptionHandler(SQLException.class)
    public @ResponseBody MyObject handleSQLException(HttpServletRequest request,
            Exception ex){
        ErrorDTO response = new ErrorDTO (400, "some exception thrown when "
                + "executing the request."); 
        return response;
    }
    //other handlers
}

ফিল্টার নিক্ষেপের ExceptionControllerজন্য যারা ব্যবহার করতে চান তাদের সাথে সমাধান ভাগ করে নেওয়া Exceptions


10
ঠিক আছে, আপনার নিজের সমাধানটি ভাগ করে নিতে স্বাগতম যা এটি করার উপায় বলে মনে হচ্ছে :)
রাফ

4
আপনি যদি নিজের ফিল্টারটিতে একটি নিয়ামকযুক্ত ওয়্যার্ড করা এড়াতে চান (যা এটি @ বাটো-বৈয়ারসায়ারেনভ বলে ধরে নিয়েছে) তবে আপনি সহজেই যুক্তিটি বের করতে পারেন যেখানে আপনি ত্রুটি ডিটিও তৈরি করেছেন তার নিজের @Componentশ্রেণিতে এবং ফিল্টারটিতে এবং এর মধ্যে এটি ব্যবহার করতে পারেন নিয়ামক।
রেডিগার স্কুল্জ

4
আমি আপনার সাথে পুরোপুরি একমত নই, কারণ এটি আপনার ফিল্টারটিতে একটি নির্দিষ্ট নিয়ামক ইনজেকশনের পক্ষে খুব পরিষ্কার নয়।
psv

এর মধ্যে যেমন উল্লেখ করা হয়েছে সেগুলির answerএকটি উপায়! আমি দাবি করি নি যে এটি সবচেয়ে ভাল উপায় way আপনার উদ্বেগকে ভাগ করে নেওয়ার জন্য আপনাকে ধন্যবাদ @psv আমি নিশ্চিত যে আপনার মনে যে সমাধান রয়েছে তা সম্প্রদায় প্রশংসা করবে :)
রাফ

12

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

আমি যে সহজ সমাধানটি সন্ধান করতে পারি তা হ'ল ব্যতিক্রম হ্যান্ডলারটি একা রেখে যাওয়া, এবং নিম্নলিখিত হিসাবে একটি ত্রুটি নিয়ন্ত্রণকারী প্রয়োগ করা:

@Controller
public class ErrorControllerImpl implements ErrorController {
  @RequestMapping("/error")
  public void handleError(HttpServletRequest request) throws Throwable {
    if (request.getAttribute("javax.servlet.error.exception") != null) {
      throw (Throwable) request.getAttribute("javax.servlet.error.exception");
    }
  }
}

সুতরাং, ব্যতিক্রমগুলির ফলে ঘটে যাওয়া কোনও ত্রুটি প্রথমে ErrorControllerএকটি @Controllerপ্রসঙ্গে থেকে পুনর্বিবেচনা করে ব্যতিক্রম হ্যান্ডলারের কাছে পুনঃনির্দেশিত হয় , অন্য কোনও ত্রুটি (সরাসরি কোনও ব্যতিক্রমের কারণে ঘটে না) এর মধ্য দিয়ে যায়ErrorController কোনও পরিবর্তন ছাড়াই ।

এটি আসলে একটি খারাপ ধারণা কেন কোনও কারণ?


4
ধন্যবাদ এখন এই সমাধানটি পরীক্ষা করার জন্য তবে আমার ক্ষেত্রে নিখুঁতভাবে কাজ করুন।
ম্যাকিয়েজ

স্প্রিং বুট @Override public String getErrorPath() { return null; }
২.০++ এর

4
আপনি "javax.servlet.error.exception" এর পরিবর্তে javax.servlet.RequestDispatcher.ERROR_EXCEPTION ব্যবহার করতে পারেন
মার্কস

9

আপনি যদি জেনেরিক উপায় চান তবে আপনি ওয়েব.এক্সএমএলে একটি ত্রুটি পৃষ্ঠাটি সংজ্ঞায়িত করতে পারেন:

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/500</location>
</error-page>

এবং স্প্রিং এমভিসিতে ম্যাপিং যুক্ত করুন:

@Controller
public class ErrorController {

    @RequestMapping(value="/500")
    public @ResponseBody String handleException(HttpServletRequest req) {
        // you can get the exception thrown
        Throwable t = (Throwable)req.getAttribute("javax.servlet.error.exception");

        // customize response to what you want
        return "Internal server error.";
    }
}

তবে বিশ্রামে এপিআই লোকেশনটির সাথে পুনঃনির্দেশ করা ভাল সমাধান নয়।
jmattheis

@ jmattheis উপরেরটি পুনর্নির্দেশ নয়।
holmis83

সত্য, আমি অবস্থানটি দেখেছি এবং ভেবেছিলাম এটির HTTP অবস্থানের সাথে কিছু করতে হবে। তারপরে এটি আমার দরকার (:
jmattheis

আপনি জাভা কনফিগারেশনকে ওয়েব.এক্সএমএল এর সমতুল্য যুক্ত করতে পারেন, যদি এটি বিদ্যমান থাকে?
কে-ডেন

4
@ কে-ডেন আমি মনে করি বর্তমান অনুমানের সাথে জাভা কনফিগারেশনের সমতুল্য নেই তবে আপনি ওয়েব.এক্সএমএল এবং জাভা কনফিগার করতে পারেন।
holmis83

5

এটি ডিফল্ট স্প্রিং বুট / ত্রুটি হ্যান্ডলারকে ওভাররাইড করে আমার সমাধান

package com.mypackage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * This controller is vital in order to handle exceptions thrown in Filters.
 */
@RestController
@RequestMapping("/error")
public class ErrorController implements org.springframework.boot.autoconfigure.web.ErrorController {

    private final static Logger LOGGER = LoggerFactory.getLogger(ErrorController.class);

    private final ErrorAttributes errorAttributes;

    @Autowired
    public ErrorController(ErrorAttributes errorAttributes) {
        Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
        this.errorAttributes = errorAttributes;
    }

    @Override
    public String getErrorPath() {
        return "/error";
    }

    @RequestMapping
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest aRequest, HttpServletResponse response) {
        RequestAttributes requestAttributes = new ServletRequestAttributes(aRequest);
        Map<String, Object> result =     this.errorAttributes.getErrorAttributes(requestAttributes, false);

        Throwable error = this.errorAttributes.getError(requestAttributes);

        ResponseStatus annotation =     AnnotationUtils.getAnnotation(error.getClass(), ResponseStatus.class);
        HttpStatus statusCode = annotation != null ? annotation.value() : HttpStatus.INTERNAL_SERVER_ERROR;

        result.put("status", statusCode.value());
        result.put("error", statusCode.getReasonPhrase());

        LOGGER.error(result.toString());
        return new ResponseEntity<>(result, statusCode) ;
    }

}

এটি কোনও অটো কনফিগারেশন প্রভাবিত করে?
সামেট বাস্কেসি

নোট করুন যে হ্যান্ডলারএক্সেপশন রিসোলভার অগত্যা ব্যতিক্রমটি পরিচালনা করে না। সুতরাং এটি HTTP 200 হিসাবে পড়তে পারে calling প্রতিক্রিয়া.সেটাস্টাস (..) ব্যবহার করার আগে এটি নিরাপদ বলে মনে হচ্ছে।
টমাসআরএস

5

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

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

যেমন


@ControllerAdvice
@RestController
public class GlobalErrorHandler implements ErrorController {

  @ResponseStatus(HttpStatus.BAD_REQUEST)
  @ExceptionHandler(ValidationException.class)
  public Error handleValidationException(
      final ValidationException validationException) {
    return new Error("400", "Incorrect params"); // whatever
  }

  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  @ExceptionHandler(Exception.class)
  public Error handleUnknownException(final Exception exception) {
    return new Error("500", "Unexpected error processing request");
  }

  @RequestMapping("/error")
  public ResponseEntity handleError(final HttpServletRequest request,
      final HttpServletResponse response) {

    Object exception = request.getAttribute("javax.servlet.error.exception");

    // TODO: Logic to inspect exception thrown from Filters...
    return ResponseEntity.badRequest().body(new Error(/* whatever */));
  }

  @Override
  public String getErrorPath() {
    return "/error";
  }

}

3

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

বাস্তবায়নে বিভিন্ন শর্ত হতে পারে। আমার ক্ষেত্রে অ্যাপ্লিকেশন প্রস্তুত থাকলে অ্যাপ্লিকেশন ম্যানেজার পরীক্ষা করে।

import ...ApplicationManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class SystemIsReadyFilter implements Filter {

    @Autowired
    private ApplicationManager applicationManager;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (!applicationManager.isApplicationReady()) {
            ((HttpServletResponse) response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "The service is booting.");
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {}
}

2

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

আমি একটি কাস্টম ফিল্টার তৈরি করেছি এবং অ্যাড ফিল্টারএফটার পদ্ধতিটি ব্যবহার করে আমার সুরক্ষা কনফিগারেশনটি সংশোধন করেছি এবং কর্স ফিল্টার ক্লাসের পরে যুক্ত করেছি।

@Component
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    //Cast the servlet request and response to HttpServletRequest and HttpServletResponse
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;

    // Grab the exception from the request attribute
    Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
    //Set response content type to application/json
    httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);

    //check if exception is not null and determine the instance of the exception to further manipulate the status codes and messages of your exception
    if(exception!=null && exception instanceof AuthorizationParameterNotFoundException){
        ErrorResponse errorResponse = new ErrorResponse(exception.getMessage(),"Authetication Failed!");
        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        PrintWriter writer = httpServletResponse.getWriter();
        writer.write(convertObjectToJson(errorResponse));
        writer.flush();
        return;
    }
    // If exception instance cannot be determined, then throw a nice exception and desired response code.
    else if(exception!=null){
            ErrorResponse errorResponse = new ErrorResponse(exception.getMessage(),"Authetication Failed!");
            PrintWriter writer = httpServletResponse.getWriter();
            writer.write(convertObjectToJson(errorResponse));
            writer.flush();
            return;
        }
        else {
        // proceed with the initial request if no exception is thrown.
            chain.doFilter(httpServletRequest,httpServletResponse);
        }
    }

public String convertObjectToJson(Object object) throws JsonProcessingException {
    if (object == null) {
        return null;
    }
    ObjectMapper mapper = new ObjectMapper();
    return mapper.writeValueAsString(object);
}
}

সিকিউরিটি কনফিগ ক্লাস

    @Configuration
    public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    AuthFilter authenticationFilter;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterAfter(authenticationFilter, CorsFilter.class).csrf().disable()
                .cors(); //........
        return http;
     }
   }

ত্রুটিআরস্পণ ক্লাস

public class ErrorResponse  {
private final String message;
private final String description;

public ErrorResponse(String description, String message) {
    this.message = message;
    this.description = description;
}

public String getMessage() {
    return message;
}

public String getDescription() {
    return description;
}}

0

আপনি ক্যাচ ব্লকের ভিতরে নিম্নলিখিত পদ্ধতিটি ব্যবহার করতে পারেন:

response.sendError(HttpStatus.UNAUTHORIZED.value(), "Invalid token")

লক্ষ্য করুন যে আপনি যে কোনও এইচটিপিস্ট্যাটাস কোড এবং একটি কাস্টম বার্তা ব্যবহার করতে পারেন।


-1

এটি অদ্ভুত কারণ @ কন্ট্রোলার অ্যাডভাইসকে কাজ করা উচিত, আপনি কি সঠিক ব্যতিক্রমটি ধরছেন?

@ControllerAdvice
public class GlobalDefaultExceptionHandler {

    @ResponseBody
    @ExceptionHandler(value = DataAccessException.class)
    public String defaultErrorHandler(HttpServletResponse response, DataAccessException e) throws Exception {
       response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
       //Json return
    }
}

CorsFilter এ এই ব্যতিক্রমটি ধরার চেষ্টা করুন এবং 500 টি ত্রুটি পাঠানোর চেষ্টা করুন, এরকম কিছু

@ExceptionHandler(DataAccessException.class)
@ResponseBody
public String handleDataException(DataAccessException ex, HttpServletResponse response) {
    response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
    //Json return
}

কর্স ফিল্টারে ব্যতিক্রম হ্যান্ডেলিংয়ের কাজ করে তবে এটি খুব পরিষ্কার নয়। আসলে আমার যা দরকার তা হ'ল সমস্ত ফিল্টারগুলির ব্যতিক্রম হ্যান্ডেল করা
কোপেলিটস

35
থেকে ব্যতিক্রম থ্রোক Filterধরা নাও পড়তে পারে @ControllerAdviceকারণ না পৌঁছতে পারে DispatcherServlet
থানহ এনগুইন ভ্যান

-1

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

সম্পাদনা: ব্যাকরণ


আপনি কি আপনার বিশ্বব্যাপী ত্রুটি হ্যান্ডলারের কোড স্নিপেট ভাগ করে নিতে আপত্তি করবেন?
নীরজ ভার্নেকার

এটা আমার জন্য কাজ করে না। আমি কাস্টম ব্যতিক্রম করেছি, যা সার্লেটএক্সসেপশন প্রসারিত করে এক্সপেশনহ্যান্ডলারের এই ব্যতিক্রমটির জন্য সমর্থন যোগ করেছি, তবে এটি সেখানে বাধা দেওয়া হয়নি।
মার্কস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.