Meshes are data structures, so the exact method by which you render them depends on how you store the data.
One way that worked for me was to have FloatBuffers for the vertices, normals, and texture coordinates. I would then have a list of index groups which consisted of material information and an IntBuffer of indices that would reference the vertices, normals, and texture coordinates buffers. If you're not using textures then you can just ignore the texture coordinate buffer. The FloatBuffers must all be of the same length and should be rewound before each frame.
Then you could use glVertexArrayPointer() and similar methods to submit the buffers. Loop the list of index groups and apply materials and then call glDrawElements().
This method allows for a very simple port to using vertex buffer objects for increased performance.
However, one thing to keep in mind is that the vertex, normal, and texture coordinate are lumped together this way. Thus for a cube, one corner would need to be 3 different coordinates because it has 3 different normals but only point.