`
woming66
  • 浏览: 57562 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

自己编写一个基于Velocity的MVC框架

    博客分类:
  • Java
阅读更多
公司留了作业(还有一个月毕业),让预习Velocity,在家呆着没意思,反正闲着也是闲着,看了VelocityViewServlet源码,感觉还可以,取其精华去其糟粕,自己写了一个基于Velocity的MVC框架,废话不多说了,直接进入正题。

VelocityActionServlet是整个MVC框架的核心类,拦截所有的Action请求,分发给不同的Action进行处理。
init()方法初始化了系统需要的资源和VelocityEngine。
doProcess()是这个类的核心方法,处理用户请求,获取context数据,获取模板,合成html
package com.zzq.velocity.core;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.collections.ExtendedProperties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.io.VelocityWriter;

public class VelocityActionServlet extends HttpServlet {

	private static Log log = LogFactory.getLog(VelocityActionServlet.class);
	
	/**
	 * request放入VelocityContext中的key
	 */
	public static final String REQUEST = "request";

	/**
	 * response放入VelocityContext中的key
	 */
    public static final String RESPONSE = "response";
	
	public static final String CONTENT_TYPE = "default.contentType";
	
	public static final String OUTPUT_ENCODING = "output.encoding";
	
	/**
	 * 默认的输出编码
	 */
	public static final String DEFAULT_OUTPUT_ENCODING = "UTF-8";
	
	/**
	 * velocity.properties在web.xml文件默认的key
	 */
	protected static final String INIT_PROPS_KEY =
        "org.apache.velocity.properties";
	
	/**
	 * velocity.properties在默认的路径
	 */
	protected static final String DEFAULT_PROPERTIES_PATH =
        "/WEB-INF/velocity.properties";
	
	/**
	 * 默认的ContextType
	 */
	public static final String DEFAULT_CONTENT_TYPE = "text/html";
	
	/**
	 * 对输出流维护的池
	 */
	private ObjectPool<VelocityWriter> pool = new ObjectPool<VelocityWriter>(40);

    private VelocityEngine velocity = null;
    
    /**
     * 例如user.do?method=add -> 会调用UserAction的add方法 相当于DispatchAction功能
     */
    private static final String DEFAULT_PARAMETER_METHOD = "method";

    private static final String INIT_PARAMETER_KEY = "parameter";
    
    private String parameterMethod;
    
    /**
     * 最终默认的ContentType
     */
    private String defaultContentType;
    
    private static final String INIT_TEMPLATEPATH_KEY = "templatePath";
	
    private static final String FILE_RESOURCE_LOADER_PATH = "file.resource.loader.path";
    
	public void init(ServletConfig config) throws ServletException {
		
		super.init(config);
		
		/**
		 * 初始化Velocity引擎
		 */
		initVelocity(config);
		
		defaultContentType = (String)getVelocityProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
        String encoding = (String)getVelocityProperty(OUTPUT_ENCODING, DEFAULT_OUTPUT_ENCODING);
        parameterMethod = findInitParameter(config, INIT_PARAMETER_KEY, DEFAULT_PARAMETER_METHOD);
        
        int index = defaultContentType.lastIndexOf(";");
        
        if(index < 0) {
        	defaultContentType += "; charset=" + encoding;
        }
        
	}
	
	/**
	 * 初始化Velocity引擎
	 * @param config
	 * @throws ServletException
	 */
	protected void initVelocity(ServletConfig config) throws ServletException {
		
		try {
			
			velocity = new VelocityEngine();
			
			ExtendedProperties p = loadConfiguration(config);
			
			String templatePath = findInitParameter(config, INIT_TEMPLATEPATH_KEY);
			
			templatePath = config.getServletContext().getRealPath("/") + templatePath;
			
			velocity.setProperty(FILE_RESOURCE_LOADER_PATH, templatePath);
			
			velocity.setExtendedProperties(p);
	   
			velocity.init();
		} catch (Exception e) {
			log.error("初始化velocity引擎时出错!");
			throw new ServletException(e);
		}
	}
	
	protected String getVelocityProperty(String key, String defaultValue) {
		
		String value = (String)velocity.getProperty(key);
		
		if(null == value || "".equals(value.trim())) {
			value = defaultValue;
		}
		
		return value;
	}
	
	/**
	 * 加载velocity.properties配置文件
	 */
	protected ExtendedProperties loadConfiguration(ServletConfig config) {
		
		String propsFile = findInitParameter(config, INIT_PROPS_KEY);
		
		if(null == propsFile) {
			propsFile = DEFAULT_PROPERTIES_PATH;
		}
		
		ExtendedProperties properties = new ExtendedProperties();
		InputStream inputStream = getServletContext().getResourceAsStream(propsFile);
		
		try {
			inputStream = getServletContext().getResourceAsStream(propsFile);
			
			if(null != inputStream) {
				properties.load(inputStream);
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			if(null != inputStream) {
				try {
					inputStream.close();
				} catch (IOException e) {
					throw new RuntimeException("关闭" + propsFile + "文件时出现异常!");
				}
			}
		}
		
		return properties;
	}
	
	protected String findInitParameter(ServletConfig config, String key) {
		
		String value = config.getInitParameter(key);
		
		if(null == value || "".equals(value.trim())) {
			value = config.getServletContext().getInitParameter(key);
		}
		
		return value;
	}
	
	protected String findInitParameter(ServletConfig config, String key, String defaultValue) {
		
		String value = config.getInitParameter(key);
		
		if(null == value || "".equals(value.trim())) {
			value = config.getServletContext().getInitParameter(key);
		}
		
		if(null == value || "".equals(value.trim())) {
			value = defaultValue;
		}
		
		return value;
	}
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		this.doProcess(request, response);
	}
		
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
	
		this.doProcess(request, response);
	}
	
	/**
	 * 请求处理的核心方法
	 * @param request
	 * @param response
	 */
	protected void doProcess(HttpServletRequest request, HttpServletResponse response) {
		
		Context context = null;
		
		try {
			initServletActionContext(request, response);
			
			initActionContext(request);
			
			setContentType(request, response);
			
			Action action = getAction(request);
			
			String templateName = doExecute(action, request, response);
			
			//在Action中调用response.sendRedirect();
			if(null == templateName) {
				return ;
			}
			
			context = createContext(action, request, response);
			
			Template template = handleRequest(templateName, request, response, context);
			
			mergeTemplate(template, context, response);
		} catch(Exception e) {
			try {
				e.printStackTrace(response.getWriter());
				response.getWriter().flush();
			} catch (IOException e1) {
				throw new RuntimeException(e);
			}
		} finally {
			destoryServletActionContext();
			destoryActionContext(request);
		}
	}
	
	/**
	 * 给ServletActionContext赋值
	 * @param request
	 * @param response
	 */
	protected void initServletActionContext(HttpServletRequest request,
			HttpServletResponse response) {
		ServletActionContext.setRequest(request);
		ServletActionContext.setResponse(response);
	}
	
	/**
	 * 给ActionContext赋值
	 * @param request
	 */
	protected void initActionContext(HttpServletRequest request) {
		//处理request
		Map<String, Object> values = new HashMap<String, Object>();
		
		Enumeration enumeration = request.getAttributeNames();
		while(enumeration.hasMoreElements()) {
			String key = (String)enumeration.nextElement();
			values.put(key, request.getAttribute(key));
		}
		
		ActionContext.setRequest(values);
		
		//处理session
		values = new HashMap<String, Object>();
		HttpSession session = request.getSession();
		if(null != session) {
			session = request.getSession(true);
		}
		
		enumeration = session.getAttributeNames();
		
		while(enumeration.hasMoreElements()) {
			String key = (String)enumeration.nextElement();
			values.put(key, session.getAttribute(key));
		}
		
		ActionContext.setSession(values);
		
		//处理ServletContext
		values = new HashMap<String, Object>();
		ServletContext servletContext = session.getServletContext();
		enumeration = servletContext.getAttributeNames();

		while(enumeration.hasMoreElements()) {
			String key = (String)enumeration.nextElement();
			values.put(key, session.getAttribute(key));
		}
		
		ActionContext.setServletContext(values);
	}
	
	/**
	 * 销毁当前线程的ServletActionContext
	 */
	protected void destoryServletActionContext() {
		ServletActionContext.destory();
	}
	
	/**
	 * 销毁当前线程的ActionContext
	 * @param request
	 */
	protected void destoryActionContext(HttpServletRequest request) {
		
		Map<String, Object> values = ActionContext.getContext().getRequest();
		for(Iterator<String> iter = values.keySet().iterator(); iter.hasNext(); ) {
			String key = iter.next();
			request.setAttribute(key, values.get(key));
		}
		
		values = ActionContext.getContext().getSession();
		HttpSession session = request.getSession();
		for(Iterator<String> iter = values.keySet().iterator(); iter.hasNext(); ) {
			String key = iter.next();
			session.setAttribute(key, values.get(key));
		}
		
		values = ActionContext.getContext().getServletContext();
		ServletContext servletContext = session.getServletContext();
		for(Iterator<String> iter = values.keySet().iterator(); iter.hasNext(); ) {
			String key = iter.next();
			servletContext.setAttribute(key, values.get(key));
		}
		
		ActionContext.destory();
		
	}
	
	protected String doExecute(Action action, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		
		String methodName = request.getParameter(parameterMethod);
		
		if(null == methodName || "".equals(methodName.trim())) {
			methodName = "execute";
		}
		
		Method method = action.getClass().getMethod(methodName);
		
		String templateName = (String)method.invoke(action);
		
		return templateName;
	}
	
	protected Context createContext(Action action, HttpServletRequest request,
			HttpServletResponse response){
		
		VelocityContext context = new VelocityContext();
		
		context.put(REQUEST, request);
		context.put(RESPONSE, response);
		
		Map<String, Object> params = action.getContext();
		for(Iterator<String> iter = params.keySet().iterator(); iter.hasNext(); ) {
			String key = iter.next();
			Object value = params.get(key);
			context.put(key, value);
		}

		return context;
	}
	
	private Action getAction(HttpServletRequest request) {
		String requestURI = request.getRequestURI();
		
		String actionName = requestURI.substring(requestURI.indexOf('/', 1), requestURI.lastIndexOf('.'));
		
		Action action = (Action)BeanFactory.getBean(actionName);
		
		if(null == action) {
			throw new RuntimeException("没有找到路径为:" + actionName + "对应的Action");
		}
		
		return action;
	}
	
	protected void setContentType(HttpServletRequest request,
            HttpServletResponse response) {
		response.setContentType(defaultContentType);
	}

	protected Template handleRequest(String templateName, HttpServletRequest request,
            HttpServletResponse response, Context ctx) {
		
		//do something......
		
		Template template = null;
		
		try {
			template = velocity.getTemplate(templateName);
		}  catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		return template;
	}
	
	protected void mergeTemplate(Template template,
            Context context,HttpServletResponse response) throws UnsupportedEncodingException, IOException {
		
		VelocityWriter vw = null;
		Writer writer = getResponseWriter(response);
		
		try {
			vw = pool.get();
			if(null == vw) {
				vw = new VelocityWriter(writer, 4*1024, true);
			} else {
				vw.recycle(writer);
			}
			template.merge(context, writer);
		} finally {
			if(null != vw) {
				vw.flush();
				vw.recycle(null);
				pool.put(vw);
			}
		}
	}
	
	protected Writer getResponseWriter(HttpServletResponse response)
			throws UnsupportedEncodingException, IOException {
		Writer writer = null;
		
		try {
			writer = response.getWriter();
        } catch (IllegalStateException e) {
	        String encoding = response.getCharacterEncoding();
	        if (encoding == null) {
	            encoding = DEFAULT_OUTPUT_ENCODING;
	        }
	        writer = new OutputStreamWriter(response.getOutputStream(), encoding);
	    }
        
	    return writer;
	}
}


这是一个简单的Bean工程实现,加载类路径下的beans.properties文件(这里完全可以用xml,这都是次要的问题,不是核心问题,等以后有时间了可以继续改进)
beans.properties文件,
路径=Action类,如:
/user=com.velocity.test.action.UserAction
package com.zzq.velocity.core;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

public class BeanFactory {
	
	private static Map<String, String> map = new HashMap<String, String>();
	
	static {
		InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("beans.properties");
		
		try {
			Properties prop = new Properties();
			prop.load(is);
			Iterator iter = prop.keySet().iterator();
			
			while(iter.hasNext()) {
				String key = (String)iter.next();
				String className = prop.getProperty(key);
				map.put(key, className);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("初始化BeanFactory失败", e);
		} finally {
			try {
				if(null != is) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
	
	public static Object getBean(String id) {
		
		//prototype
		
		String className = map.get(id);
		if(null == className) {
			return null;
		}
		
		Object action = null;
		try {
			action = Class.forName(className).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("创建Action类:" + className + "失败", e);
		}
		
		return action;
	}
}


ObjectPool对象池的实现,主要是对Writer进行管理。
package com.zzq.velocity.core;

import java.util.ArrayList;
import java.util.List;

/**
 * 对象池
 * @author zzq
 *
 */
public class ObjectPool<T> {

	/**
	 * 默认池大小
	 */
	public static final int DEFAULT_POOL_SIZE = 10;

	private int max;

         private int current=-1;
	
	private List<T> pool = null;
	
	public ObjectPool() {
		
		this(DEFAULT_POOL_SIZE);
	}
	
	public ObjectPool(int size) {
		max = size;
		pool = new ArrayList<T>(size);
	}
	
	public T get() {
		T obj = null;

		synchronized (this) {
			if(current > -1) {
				obj = pool.get(current);
				current --;
			}
		}
		return obj;
	}
	
	public void put(T obj) {
		synchronized (this) {
			current ++;
			if(current < max) {
				pool.add(obj);
				return ;
			}
			current --;
		}
	}
	
	public int getMax() {
		return max;
	}
	
	public List<T> getPool() {
		return pool;
	}
	
}


VelocityWriter类对Writer进行修饰,加入了Buffer。
package com.zzq.velocity.core;

import java.io.IOException;
import java.io.Writer;

public class VelocityWriter extends Writer {

    private int bufferSize;
    private boolean autoFlush;
    
    private Writer writer;

    private char cb[];
    private int next;
    
    private static final int DEFAULT_CHARBUFFER_SIZE = 8 * 1024;
    
    public VelocityWriter(Writer writer) {
    	 this(writer, DEFAULT_CHARBUFFER_SIZE, true);
    }
    
    public VelocityWriter(Writer writer, int size, boolean isFlush) {
    	
    	if(size < 0) {
    		throw new IllegalArgumentException("Buffer size < 0");
    	}
    	
    	this.bufferSize = size;
    	this.autoFlush = isFlush;
    	this.writer = writer;
    	
    	cb = size > 0 ? new char[size] : null;
    	next = 0;
    }
    
    public int getBufferSize() { return bufferSize; }

    public boolean isAutoFlush() { return autoFlush; }
    
    private final void flushBuffer() throws IOException {
    	
    	if(bufferSize == 0) {
    		return ;
    	} 
    	if(next == 0) {
    		return ;
    	}
    	writer.write(cb, 0, next);
    	this.next = 0;
    }
    
    public final void clear() {
        next = 0;
    }
    
    private final void bufferOverflow() throws IOException {
    	
    	throw new IOException("Buffer over flow!");
    }
    
    public final void write(int c) throws IOException {
    	
    	if(bufferSize == 0) {
    		writer.write(c);
    		return ;
    	}
    	
    	if(next >= bufferSize) {
    		if(autoFlush) {
    			flushBuffer(); 
    		} else {
    			bufferOverflow();
    		}
    	}
    	
    	cb[next++] = (char)c;
    }
    
    public final void write(char buf[]) throws IOException {
    	write(buf, 0, buf.length);
    }
    
    public final void write(String s, int off, int len) throws IOException {
    	write(s.toCharArray(), off, len);
    }
    
    public final void write(String s) throws IOException {
    	write(s, 0, s.length());
    }
    
    @Override
	public void write(char[] cbuf, int off, int len) throws IOException {

    	if(bufferSize == 0) {
    		writer.write(cbuf, off, len);
    		return ;
    	}
    	
    	if (len == 0)
        {
            return;
        }

        if (len >= bufferSize)
        {
            if (autoFlush)
                flushBuffer();
            else
                bufferOverflow();
            writer.write(cbuf, off, len);
            return;
        }
    	
    	if(len + off > cbuf.length) {
    		throw new IllegalArgumentException("len + off > cbuf.length");
    	}
    	
    	while(len > 0) {
    		int b = len > bufferSize - next ? bufferSize - next : len;
    		System.arraycopy(cb, next, cbuf, off, b);
        	next += b;
        	if(next >= bufferSize) {
        		if(autoFlush) {
        			flushBuffer(); 
        		} else {
        			bufferOverflow();
        		}
        	}
        	
        	off += b;
        	len -= b;
    	}
	}
    
    public final void recycle(Writer writer) {
    	this.writer = writer;
    	clear();
    }
    
	@Override
	public void close() throws IOException {
		if(writer != null) {
			flush();
			writer.close();
		}
	}

	@Override
	public void flush() throws IOException {
		flushBuffer(); 
		writer.flush();
	}
}


ServletActionContext这个类,挺简单的,一看就能明白,和Struts2的ServletActionContext功能一样。
package com.zzq.velocity.core;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class ServletActionContext {

	private static ThreadLocal<HttpServletRequest> reqContext = new ThreadLocal<HttpServletRequest>();
	
	private static ThreadLocal<HttpServletResponse> respContext = new ThreadLocal<HttpServletResponse>();

	public static void setRequest(HttpServletRequest request) {
		reqContext.set(request);
	}
	
	public static void setResponse(HttpServletResponse response) {
		respContext.set(response);
	}
	
	public static HttpServletRequest getRequset() {
		return reqContext.get();
	}
	
	public static HttpServletResponse getResponse() {
		return respContext.get();
	}
	
	public static HttpSession getSession() {
		return reqContext.get().getSession();
	}
	
	public static ServletContext getServletContext() {
		return reqContext.get().getSession().getServletContext();
	}
	
	public static void destory() {
		reqContext.remove();
		respContext.remove();
	}
}

这个更不用说了,玩过Struts2的人一看就知道。
package com.zzq.velocity.core;

import java.util.Map;

/**
 * 将Servlet API 进行解耦
 * @author zzq
 *
 */
public class ActionContext {

	private static ActionContext instance = new ActionContext();
	
	private static ThreadLocal<Map<String, Object>> request = new ThreadLocal<Map<String, Object>>();
	
	private static ThreadLocal<Map<String, Object>> session = new ThreadLocal<Map<String, Object>>();

	private static ThreadLocal<Map<String, Object>> servletContext = new ThreadLocal<Map<String, Object>>();
	
	private ActionContext() {}
	
	public static ActionContext getContext() {
		return instance;
	}
	
	public static void setRequest(Map<String, Object> value) {
		request.set(value);
	}
	
	public static void setSession(Map<String, Object> value) {
		session.set(value);
	}
	
	public static void setServletContext(Map<String, Object> value) {
		servletContext.set(value);
	}
	
	public Map<String, Object> getSession() {
		return session.get();
	}
	
	public Map<String, Object> getServletContext() {
		return servletContext.get();
	}
	
	public Map<String, Object> getRequest() {
		return request.get();
	}
	
	public static void destory() {
		request.remove();
		session.remove();
		servletContext.remove();
	}
}

一个接口,所有的Action类都必须要实现这个接口。
package com.zzq.velocity.core;

import java.util.Map;

public interface Action {
	
	public String execute() throws Exception;
	
	/**
	 * 获取Velocity需要的Context数据
	 * @return Context
	 */
	public Map<String, Object> getContext();
}


最后就是这个web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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">
  
  <servlet>
  	<servlet-name>VelocityActionServlet</servlet-name>
  	<servlet-class>com.zzq.velocity.core.VelocityActionServlet</servlet-class>
 	<init-param>
 		<param-name>properties</param-name>
 		<param-value>/WEB-INF/velocity.properties</param-value>
 	</init-param>
 	<init-param>
 		<param-name>templatePath</param-name>
 		<param-value>/vm</param-value>
 	</init-param>
 	<load-on-startup>10</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>VelocityActionServlet</servlet-name>
  	<url-pattern>*.html</url-pattern>
  </servlet-mapping>
</web-app>


核心的东西就是这些,下面玩一下这个框架。
1、定义Action类
package com.velocity.test.action;

import java.util.HashMap;
import java.util.Map;

import com.zzq.velocity.core.Action;
import com.zzq.velocity.core.ServletActionContext;

public class UserAction implements Action {

	private Map<String, Object> map = new HashMap<String, Object>();
	
	public String execute() throws Exception {

		return "/login.vm";
	}
	
	public String login() {
		
		String username = ServletActionContext.getRequset().getParameter("username");
		String password = ServletActionContext.getRequset().getParameter("password");
		
		User user = new User();
		user.setUsername(username);
		user.setPassword(password);
		
		System.out.println(username);
		System.out.println(password);
		
		map.put("user", user);
		
		ServletActionContext.getSession().setAttribute("user", user);
		
		return "/login_success.vm";
	}
	
	public String register() {
		
		String username = ServletActionContext.getRequset().getParameter("username");
		String password = ServletActionContext.getRequset().getParameter("password");
		
		System.out.println(username);
		System.out.println(password);
		
		return "/register_success.vm";
	}

	public String registerInput() {
		
		return "/register.vm";
	}
	
	public Map<String, Object> getContext() {
		return map;
	}
}


2、在beans.properties加入
/user=com.velocity.test.action.UserAction

3、定义模板,放到WebRoot/vm/下(这个路径可以在web.xml中配)
引用
<!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=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>用户登录</h2>
<form action="user.html" method="post">
<input type="hidden" name="method" value="login">
用户名:<input name="username"><br>
密码:<input name="password" type="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>

引用
<!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=UTF-8">
<title>Insert title here</title>
</head>
<body>
登录成功!$user.username<br>
session:$request.session.getAttribute('user').username
</body>
</html>

4、访问http://localhost:8080/Veloctiy/user.html 一看就知道

总之:这个就是现在闲着没意思编着玩的,缺少很多功能(如上传,参数类型装换,还有对整个框架的扩展如插件化等等),跟成型的MVC Framework没法发,但是如果有人力、时间、金钱,相信我们国人也会编出相当完美优雅的框架。
还有一个月就毕业了,回望过去,还是很向往自己的大学生活,面对现实只能勇敢的去面对。
分享到:
评论
33 楼 javaboy2010 2012-12-26  
不错,还没毕业,写出如此代码,楼主很强啊! 向楼主学习!
32 楼 enjsky 2010-06-03  
Java企业级框架 .Net企业级框架
EfsFrame就是一套基于Ajax技术实现的优秀的Java/.Net企业级框架,简单+实用+高效+稳定
开源下载地址:http://www.efsframe.cn/
大量的框架设计文档,帮助学习系统框架设计原理
31 楼 woming66 2010-06-03  
xiangkun 写道
woming66 写道
为什么自己写的东西发上来却被评为“隐藏帖”,本意想把自己学习收获的成果分享一下,难道这还有什么错吗?评价“隐藏帖”的人,你们这样做让我很心寒!




慢慢就会习惯了.. 我都已经习惯了..JE上的大鸟们都是这样的!!

谢谢你的回复,呵呵 已经想通了 应有网友的话“自己专研知识、与人分享交流,最后得到进步,这才是王道”。
30 楼 xiangkun 2010-06-03  
woming66 写道
为什么自己写的东西发上来却被评为“隐藏帖”,本意想把自己学习收获的成果分享一下,难道这还有什么错吗?评价“隐藏帖”的人,你们这样做让我很心寒!




慢慢就会习惯了.. 我都已经习惯了..JE上的大鸟们都是这样的!!
29 楼 woming66 2010-06-03  
ilove2009 写道
不错,还没毕业就有这水平了。前途无量。

谢谢你的回复,我会继续努力的!
28 楼 ilove2009 2010-06-03  
不错,还没毕业就有这水平了。前途无量。
27 楼 woming66 2010-06-03  
jenlp520 写道
woming66 写道
jenlp520 写道
我插 je没有防重复提交的吗??

这块还没做呢,现在只是个架子,解决重复提交,我的想法是定义一个Velocity的宏,页面input的时候,载入宏(就是往session中弄个值,页面有个hidden),到提价的action中进行比对session和表单hidden的值。


其实我说的是javaeye 回帖的时候手一抖 回了2个

呵呵 人无完人 何况论坛系统了
26 楼 woming66 2010-06-03  
Norton_SdGromo 写道
Velocity我不太懂,但是只要肯动手就精神可嘉,不要太在意那些给隐藏贴的,继续努力~~

谢谢你的回复!我会努力的!
25 楼 jenlp520 2010-06-03  
woming66 写道
jenlp520 写道
我插 je没有防重复提交的吗??

这块还没做呢,现在只是个架子,解决重复提交,我的想法是定义一个Velocity的宏,页面input的时候,载入宏(就是往session中弄个值,页面有个hidden),到提价的action中进行比对session和表单hidden的值。


其实我说的是javaeye 回帖的时候手一抖 回了2个
24 楼 Norton_SdGromo 2010-06-03  
Velocity我不太懂,但是只要肯动手就精神可嘉,不要太在意那些给隐藏贴的,继续努力~~
23 楼 woming66 2010-06-03  
janrn 写道
看到此贴,眼睛一亮。LZ继续加油。
结果不是最重要的,代码也不是最重要的,设计思想才是最大的收获,以及研究的能力。
恭喜你,取得如此结果。

谢谢你的回复,愿我们一起努力,以后多多交流经验!
22 楼 janrn 2010-06-03  
看到此贴,眼睛一亮。LZ继续加油。
结果不是最重要的,代码也不是最重要的,设计思想才是最大的收获,以及研究的能力。
恭喜你,取得如此结果。
21 楼 woming66 2010-06-03  
<div class="quote_title">zhangshixi 写道</div>
<div class="quote_div">
<div class="quote_title">woming66 写道</div>
<div class="quote_div">
<div class="quote_title">zhangshixi 写道</div>
<div class="quote_div">
<div class="quote_title">woming66 写道</div>
<div class="quote_div">为什么自己写的东西发上来却被评为“隐藏帖”,本意想把自己学习收获的成果分享一下,难道这还有什么错吗?评价“隐藏帖”的人,你们这样做让我很心寒!</div>
<br>写自己的博客、总结自己的知识,让别人去随意评论吧。其实大可不必在意这些,自己专研知识、与人分享交流,最后得到进步,这才是王道。<br>
</div>
<br>谢谢你的评价。您说的很对!自己专研知识、与人分享交流,最后得到进步,这才是王道。望以后继续交流!</div>
<p><br>我觉得这也许就是我们的心态吧,抛开万千世界不谈,只说在这么一个小小的社区中,其实已经繁琐复杂了:<br>有的人以看文章、学知识为乐;<br>有的人以总结知识、写博客为乐;<br>有的人以与人分享、交流为乐;<br>有的人以盲目追求点击率、人气为乐;<br>有的人以高高在上、傲视群雄为乐;<br>有的人以打发无聊、寂寞为乐<br>......<br>那么我们想想自己又属于哪种人呢?<br>也许当您看透了这些,任何鼓励、打击、甚至被人BS,都是过眼云烟罢了。</p>
<p> </p>
</div>
<p> </p>
<p>说的好!</p>
20 楼 zhangshixi 2010-06-03  
<div class="quote_title">woming66 写道</div>
<div class="quote_div">
<div class="quote_title">zhangshixi 写道</div>
<div class="quote_div">
<div class="quote_title">woming66 写道</div>
<div class="quote_div">为什么自己写的东西发上来却被评为“隐藏帖”,本意想把自己学习收获的成果分享一下,难道这还有什么错吗?评价“隐藏帖”的人,你们这样做让我很心寒!</div>
<br>写自己的博客、总结自己的知识,让别人去随意评论吧。其实大可不必在意这些,自己专研知识、与人分享交流,最后得到进步,这才是王道。<br>
</div>
<br>谢谢你的评价。您说的很对!自己专研知识、与人分享交流,最后得到进步,这才是王道。望以后继续交流!</div>
<p><br>我觉得这也许就是我们的心态吧,抛开万千世界不谈,只说在这么一个小小的社区中,其实已经繁琐复杂了:<br>有的人以看文章、学知识为乐;<br>有的人以总结知识、写博客为乐;<br>有的人以与人分享、交流为乐;<br>有的人以盲目追求点击率、人气为乐;<br>有的人以高高在上、傲视群雄为乐;<br>有的人以打发无聊、寂寞为乐<br>......<br>那么我们想想自己又属于哪种人呢?<br>也许当您看透了这些,任何鼓励、打击、甚至被人BS,都是过眼云烟罢了。</p>
<p> </p>
19 楼 woming66 2010-06-03  
jenlp520 写道
我插 je没有防重复提交的吗??

这块还没做呢,现在只是个架子,解决重复提交,我的想法是定义一个Velocity的宏,页面input的时候,载入宏(就是往session中弄个值,页面有个hidden),到提价的action中进行比对session和表单hidden的值。
18 楼 woming66 2010-06-03  
jenlp520 写道
无论LZ这个东西写不好 都必须表扬下 是自己动手的 必定会有收获
至于那些评隐藏的 不用理他们 中国人有个特点就是 越是下层的人的在获得一点点权利后就会去欺负比他们更下层的人来获得快感

呵呵 谢谢你的回复。我会继续努力的!
17 楼 woming66 2010-06-03  
hardPass 写道
大概浏览量下,没仔细看,总归发现:
哦,不错哦!

我总觉着parse是个不可靠的东西——也许是错觉
不过如果能自己控制Velocity模板的缓存,细粒度的控制到页面片段的缓存,那就更好了

这个小弟弟,刚毕业就这么来塞,前途无量啊
不错,不错

谢谢你的回复!恩,这里的确有很多地方要改进,要重构的,随着今后的学习,我会继续完善它!
16 楼 jenlp520 2010-06-03  
我插 je没有防重复提交的吗??
15 楼 jenlp520 2010-06-03  
无论LZ这个东西写不好 都必须表扬下 是自己动手的 必定会有收获
至于那些评隐藏的 不用理他们 中国人有个特点就是 越是下层的人的在获得一点点权利后就会去欺负比他们更下层的人来获得快感
14 楼 jenlp520 2010-06-03  
无论LZ这个东西写不好 都必须表扬下 是自己动手的 必定会有收获
至于那些评隐藏的 不用理他们 中国人有个特点就是 越是下层的人的在获得一点点权利后就会去欺负比他们更下层的人来获得快感

相关推荐

    基于Ajax的新MVC框架的研究与实现

    本文将Ajax技术与MVC模式紧密结合,设计了一个新的MVC框架。应用该框架后,客户端请求基本都是Ajax请求。本文首次采用了Container这一概念,并提出了Container树结构信息的表示法,设计了针对该表示法的解析及生成算法。...

    spring mvc mybatis velocity 示范

    MyBatis 是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。Velocity 是一款强大的模板引擎,能够帮助开发者将动态内容和静态内容分离,提升网站的开发效率和可维护性。 Spring MVC 框架详解: ...

    Struts 2 自定义MVC 框架

    它通过提供一个统一的架构来管理控制器、视图和模型,使得开发者能够更专注于业务逻辑,而不是底层实现细节。自定义Struts 2 MVC框架的过程有助于深入理解其工作原理,从而更好地应用和优化项目。 首先,我们来详细...

    Spring-MVC框架简单实现

    Spring MVC 是 Spring 框架的一部分,它是一个用于构建 Web 应用程序的模型-视图-控制器(MVC)架构。在这个简易版框架中,我们将深入理解 Spring MVC 的核心概念和关键组件。 **1. MVC 架构模式** 在 MVC 模式中,...

    一套基于SpringMVC+velocity框架的web应用 ,基于注解

    SpringMVC是Spring框架的一部分,它是一个用于构建Web应用程序的轻量级、模型-视图-控制器(MVC)框架。基于注解的SpringMVC允许开发者在控制器类的方法上直接使用注解,如@RequestMapping,@RequestParam等,极大地...

    设计 REST 风格的 MVC 框架

    因此,设计一个原生支持REST风格的MVC框架,以适应现代Web开发的需求,变得尤为重要。 #### REST风格的MVC框架设计原理 在设计REST风格的MVC框架时,关键在于如何将URL直接映射到具体的控制器方法上,而不是像传统...

    spring mvc与velocity整合

    Velocity是一个基于Java的模板引擎,它的主要目标是提供一个简洁、高效的模板语言,使开发者可以专注于页面布局和设计,而不用关心底层的Java代码。Velocity模板语言(VTL)允许开发者在模板中引用Java对象,动态...

    北大青鸟使用MVC框架开发大型网站

    - Struts2:这是一个基于MVC设计模式的Web应用框架,用于简化JSP/Servlet的开发。它处理HTTP请求,控制流程,并提供了丰富的动作和拦截器机制,使得业务逻辑的组织更加清晰。 - Spring:Spring框架是一个全面的后端...

    maven+springMVC+mybatis+velocity+mysql+junit项目框架搭建

    JUnit是Java语言的一个单元测试框架,用于编写和运行可重复的测试。开发者可以利用JUnit编写测试用例,确保代码的功能正确性,提高代码质量。在项目开发过程中,Junit起到了关键的测试保障作用,帮助尽早发现和修复...

    maven搭建spring mvc velocity+mybatis

    总结起来,"maven搭建spring mvc(velocity+mybatis)"是一个典型的Java Web开发流程,它结合了项目管理、Web框架、模板引擎和持久层工具。通过这样的实践,开发者可以更好地理解和掌握现代企业级应用的构建方式,提升...

    Maven 整合 Spring mvc + Mybatis + Velocity 的实例

    本实例将探讨如何使用Maven作为项目管理工具,结合Spring MVC作为控制层框架,Mybatis作为数据访问层框架,以及Velocity作为视图层模板引擎,来构建一个完整的Java Web应用。以下是关于这些技术的详细解释和整合步骤...

    Maven + Spring mvc + Mybatis + Velocity 整合实例

    本示例提供了一个基于Maven、Spring MVC、Mybatis和Velocity的整合实例,旨在帮助开发者理解并掌握这四大技术栈的协同工作方式。这四个组件在Java Web开发中扮演着至关重要的角色: 1. Maven:Maven是一款项目管理...

    spring mvc sitemesh velocity整合

    Velocity 是一个基于Java的模板引擎,它允许开发者使用简单的模板语言来生成动态内容。Velocity与JSP相比,更注重模板的纯粹性和可读性,避免了JSP中的过多Java代码,使得模板更加易于维护。在Spring MVC中,...

    spring mvc框架搭建

    Spring MVC 是 Spring 框架的一个模块,它为构建基于 Java 的 Web 应用程序提供了一个模型-视图-控制器(MVC)架构。在本文中,我们将深入探讨如何使用 Maven 搭建一个包含 Spring MVC、MyBatis 和 Velocity 的基本...

    Velocity+Struts 配置

    Velocity 是一个基于Java的模版引擎。它允许web 页面设计者引用JAVA代码预定义的方法。Web 设计者可以根据MVC模式和JAVA程序员并行工作,这意味着Web设计者可以单独专注于设计良好的站点,而程序员则可单独专注于...

    spring+velocity+ibatis

    Velocity是Apache软件基金会的一个开源项目,它是一个基于Java的模板引擎,主要用于生成动态Web内容。Velocity将展示逻辑与业务逻辑分离,允许开发者专注于内容和布局,而无需关心如何控制页面流程。它的模板语言...

    自定义mvc框架

    Struts是Apache软件基金会的一个开源项目,是一个基于MVC设计模式的Java Web应用框架。它提供了以下核心功能: 1. **Action**:Struts的控制器部分,处理用户请求并调用对应的业务逻辑。 2. **ActionForm**:用于...

    velocity-1.5.jar,velocity-1.6.2-dep.jar,velocity-tools-1.3.jar

    这些JAR文件在Java Web应用中尤其有用,特别是对于那些基于MVC框架(如Struts或Spring MVC)的应用。Velocity可以作为视图层的模板引擎,使得开发者可以通过简单的模板语言来生成动态HTML,而无需深入理解复杂的JSP...

    velocity插件

    Velocity 是一款基于 Java 的模板引擎,它被广泛应用于 Web 开发中,特别是作为 Apache Struts 和 Spring MVC 框架的一部分。Velocity 插件则是为了在开发环境中提供对 Velocity 模板语言的支持,使得开发者可以在 ...

    mvc自定义框架

    本篇将深入探讨如何自定义一个简单的MVC框架,以帮助初学者更好地理解和应用这一模式。 首先,我们来了解 MVC 架构的基本组成部分: 1. **模型(Model)**:模型是应用程序的核心,负责处理业务逻辑和数据管理。它...

Global site tag (gtag.js) - Google Analytics