java获取uriinfo_javaweb-servlet实现简单的mvc分发请求

这篇博客介绍了如何使用Java自定义Servlet实现基于注解的MVC请求分发,利用Freemarker进行视图渲染。通过创建Controller和RequestMapping注解标记控制器和URL映射,使用反射工具类解析这些注解,建立URI信息,并定义视图解析器处理Freemarker模板。最后展示了DispatcherServlet的实现和一个简单的测试控制器。
摘要由CSDN通过智能技术生成

自定义servlet请求分发,模拟mvc,视图采用freemarker2.3.27

1).创建注解

标记控制器注解Controller

仅仅起到标记的作用,没有什么具体的作用_

package com.fkt.core.annotation;

import static java.lang.annotation.ElementType.TYPE;

import java.lang.annotation.Documented;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

* 标记控制器

* @author xuzhen

*

*/

@Target(TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Controller {

}

标记映射注解RequestMapping

value就是用来存储请求Url,用来分发请求用的

package com.fkt.core.annotation;

import static java.lang.annotation.ElementType.METHOD;

import static java.lang.annotation.ElementType.TYPE;

import java.lang.annotation.Documented;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

* 标记url

* @author xuzhen

*

*/

@Target({ TYPE, METHOD })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface RequestMapping {

/**

* 路径映射值

* @return

*/

String value() default "";

}

2).定义实体类

存储视图和数据的实体类ModelAndView

package com.fkt.core.entity;

import java.util.HashMap;

import java.util.Map;

/**

* 包含视图和数据的实体类,主要用于freemarker渲染使用

* @author xuzhen

*

*/

@SuppressWarnings({"rawtypes","unchecked"})

public class ModelAndView {

//视图名称

private String viewName = null;

//模板根容器

private Map root = null;

public ModelAndView() {

root = new HashMap();

}

public ModelAndView(String viewName) {

this();

this.viewName=viewName;

}

public String getViewName() {

return viewName;

}

public void setViewName(String viewName) {

this.viewName = viewName;

}

public Map getRoot() {

return root;

}

/**

* 增加数据

* @param key

* @param value

*/

public void addObject(Object key,Object value) {

root.put(key, value);

}

}

路径映射具体信息的实体类URIInfo

Method是反射包里的一个类,代表类的方法,有点类似c++的方法指针,想具体了解的话,就去看看java的反射吧_!

package com.fkt.core.entity;

import java.lang.reflect.Method;

/**

* uri的实体类,包含uri对应的控制器和控制器方法

* @author xuzhen

*

*/

public class URIInfo {

//控制器键

private String controllerId;

//控制器方法

private Method uriMethod;

public URIInfo() {}

public URIInfo(String controllerId,Method uriMethod) {

this.controllerId=controllerId;

this.uriMethod=uriMethod;

}

public String getControllerId() {

return controllerId;

}

public void setControllerId(String controllerId) {

this.controllerId = controllerId;

}

public Method getUriMethod() {

return uriMethod;

}

public void setUriMethod(Method uriMethod) {

this.uriMethod = uriMethod;

}

}

3). 编写反射工具类

根据注解把控制器添加到容器,根据注解存储映射的具体信息(映射路径,控制器方法)

package com.fkt.core.tool;

import java.io.File;

import java.lang.annotation.Annotation;

import java.lang.reflect.Method;

import java.net.URISyntaxException;

import java.util.HashMap;

import java.util.Map;

import java.util.UUID;

import com.fkt.core.annotation.Controller;

import com.fkt.core.annotation.RequestMapping;

import com.fkt.core.entity.URIInfo;

/**

* 反射相关工具类

* @author xuzhen

*

*/

public abstract class ReflexUtils {

/**

* 根据包名反射解析所有的控制器

* @param packageName

* @return

* @throws URISyntaxException

* @throws ClassNotFoundException

* @throws IllegalAccessException

* @throws InstantiationException

*/

@SuppressWarnings({ "rawtypes", "unchecked" })

public static Map analysisController(String packageName) throws URISyntaxException, ClassNotFoundException, InstantiationException, IllegalAccessException{

Map controllersMap = new HashMap();

ClassLoader classLoader = ReflexUtils.class.getClassLoader();

String packageDirectory = packageName.replace(".", "/");

File directory = new File(classLoader.getResource(packageDirectory).toURI());

for(File file : directory.listFiles()) {

String fName = file.getName();

if(!fName.endsWith(".class")) {

continue;

}

fName = fName.substring(0, fName.length() - 6);

String className = packageName+"."+fName;

Class cl = classLoader.loadClass(className);

//检查解析包中的类是否带有Controller注解,没有注解不往容器中添加实例

Annotation controllerAnnotation = cl.getAnnotation(Controller.class);

if(controllerAnnotation!=null) {

controllersMap.put(UUID.randomUUID().toString(), cl.newInstance());

}

}

return controllersMap;

}

/**

* 解析控制器上和方法上的RequestMapping注解,并存储对应的方法到容器

* @param controllersMap

* @return

*/

@SuppressWarnings({ "unchecked", "rawtypes" })

public static Map analysisURIByController(Map controllersMap){

Map uriInfosMap = new HashMap();

for(String controllerId : controllersMap.keySet()) {

Object controller = controllersMap.get(controllerId);

Class controllerClass = controller.getClass();

String uriPrefix = "";

//解析类controller上的ReqestMapping注解

Annotation cRequestMappingAnnotation = controllerClass.getAnnotation(RequestMapping.class);

if(cRequestMappingAnnotation!=null) {

RequestMapping requestMapping = (RequestMapping)cRequestMappingAnnotation;

uriPrefix = requestMapping.value();

}

Method[] controllerMethods = controllerClass.getMethods();

for(Method controllerMethod : controllerMethods) {

Annotation mRequestMappingAnnotation = controllerMethod.getAnnotation(RequestMapping.class);

if(mRequestMappingAnnotation!=null) {

RequestMapping requestMapping = (RequestMapping)mRequestMappingAnnotation;

String uri = uriPrefix+requestMapping.value();

URIInfo uriInfo = new URIInfo(controllerId, controllerMethod);

uriInfosMap.put(uri, uriInfo);

}

}

}

return uriInfosMap;

}

}

4). 定义视图解析器,解析freemarker页面

package com.fkt.core.resolver;

import java.io.File;

import java.io.IOException;

import java.io.Writer;

import java.net.URI;

import javax.servlet.http.HttpServletResponse;

import com.fkt.core.entity.ModelAndView;

import freemarker.core.ParseException;

import freemarker.template.Configuration;

import freemarker.template.MalformedTemplateNameException;

import freemarker.template.Template;

import freemarker.template.TemplateException;

import freemarker.template.TemplateExceptionHandler;

import freemarker.template.TemplateNotFoundException;

/**

* 简单的freemarker模板处理引擎

* @author xuzhen

*

*/

public class FreemarkerViewResolver {

private Configuration cfg = null;

private String defaultEncoding = "UTF-8";

public FreemarkerViewResolver() {

}

public FreemarkerViewResolver(String defaultEncoding) {

this.defaultEncoding=defaultEncoding;

}

/**

* 初始化freemarker引擎

* @param directory

* @throws IOException

*/

public void init(URI viewDirectory) throws IOException {

cfg = new Configuration(Configuration.VERSION_2_3_27);

cfg.setDefaultEncoding(defaultEncoding);

cfg.setDirectoryForTemplateLoading(new File(viewDirectory));

cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

cfg.setLogTemplateExceptions(false);

cfg.setWrapUncheckedExceptions(true);

}

//视图解析方法

public void resolver(ModelAndView mav,HttpServletResponse response) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException {

Template template = cfg.getTemplate(mav.getViewName());

Writer out = response.getWriter();

template.process(mav.getRoot(), out);

out.flush();

}

}

5). 定义请求分发servlet

package com.fkt.core;

import java.io.IOException;

import java.util.Map;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.fkt.core.entity.ModelAndView;

import com.fkt.core.entity.URIInfo;

import com.fkt.core.resolver.FreemarkerViewResolver;

import com.fkt.core.tool.ReflexUtils;

/**

* freemarker测试核心分发控制器

* @author xuzhen

*

*/

public class DispatcherServlet extends HttpServlet {

private static final long serialVersionUID = 1762792866529445537L;

//定义存储所有的控制器的容器

private Map controllersMap = null;

//定义存储uri信息容器

private Map uriInfosMap = null;

//创建模板引擎

private FreemarkerViewResolver viewResolver = null;

//编码默认使用utf-8

private String defaultCharacterEncoding = "UTF-8";

@Override

public void init() throws ServletException {

defaultCharacterEncoding = getInitParameter("characterEncoding");

String mvcPackage = getInitParameter("mvcPackage");

String viewDirectory = getInitParameter("viewDirectory");

try {

controllersMap = ReflexUtils.analysisController(mvcPackage);

uriInfosMap = ReflexUtils.analysisURIByController(controllersMap);

viewResolver = new FreemarkerViewResolver(defaultCharacterEncoding);

viewResolver.init(getServletContext().getResource(viewDirectory).toURI());

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

doPost(req, resp);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

req.setCharacterEncoding(defaultCharacterEncoding);

resp.setCharacterEncoding(defaultCharacterEncoding);

String uri = req.getRequestURI().replace(req.getServletContext().getContextPath(), "");

URIInfo uriInfo = uriInfosMap.get(uri);

try {

Object mavObject = uriInfo.getUriMethod().invoke(controllersMap.get(uriInfo.getControllerId()), req,resp);

if(mavObject!=null) {

viewResolver.resolver((ModelAndView) mavObject, resp);

return;

}

} catch (Exception e) {

//处理最外层捕捉错误,并抛到前台

e.printStackTrace(resp.getWriter());

return;

}

//没有正确的处理时的输出

resp.getWriter().println("^_^ error!");

resp.getWriter().flush();

}

@Override

public void destroy() {

}

}

6). 使用

web.xml

freemarker-test

index.html

dispatcherServlet

com.fkt.core.DispatcherServlet

mvcPackage

com.fkt.web.controller

viewDirectory

/WEB-INF/views

characterEncoding

UTF-8

dispatcherServlet

/

TestController

package com.fkt.web.controller;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.fkt.core.annotation.Controller;

import com.fkt.core.annotation.RequestMapping;

import com.fkt.core.entity.ModelAndView;

@Controller

public class TestController {

@RequestMapping("/")

public ModelAndView index(HttpServletRequest request,HttpServletResponse response) throws IOException {

ModelAndView mav = new ModelAndView("index.ftl");

mav.addObject("name", "欢迎进入首页!");

return mav;

}

}

index.ftl

首页

${name!""}

代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单JavaWeb登录功能实现代码示例: ```java // 导入必要的包 import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { // 设置响应内容类型 response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html><head><title>Login</title></head><body>"); out.println("<h1>JavaWeb登录功能实现</h1>"); // 获取表单参数 String username = request.getParameter("username"); String password = request.getParameter("password"); // 检查登录信息是否正确 if (username.equals("admin") && password.equals("admin")) { // 创建会话并将用户名存储在会话中 HttpSession session = request.getSession(true); session.setAttribute("username", username); // 重定向到成功页面 response.sendRedirect("success.jsp"); } else { // 登录失败 out.println("<p>用户名或密码错误,请重新输入!</p>"); out.println("<a href='login.jsp'>返回登录页面</a>"); } out.println("</body></html>"); out.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { doGet(request, response); } } ``` 在上述代码中,我们使用了 `doGet` 方法来处理 GET 请求和 `doPost` 方法来处理 POST 请求。当用户提交登录表单时,我们获取表单中的用户名和密码,并在后台验证。如果登录信息正确,我们创建一个会话并将用户名存储在会话中,然后重定向到成功页面。如果登录信息不正确,则返回登录页面并显示错误消息。 这只是一个简单的示例,实际的登录功能可能需要更多的验证和安全措施。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值