Showing posts with label CSS. Show all posts
Showing posts with label CSS. Show all posts

Saturday, 26 December 2015

Serving static resources with Spring MVC 3.0 in Java

Background

Many time we use custom CSS and java script file to add functionality and style to our web pages. We usually refer them in our JSP pages. In this post we will see how we can refer such static resources with Spring 3.0+. We will use Tomcat as our container/server.


Setup

If you are new to Spring then try out a sample Spring program -
Above post is somewhat old but should give you good idea as to get started. Anyhow I will provide the setup xmls here.

Your web.xml file should look as follows -

<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <display-name>Spring Web MVC Demo Application</display-name>
   
   
  <servlet>
      <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
     <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
  </servlet-mapping>
  
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
   

</web-app>



 Important file here is mvc-dispatcher-servlet.xml which forms a part of web application context. Have given a dummy file root-context.xml for root application context but you may not add it in your web.xml file. If you are not familiar with context loading part I suggest read

As I said create file mvc-dispatcher-servlet.xml with following content -

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc 
                        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
    
    <!-- Scan for components under this package -->
    <context:component-scan base-package="com.osfg.test" />



    <mvc:annotation-driven/>
    
</beans>


As you can see the web application context will scan package com.osfg.test to find Spring resources like handler/interceptor. GO ahead create this package and create a controller in it. Lets call it TestController.java. Add following content to it.

package com.osfg.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author athakur
 */
@Controller
public class TestController {
    
    @RequestMapping(value="/test", method=RequestMethod.GET)
    public String welcome() {
        return "test";
    }

}



That's it. We have our controller all setup. This controller returns a logical view name called test. Now if you notice our spring configuration we have already defined InternalResourceViewResolver which provides a JSTL view. So go ahead and create a JSP file at /pages/test.jsp under webapp or webcontent.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>OSFG Test Page</title>
<link href="CSS/test.css" rel="stylesheet">
</head>
<body>

<h1>Hello World from OSFG!</h1>

</body>
</html>


As you can see our JSP references a CSS file called test.css. Create a folder called CSS and then create a file called test.cs  in it. Add following contents to it.
H1 {
color: white; background: teal; FONT-FAMILY: arial; FONT-SIZE: 18pt; FONT-STYLE: normal; FONT-VARIANT: normal
}



Ok we are all set to test now.

Note the Directory structure below -

 


Testing 1.0

Go ahead start up your tomcat server and load following URL
  • http://localhost:8080/TestWebProject/test 



 Oops! what happened? It is not able to find the CSS file.Well lets come to the point. Spring does not directly allow you to access static resources and the very goal of this post is to show you how. So lets see that now.

Add following to your Spring configuration -
<mvc:default-servlet-handler />


This basically allows you to render static resources from root folder (under webapp or webcontent).
It essentially configures a handler for serving static resources by forwarding to the Servlet container's default Servlet (DefaultServletHttpRequestHandler is used).
 Lets test with our new configuration -

Testing 2.0

After restarting the server hit the URL again -



All good? Yup :) There is also alternate way to do this. You can define resource mapping instead of specifying default-servlet-handler.

<mvc:resources mapping="/resources/**" location="/CSS/" />

Then you also need to make change in JSP as follows

<link href="resources/test.css" rel="stylesheet">

So when you reference resources it will go and pick up from CSS. You can use classpath references in location as well. Here ResourceHttpRequestHandler is used to serve request based on location provided.


Related Links





Saturday, 4 July 2015

Understanding CSS Specificity

Background

Life is good when you have a small web project with limited and simple CSS but as your project size grows and more CSS is to be applied complexity increases. 

In there are two or more conflicting CSS rules that point to the same element then your web browser will apply some rules to figure out which rule should be given higher precedence and be applied.

We term this rule weight as selectivity. More the selectivity more is the preference given to that rule.

Example


Enough of the theory lets see an example. Consider following html

<html>
    <head>
        <style type="text/css">
            .redbutton{color: red;}
            .bluebutton{color: blue;}
             #innerdiv input {color: green;}
        </style>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
        <script>
            function changecolor()
            {
                jQuery("#colorbutton").addClass("bluebutton");
            }
        </script>
    <title>Testing CSS Selectivity</title>
    </head>
    <body>
        <div id="ouderdiv">
            <div id ="innerdiv">
                <input id="colorbutton" type="button" class="redbutton" value="Click Me" onclick="changecolor()"/>
            <div>
        <div>
    </body>
    
</html>

What do you expect will be the color of the button on page load and on click ? Well think a bit and then try it out. Paste above html in a file and open it in any browser. Observer the color, click on the button and then observer the color again. 

Before Cick

After Click


Whats happening?

Have questions? Will be answered soon. Lets take a step back and review our html code. We have a button. For this button we provided a class called redbutton (which should make the button red) and then on click we are dynamically changing the class to bluebutton (which should make the button blue). But none of these worked. It is still green. As you must have guessed correctly by now there is another css rule that is getting applied.

#innerdiv input {color: green;}

But why? Because CSS specificity of this rule is more than other class rules that we have defined. Next natural question - How is css specificity determined by the browser?

How is CSS specificity calculated?

There are some basic rules to determine specificity of a CSS rule.

Determination of specificity of a CSS rule depends on what type of selector is used
  • HTML selector (Eg input) has specificity 1
  • Class selector (Eg .redcolor) has specificity 10
  • ID selector (Eg. #innerdiv) has specificity 100
And if you have multiple such selectors in an CSS rule then their individual specificity just get added to form rule specificity that is used by the browser to determine precedence.

Here are few example
  • a - specificity 1 (1 HTML selector)
  • div a - specificity 2 (2 HTML selectors,  1+1)
  • div .someclass - specificty 11 (1 HTML selector and 1 class selector, 1 + 10)
  • div #someid - specificity 101  (1 HTML selector and 1 id selector, 1 + 100)  
  • div #someid .someclass - specificity 111  (1 HTML selector and 1 id selector and 1 class selector, 1 + 100 + 10)  

and so on.... Hope you got the point.

Note : If two conflicting rules have same selectivity then the one applied or parsed later is picked up.

So lets apply it to our rules.

  • .redbutton{color: red;} - specificity 10 (1 class selector)
  • .bluebutton{color: blue;} - specificity 10 (1 class selector)
  • #innerdiv input {color: green;} - specificity 101 (1 id selector and 1 html selector, 100+1)
So how can we leverage this information now? Lets increase the specificity of first two color rules now.

  • #innerdiv .redbutton{color: red;} - specificity 110 (1 id selector and 1 class selector,100+10)
  • #innerdiv .bluebutton{color: blue;} - specificity 110 (1 id selector and 1 class selector,100+10)
  • #innerdiv input {color: green;} - specificity 100 (1 id selector and 1 html selector,100+1)

With above rules now test our page again.

 Before Click




 After Click




That's all with CSS selectivity. Ideal scenario is when no two rules conflict but in my personal experience conflicting rules are bound to happen for a big web project. This is when this rules come handle. Let me know if you still have any questions :).
t> UA-39527780-1 back to top