Tomcat servlet, redirect all urls to a single webp

2019-02-27 23:59发布

问题:

I deployed a servlet 'csvreports' in tomcat. 'index.html' in csvreports picks csv file from data/ folder and displays as html table.

The url format is

localhost:8080/csvreports/?csv=test.csv

I am parsing the url in index.html to get csv file name and read from /data/test.csv in the code.

Now, the url is changed to like localhost:8080/csvreports/folder1/?csv=test.csv, localhost:8080/csvreports/folder2/?csv=test.csv etc.

folder1 and folder2 gets generated dynamically and assuming the folders are already present in tomcat/webapps/csvreports/

I need to execute the same index.html for all urls. My idea is to parse url to get the path and finally use the path to read csv.

I wanted to how to redirect localhost:8080/csvreports/*/?csv=test.csv to a single webpage.

Any other ideas on how to accomplish this would be appreciated.

回答1:

Mapping all URLs to same page

Use an index.jsp instead of an index.html. You could literally just rename the file, without changing any of the contents.

Then in your web.xml, you can specify that all URLs starting with /csvreports should be routed to your index.jsp.

<servlet>
    <servlet-name>index</servlet-name>
    <jsp-file>/index.jsp</jsp-file>
</servlet>
<servlet-mapping>
    <servlet-name>index</servlet-name>
    <url-pattern>/csvreports/*</url-pattern>
</servlet-mapping>

Regex for extracting path

In your index.jsp, you could use a regex on your URL with two capturing groups.

var regex = /.*csvreports\/(.*)\?csv=(.*)/g;

The first .* will tell it to match any characters before csvreports. This way, it will match no matter what your host name is. For example, currently it is localhost:8080, but if you deploy it to a test or production server, or if someone else hits your web server from another machine, it will be something different.

Next, it matches csvreports, which means that after the host name, the URL must contain the exact string csvreports.

Next, it looks for a single slash /.

Then, comes the first capturing group (.*). The parentheses indicate that it is a matching group. The .* tells it to match any character. So, it will match all characters between the first / in your URL and the question mark ?.

Then, it will look for ?csv=.

And finally, a second capture group (.*) is used to capture any characters after the =.


Now that you have the regex all set to match your URL, you can call the .exec() method on the regex, and pass it your URL.

var match = regex.exec(url);

Finally, you can extract the captured groups from the match variable that is returned from the call to .exec().

var directories = match[1];
var csvfilename = match[2];

You can get your path by concatenating those two matched groups. You may also want to check to ensure that there is a / at the end of your directories. For example, the regex should match localhost:8080/csvreports/folder1?csv=file.csv, but in this case directories='folder1' and csvfilename=file.csv, so when you concatenate them, you would get 'folder1file.csv', when what you want is 'folder1/file.csv'. So, before you concatenate them, check if the last character in directories is a /, and if not, put a / between directories and csvfilename.


Example

Here is a simple example to show this regex in action.

function getPathFromUrl() {
  var url = document.getElementById('url').value;

  var regex = /.*csvreports\/(.*)\?csv=(.*)/g;
  var match = regex.exec(url);
  
  var span = document.getElementById('path');
  
  
  var directories = match[1];
  var csvfilename = match[2];
  
  var path = directories;
  
  if (path[path.length-1] !== '/') {
    path += '/'
  }
  
  path += csvfilename;    
  
  span.innerHTML = path;
}
<input id="url" type="text" value="localhost:8080/csvreports/folder1/?csv=test.csv" size="50">
<button id="button" onclick="getPathFromUrl()">Get Path</button>
<br><br>
<label for="path"><strong>Path:</strong></label>
<span id="path"></span>