Markus Möller: UTF-8-Encoder

Hallo!
Ich schreibe gerade an einer Webanwendung, die international einsetzbar sein soll. Jetzt kommt natürlich die Sache mit den Zeichensätzen:
Ich bekomme meine Daten in Unicode. Das heißt, es sind alle nur erdenkbaren Zeichen dabei. Ein Servlet soll das jetzt als HTML darstellen. Also setzte ich mittels meta-Angabe "content="text/html; charset=UTF-8", also Unicode. Resultat ist, dass alle Sonderzeichen trotzdem als Fragezeichen dargestellt werden. "Füße" => "F??e"
Als nächsten Versuch habe ich den UTF-8-Decoder aus dem JS-Feature-Artikel umgeschrieben (siehe unten). Das klappt aber nur bedingt. "Füße" => "Fü??e" (ja, wirklich 2 Fragezeichen).
Was mach ich denn da noch verkehrt, wo ist mein Denkfehler?
Hier der Code:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Unicode extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<body>");
        out.println("<head><meta http-equiv="content-type" content="text/html; charset=UTF-8">");
        out.println("<title>Hello World!</title>");
        out.println("</head>");
        out.println("<body>");
        String rohtext = "Füße, Möller";
        String utftext = "";
        byte[] bytes = new byte[0];
        try {
            bytes = rohtext.getBytes("UTF-8");
        } catch (java.io.UnsupportedEncodingException e) {
            e.printStackTrace();
            System.exit(1);
        }
        for(int n=0; n<bytes.length; n++) {
             byte c = bytes[n];
             // alle Zeichen von 0-127 => 1byte
             if (c<128)
                 utftext += new String(new byte[] {c});
             // alle Zeichen von 127 bis 2047 => 2byte
             else if((c>127) && (c<2048)) {
                 utftext += new String(new byte[] {(byte)((c>>6)|192)});
                 utftext += new String(new byte[] {(byte)((c&63)|128)});
             }
             // alle Zeichen von 2048 bis 66536 => 3byte
             else {
                 utftext += new String(new byte[] {(byte)((c>>12)|224)});
                 utftext += new String(new byte[] {(byte)(((c>>6)&63)|128)});
                 utftext += new String(new byte[] {(byte)((c&63)|128)});
             }
         }
         out.println("ROH: " + rohtext + "<br>\n");
         out.println("UNI: " + utftext + "<br>\n");
        out.println("</body>");
        out.println("</html>");
    }
}