I'm a Ruby on Rails developer programming a web application in Java. I am trying to achieve something similar to what is achieved in Rails. In Rails it is possible to call a link using localhost:8000\Users\1 when Users is a Model and 1 is the id of a specific user. I would like to get the same kind of thing in Java.
I am working in an MVC type design where my JSP pages are the view and my Servlets are the controllers. I created a servlet called Users which renders the users.jsp page now i can get to that page using the URL localhost:8000\projectName\Users, i would like to route localhost:8000\projectName\Users\1 to the page user.jsp while the appropriate Servlet will handle sending into the page the correct user (with id=1).
Any idea how I can achieve this?
I'm doing this in a University project and am not allowed to use any frameworks. I also would rather something i could code rather than install.
now i can get to that page using the URL localhost:8000\projectName\Users, i would like to route localhost:8000\projectName\Users\1 to the page user.jsp while the appropriate Servlet will handle sending into the page the correct user (with id=1).
Simple. Map the servlet on an URL pattern of /Users/* instead of /Users. You can then grab the path info (the part after /Users in the URL, which is thus /1 in your example) as follows:
String pathInfo = request.getPathInfo();
// ...
You can just forward to users.jsp the usual way.
Long id = Long.valueOf(pathInfo.substring(1));
User user = userService.find(id);
request.setAttribute("user", user);
request.getRequestDispatcher("/WEB-INF/users.jsp").forward(request, response);
I would try this via a servlet and servlet mappings like that in web.xml
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>com.example.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/Users</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/Users/*</url-pattern>
</servlet-mapping>
Than in your UserServlet try to get the full URL and parse it to your needs. Example:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
String url = reg.getRequestURL();
//... get last part after slash and parse it to your id
}
See http://download.oracle.com/javaee/1.3/api/javax/servlet/http/HttpServletRequest.html for further documentation on the request and how its parameters can be retrieved
UrlRewriteFilter is like mod_rewrite but for Tomcat. You can use it to make your URLs SEO-friendly. You can also use Apache+mod_rewrite+Tomcat.
Related
I am new to java programming in the web environment and am having trouble understanding the flow.
For an assignment coming up I need to build a web application accessible with an API via get/post requests. For the tutorials that I have followed here is the flow I understand.
User visits top domain->
Per configuration user is directed to a jsp page->
Jsp contains javascrip and html. To access server code (for database, computations and other processes) the jsp page can use RCP to make async requests to a java servlet->
Java servlet does server handling and returns response to jsp page
Is this the required flow or can a user directly acess a servlet, and can that servlet handle get/post, or do I have to handle at the jsp and foward to the servlet?
Servlets can be accessed directly. You just need to extend HttpServlet and implement doGet and/or doPost. For example:
public class MyServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
Integer param = null;
try {
param = Integer.parseInt(req.getParameter("param"));
}
catch(NumberFormatException e) {
}
}
}
You also need to map your servlet to url in web.xml:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.adam.test.server.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/my_servlet</url-pattern>
</servlet-mapping>
Now you can access your servlet using url like this:
http://domain.com/my_servlet?param=123
I have a servlet called User.java. It is mapped to the url pattern
<servlet-mapping>
<servlet-name>User</servlet-name>
<url-pattern>/user/*</url-pattern>
</servlet-mapping>
Inside the Servlet, the path following the slash in user/ is analyzed, data about that user is retrieved from the database, set in attributes, and then the page user_home.jsp is to be displayed.
The code to make this happen is:
User user = UserManager.getUserInfoById(userPath);
request.getSession().setAttribute("user", user);
request.getRequestDispatcher("resources/jsp/user_home.jsp").forward(request, response);
The problem is, that rather than opening this user_home.jsp, the request is mapped once again to the same servlet User.java. It does nothing.
I've put output statements at the beginning of the doGet method, so I can see that the URL is
http://localhost:8080/myproj/user/resources/jsp/user_home.jsp
so it seems the obvious problem is that it's mapping right back to the user/* pattern.
How do I get the Servlet to display this page without going through URL mapping, and properly display the jsp I need it to?
If the path passed to request.getRequestDispatcher() does not begin with a "/", it is interpreted as relative to the current path. Since your servlet's path is /user/<something>, it tries to forward the request to /user/resources/jsp/user_home.jsp, which matches your servlet mapping and therefore forwards to the same servlet recursively.
On the other hand, if the path passed to request.getRequestDispatcher() begins with a "/", it is interpreted as relative to the current context root. So assuming that the resources directory is located at the root of your webapp, try adding a "/" at the beginning of the path, e.g.:
request.getRequestDispatcher("/resources/jsp/user_home.jsp").forward(request, response);
you don't want to use the * in your servlet mapping. simply because everytime that you have /user/ in your URL it will redirect back to the servlet.
the asterisk accepts every URL that has /user/ and redirect it based on servlet mappiing, so you might want to make it
<servlet-mapping>
<servlet-name>User</servlet-name>
<url-pattern>/user/User</url-pattern>
</servlet-mapping>
and use it in your action as action = user/User
I would like to have URL mappings that I'm having with spring framework like below in standard servlet web.xml configuration.
#RequestMapping(value="/students/{username}", method=RequestMethod.GET)
public String deleteSpitter(#PathVariable String username) {
...
...
}
I would like URL mappings like these two:
/students/Mike
/students/John
to be mapped to same servlet where I can also read "Mike" and "John" as parameters somehow. If it can be extended to more than one level like the example below it could be very much useful for me:
/students/{schoolname}/{studentname}
like:
/students/mcgill/mike
/students/ubc/john
You can map a standard servlet to a wildcard path and access the pathInfo part of the request using the HttpServletRequest.getPathInfo() method.
The servlet should get the path info like this
package com.acme;
public class TestServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String info = request.getPathInfo();
}
}
and you should map the servlet in your web.xml like this
<servlet>
<servlet-name>test-servlet</servlet-name>
<servlet-class>com.acme.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test-servlet</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
If you request the URL '/test/mcgill/mike' the path info will be '/mcgill/mike'. Parsing the path info is up to you.
If you work with a Java EE 6 compliant container you should also take a look at the JAX-RS specification to build RESTful web services.
Check out UrlRewriteFilter: http://www.tuckey.org/urlrewrite/
In the examples at http://urlrewritefilter.googlecode.com/svn/trunk/src/doc/manual/3.2/guide.html look at the "Clean a URL" example.
JAX-RS (aka Jersey) can do something like this with a servlet app (although not just servlets)
I want that when user hits following URL:
http://host:8080/AppName/ServletName/Param1/Param2
It should go to a servlet named ServletName and Param1 and Param2 become request parameters. I have seen these kind of urls in ruby projects. Is it possible in Java?
If you are using Spring MVC you can map a #Controller and access the params as #PathVariable in a #RequestMapping.
#Controller
public class MyController {
#RequestMapping("/{param1}/{param2})
public Response get(#PathVariable("param1") String param1, #PathVariable("param2") String param2) {
//method body
}
}
Yes, you can do something like that with a servlet. You need to set the servlet mapping in web.xml like this:
<servlet-mapping>
<servlet-name>ServletName</servlet-name>
<url-pattern>/ServletName/*</url-pattern>
</servlet-mapping>
to get all requests and in the servlet you need to parse the result of HttpServletRequest.getPathInfo().
HttpServletRequest.getContextpath() seems interesting, even though i have never used it myself.
Sure you can, it's called REST, and you can get an intro here: http://download.oracle.com/javaee/6/tutorial/doc/giepu.html
You can also map servlets to wildcarded paths, so you could just map your servlet to /ServletName/* and get the /Param1/Param2 part from request.getPathInfo().
You can also achieve this with URL rewriting. There is also a servlet container equivalent available that works with a ServletFilter called UrlRewriteFilter.
I personally use Tapestry5 which natively encodes parameters this way.
I haven't done this,even haven't seen but try this
first map the url in the web.xml like this
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>ServletName</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletName</servlet-name>
<url-pattern>/ServletName/Param1/Param2</url-pattern>
</servlet-mapping>
and then get the url to a string using
String url=request.getRequestURI();
then you can split and get param1 and param2.
I want a Servlet to handle requests to files depending on prefix and extension, e.g.
prefix_*.xml
Since mapping on beginning AND end of request path is not possible, I have mapped all *.xml requests to my Servlet.
The question now is: how can I drop out of my servlet for XML files not starting with "prefix_", so that the request is handled like a "normal" request to an xml file?
This is probably quite simple but I do not seem to be able to find this out... :-/
Thanks a lot in advance
another solution (maybe fits for you) is if you are using/plan to use an Apache in front of that web container instance you could use the rewrite module of apache. Rewriting the url to something more easy to handle for the Webapp container.
Hope this helps.
David.
I would strongly suggest using a proper MVC framework for this. As you've discovered, the flexibility of the standard servlet API is very limited when it comes to request dispatching.
Ideally, you would be able to use your existing servlet code in combination with an MVC framework, with the framework doing the diapcthing based on path pattern, and your servlets doing the business logic. Luckily, Spring MVC allows you to do just that, using the ServletForwardingController. It'd be a very lightweight spring config.
So you'd have something like this in your web.xml:
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>foo.MyServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<url-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*</url-pattern>
</url-mapping>
You would then have a WEB-INF/spring-servlet.xml file like this:
<beans>
<bean name="/prefix*.xml" class="org.springframework.web.servlet.mvc.ServletForwardingController">
<property name="servletName" value="myServlet"/>
</bean>
</beans>
And that would be pretty much it. All requests for /prefix*.xml would go to myServlet, and all others would fall through to the container.
Not shure, but once you catch all *.xml requests you can inspect the request again in your code via HttpServletRequest.getRequestURI()
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String uri =req.getRequestURI();
int i = uri.lastIndexOf('/');
int j = uri.lastIndexOf('.', i);
if (uri.substring(i+1, j).startsWith("prefix_")) {
// your code
}
}
(code not tested, only an idea ...)