বসন্ত 3 অনুরোধম্যাপিং: পাথের মান পান


133

requestMapping @PathVariableমানগুলিকে বিশ্লেষণ করার পরে কি সম্পূর্ণ পথের মান পাওয়ার কোনও উপায় আছে?

হয় যে: /{id}/{restOfTheUrl}বিশ্লেষণ করতে সক্ষম হওয়া উচিত /1/dir1/dir2/file.htmlমধ্যে id=1এবংrestOfTheUrl=/dir1/dir2/file.html

যে কোন ধরণের মতামতকে গুরুত্বসহকারে দেখা হবে।

উত্তর:


198

ইউআরএলটির মিলে যাওয়া অংশটি অনুরোধের নাম হিসাবে চিহ্নিত করা হয়েছে HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE:

@RequestMapping("/{id}/**")
public void foo(@PathVariable("id") int id, HttpServletRequest request) {
    String restOfTheUrl = (String) request.getAttribute(
        HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    ...
}

63
না, হ্যান্ডলারম্যাপিং বৈশিষ্ট্য P PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE- এ পুরো মিল রয়েছে contains
uthark

11
উথার্ক ঠিক আছে। এর মানটি restOfTheUrlপুরো পথ হবে, কেবলমাত্র বাকি অংশটি ক্যাপচার করেছে**
ডিসিএসট্রা

4
হ্যান্ডলারম্যাপিং P PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE alচ্ছিক এবং কিছু বাস্তবায়নের জন্য NULL বা "" হতে পারে। অনুরোধ.getRequestURI () একই মান প্রদান করে এবং alচ্ছিক নয়।
নিডালপ্রেস

2
এই সমাধানটি আর কাজ করে না এবং অবিশ্বাস্য।
ডলফিনজাভা

51

সবেমাত্র আমার সমস্যাটির সাথে সম্পর্কিত এই সমস্যাটি খুঁজে পেয়েছি। হ্যান্ডলারম্যাপিং ধ্রুবকগুলি ব্যবহার করে আমি সেই উদ্দেশ্যে একটি ছোট ইউটিলিটি লিখতে সক্ষম হয়েছি:

/**
 * Extract path from a controller mapping. /controllerUrl/** => return matched **
 * @param request incoming request.
 * @return extracted path
 */
public static String extractPathFromPattern(final HttpServletRequest request){


    String path = (String) request.getAttribute(
            HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    String bestMatchPattern = (String ) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);

    AntPathMatcher apm = new AntPathMatcher();
    String finalPath = apm.extractPathWithinPattern(bestMatchPattern, path);

    return finalPath;

}

19

এটি এখানে বেশ কিছুক্ষণ হয়েছে তবে এটি পোস্ট করছে। কারও পক্ষে উপকারী হতে পারে।

@RequestMapping( "/{id}/**" )
public void foo( @PathVariable String id, HttpServletRequest request ) {
    String urlTail = new AntPathMatcher()
            .extractPathWithinPattern( "/{id}/**", request.getRequestURI() );
}

1
এই কোডটির সাথে সমস্যাটি হ'ল এটি সার্লেলেট উপসর্গ এবং ম্যাপিং উপসর্গটি পরিচালনা করে না।
গ্যাভেনকোয়া

11

উপরে নির্মাণের Fabien Kruba ইতিমধ্যেই চমৎকার উত্তর , আমি ভেবেছিলাম এটা চমৎকার হবে যদি **URL এর অংশ একটি উপায় যার অনুরূপ ছিল একটি টীকা মাধ্যমে নিয়ামক পদ্ধতি করার জন্য একটি প্যারামিটার হিসাবে দেওয়া যেতে পারে, @RequestParamএবং @PathVariableবদলে সবসময় একটি ইউটিলিটি পদ্ধতি ব্যবহার করে যা স্পষ্টভাবে প্রয়োজন HttpServletRequest। সুতরাং এটি কিভাবে বাস্তবায়িত হতে পারে তার একটি উদাহরণ এখানে। আশা করি কেউ এটি কাজে লাগবে।

আর্গুমেন্ট রিললভার সহ টীকাটি তৈরি করুন:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WildcardParam {

    class Resolver implements HandlerMethodArgumentResolver {

        @Override
        public boolean supportsParameter(MethodParameter methodParameter) {
            return methodParameter.getParameterAnnotation(WildcardParam.class) != null;
        }

        @Override
        public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
            HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
            return request == null ? null : new AntPathMatcher().extractPathWithinPattern(
                    (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE),
                    (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
        }

    }

}

পদ্ধতি আর্গুমেন্ট সমাধানের নিবন্ধন করুন:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new WildcardParam.Resolver());
    }

}

**ইউআরএল এর অংশে সহজে অ্যাক্সেস পেতে আপনার নিয়ামক হ্যান্ডলার পদ্ধতিতে টিকাটি ব্যবহার করুন :

@RestController
public class SomeController {

    @GetMapping("/**")
    public void someHandlerMethod(@WildcardParam String wildcardParam) {
        // use wildcardParam here...
    }

}

9

আপনাকে বিল্ট-ইন ব্যবহার করতে হবে pathMatcher:

@RequestMapping("/{id}/**")
public void test(HttpServletRequest request, @PathVariable long id) throws Exception {
    ResourceUrlProvider urlProvider = (ResourceUrlProvider) request
            .getAttribute(ResourceUrlProvider.class.getCanonicalName());
    String restOfUrl = urlProvider.getPathMatcher().extractPathWithinPattern(
            String.valueOf(request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)),
            String.valueOf(request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)));

2
স্প্রিং বুটের সর্বশেষতম সংস্করণ
ডেভ বাউমন

1
এছাড়াও নিশ্চিত করা হচ্ছে যে এই পদ্ধতিটি স্প্রিং বুট ২.২.৪ রিলিজ হিসাবে কাজ করে।
tom_mai78101

5

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

http://www.tuckey.org/

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

ওয়েব-INF / web.xml:

<filter>
  <filter-name>UrlRewriteFilter</filter-name>
  <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<!-- map to /* -->

ওয়েব-INF / urlrewrite.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite
    PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
    "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
<urlrewrite>
  <rule>
    <from>^/(.*)/(.*)$</from>
    <to last="true">/$1?restOfTheUrl=$2</to>
</urlrewrite>

নিয়ামক পদ্ধতি:

@RequestMapping("/{id}")
public void handler(@PathVariable("id") int id, @RequestParam("restOfTheUrl") String pathToFile) {
  ...
}

2

হ্যাঁ, restOfTheUrlশুধুমাত্র প্রয়োজনীয় মানটিই ফিরিয়ে দিচ্ছে না তবে আমরা UriTemplateম্যাচিং ব্যবহার করে মানটি পেতে পারি ।

আমি সমস্যার সমাধান করেছি, সুতরাং এখানে সমস্যার সমাধানের সমাধান:

@RequestMapping("/{id}/**")
public void foo(@PathVariable("id") int id, HttpServletRequest request) {
String restOfTheUrl = (String) request.getAttribute(
    HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    /*We can use UriTemplate to map the restOfTheUrl*/
    UriTemplate template = new UriTemplate("/{id}/{value}");        
    boolean isTemplateMatched = template.matches(restOfTheUrl);
    if(isTemplateMatched) {
        Map<String, String> matchTemplate = new HashMap<String, String>();
        matchTemplate = template.match(restOfTheUrl);
        String value = matchTemplate.get("value");
       /*variable `value` will contain the required detail.*/
    }
}

1

এখানে আমি এটি কীভাবে করেছি। আপনি দেখতে পাচ্ছেন যে আমি কীভাবে অনুরোধ করা ইউআরআইটিকে একটি ফাইল সিস্টেমের পাথে রূপান্তর করব (এটি কী প্রশ্নটি সম্পর্কে রয়েছে)। বোনাস: এবং কীভাবে ফাইলটির সাথে প্রতিক্রিয়া জানাতে হয়।

@RequestMapping(value = "/file/{userId}/**", method = RequestMethod.GET)
public void serveFile(@PathVariable("userId") long userId, HttpServletRequest request, HttpServletResponse response) {
    assert request != null;
    assert response != null;

    // requestURL:  http://192.168.1.3:8080/file/54/documents/tutorial.pdf
    // requestURI:  /file/54/documents/tutorial.pdf
    // servletPath: /file/54/documents/tutorial.pdf
    // logger.debug("requestURL: " + request.getRequestURL());
    // logger.debug("requestURI: " + request.getRequestURI());
    // logger.debug("servletPath: " + request.getServletPath());

    String requestURI = request.getRequestURI();
    String relativePath = requestURI.replaceFirst("^/file/", "");

    Path path = Paths.get("/user_files").resolve(relativePath);
    try {
        InputStream is = new FileInputStream(path.toFile());  
        org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
        response.flushBuffer();
    } catch (IOException ex) {
        logger.error("Error writing file to output stream. Path: '" + path + "', requestURI: '" + requestURI + "'");
        throw new RuntimeException("IOError writing file to output stream");
    }
}

0
private final static String MAPPING = "/foo/*";

@RequestMapping(value = MAPPING, method = RequestMethod.GET)
public @ResponseBody void foo(HttpServletRequest request, HttpServletResponse response) {
    final String mapping = getMapping("foo").replace("*", ""); 
    final String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    final String restOfPath = url.replace(mapping, "");
    System.out.println(restOfPath);
}

private String getMapping(String methodName) {
    Method methods[] = this.getClass().getMethods();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName() == methodName) {
            String mapping[] = methods[i].getAnnotation(RequestMapping.class).value();
            if (mapping.length > 0) {
                return mapping[mapping.length - 1];
            }
        }
    }
    return null;
}

-4

আমারও একই সমস্যা রয়েছে এবং আমি এইভাবে সমাধান করেছি:

@RequestMapping(value = "{siteCode}/**/{fileName}.{fileExtension}")
public HttpEntity<byte[]> getResource(@PathVariable String siteCode,
        @PathVariable String fileName, @PathVariable String fileExtension,
        HttpServletRequest req, HttpServletResponse response ) throws IOException {
    String fullPath = req.getPathInfo();
    // Calling http://localhost:8080/SiteXX/images/argentine/flag.jpg
    // fullPath conentent: /SiteXX/images/argentine/flag.jpg
}

নোটটি req.getPathInfo()সম্পূর্ণ পথটি ( {siteCode}এবং সহ {fileName}.{fileExtension}) ফিরিয়ে দেবে যাতে আপনাকে সুবিধামত প্রক্রিয়া করতে হবে।

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