Reputation: 1170
I have an index.html file in the following structure.
WEB-INF/dbName/type/id/index.html
Also, there are external css and js files in the same path.
I need to access this file without exposing its path in the browser.
Below is my controller class:
@Controller
public class MyController {
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
@RequestMapping(value = "/{type}/{id}", method = RequestMethod.GET, produces = MediaType.ALL_VALUE)
public String pod(HttpServletRequest request, @PathVariable String type, @PathVariable String id)
throws IOException {
String redirectUrl = "/dbName/" + type + "/" + id + "/index.html";
return "redirect:" + redirectUrl;
}
}
Resource mapping in servlet-dispatcher.xml:
<mvc:resources mapping="/dbName/**" location="/WEB-INF/dbName/" />
The resulting URL looks like this: localhost:8080/project/dbName/type/id/index.html
But, the expected URL is: localhost:8080/project/type/id/
This code exposes the URL to the resource in the browser. Then, I tried using forward instead of redirect. Then it doesn't expose the URL, but the external CSS and js used in index.html are not loaded.
Any help would be appreciated.
Upvotes: 0
Views: 651
Reputation: 5283
The contract of a view resolver specifies that a view resolver can return null to indicate the view could not be found. Not all view resolvers do this, however, because in some cases, the resolver simply cannot detect whether or not the view exists. For example, the InternalResourceViewResolver uses the RequestDispatcher internally, and dispatching is the only way to figure out if a JSP exists, but this action can only execute once. The same holds for the VelocityViewResolver and some others. Check the javadocs of the specific view resolver to see whether it reports non-existing views. Thus, putting an InternalResourceViewResolver in the chain in a place other than the last results in the chain not being fully inspected, because the InternalResourceViewResolver will always return a view!
Redirecting to Views
As mentioned previously, a controller typically returns a logical view name, which a view resolver resolves to a particular view technology. For view technologies such as JSPs that are processed through the Servlet or JSP engine, this resolution is usually handled through the combination of InternalResourceViewResolver and InternalResourceView, which issues an internal forward or include via the Servlet API’s RequestDispatcher.forward(..) method or RequestDispatcher.include() method. For other view technologies, such as Velocity, XSLT, and so on, the view itself writes the content directly to the response stream.
RedirectView
One way to force a redirect as the result of a controller response is for the controller to create and return an instance of Spring’s RedirectView. In this case, DispatcherServlet does not use the normal view resolution mechanism. Rather because it has been given the (redirect) view already, the DispatcherServlet simply instructs the view to do its work. The RedirectView in turn calls HttpServletResponse.sendRedirect() to send an HTTP redirect to the client browser.
If you use RedirectView and the view is created by the controller itself, it is recommended that you configure the redirect URL to be injected into the controller so that it is not baked into the controller but configured in the context along with the view names. The the section called “The redirect: prefix” facilitates this decoupling.
The redirect: prefix
While the use of RedirectView works fine, if the controller itself creates the RedirectView, there is no avoiding the fact that the controller is aware that a redirection is happening. This is really suboptimal and couples things too tightly. The controller should not really care about how the response gets handled. In general it should operate only in terms of view names that have been injected into it.
The special redirect: prefix allows you to accomplish this. If a view name is returned that has the prefix redirect:, the UrlBasedViewResolver (and all subclasses) will recognize this as a special indication that a redirect is needed. The rest of the view name will be treated as the redirect URL.
The net effect is the same as if the controller had returned a RedirectView, but now the controller itself can simply operate in terms of logical view names. A logical view name such as redirect:/myapp/some/resource will redirect relative to the current Servlet context, while a name such as redirect:http://myhost.com/some/arbitrary/path will redirect to an absolute URL.
The forward: prefix
It is also possible to use a special forward: prefix for view names that are ultimately resolved by UrlBasedViewResolver and subclasses. This creates an InternalResourceView (which ultimately does a RequestDispatcher.forward()) around the rest of the view name, which is considered a URL. Therefore, this prefix is not useful with InternalResourceViewResolver and InternalResourceView (for JSPs for example). But the prefix can be helpful when you are primarily using another view technology, but still want to force a forward of a resource to be handled by the Servlet/JSP engine. (Note that you may also chain multiple view resolvers, instead.)
As with the redirect: prefix, if the view name with the forward: prefix is injected into the controller, the controller does not detect that anything special is happening in terms of handling the response.
DOCS: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html
Upvotes: 2
Reputation: 2626
The redirect sends the URL back to browser first and then from browser another request is created, redirect can redirect to resources on different servers.
Since the url with redirect action is sent back to browser, causes the browser to show the URL in client's address bar
Just use
request.getRequestDispathcer("url").forward(//required params);
Forward request is used to forward to resources available within the server from where the call is made. This transfer of control is done by the container internally and browser / client is not involved.
Upvotes: 1
Reputation:
The RequestDispatcher class and it's forward method like you've mentioned should work.
RequestDispatcher rd = req.getRequestDispatcher("index.html");
rd.forward(req, resp);
This should serve the index.html page nodifferently than visiting it directly.
It's confusing why the CSS and JS would fail to work using this method. I don't believe there is anything different between requesting /index.html or using a servlet to request index.html that would cause this. Maybe check that these files are correctly referenced in your HTML?
I know this would be better suited to a comment but I haven't yet earned enough reputation, sorry.
Upvotes: 1