这几天在家写了一个简陋版的SpringMVC,先把代码贴出来,有兴趣的同学可以看一下。
首先定义了一个简陋的服务器,其实也就是用了ServerSocket写了一个服务端(更详细的点看这里:创建一个简单的web服务器):
public class HttpServer { public static void main(String[] args) { await(); } private static void await() { ServerSocket serverSocket = null; try { ApplicationContext ac = new ApplicationContext(new HttpServletImpl(), "/com/zkn/fullstacktraining/spring/one/spring-config.properties"); ac.init(); boolean shutDown = false; //创建一个服务端 serverSocket = new ServerSocket(8005, 1, InetAddress.getByName("127.0.0.1")); //用线程池处理请求 ExecutorService executorService = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(), new ThreadFactoryBuilder().setNameFormat("XX-task-%d").build()); while (!shutDown) { //接收客户端请求 ProcessSocket processSocket = new ProcessSocket(serverSocket.accept()); executorService.execute(processSocket); } } catch (Exception e) { e.printStackTrace(); System.exit(0); } } }这里用了线程池来处理多个socket连接。
接着我们需要自定义一个Request和Response两个类来处理请求和响应信息。
Request这里存了请求头信息、请求参数信息、请求类型、请求URI等。Request的代码如下:
public class Request { /** * 输入流 */ private InputStream inputStream; /** * 头文件信息 */ private Map<String, String> headerMap = new HashMap<>(); /** * 参数信息 */ private Map<String, Object> parameterMap = new HashMap<>(); /** * 是否被解析过 */ private boolean isParser = false; /** * 请求类型 */ private String requestMethod; /** * 请求URI */ private String uri; public Request(InputStream inputStream) { this.inputStream = inputStream; } /** * 获取头文件信息 * * @param key * @return */ public String getHeader(String key) { if (key == null) { return null; } return headerMap.get(key.toLowerCase()); } /** * 获取参数的值 * * @param key * @return */ public String getParameterValue(String key) { Object obj = parameterMap.get(key); if (obj == null) return null; if (obj instanceof List) { if (!((List) obj).isEmpty()) { return (String) ((List) obj).get(0); } return null; } return (String) obj; } /** * 获取多个值 * * @param key * @return */ public List<String> getParameterValues(String key) { Object obj = parameterMap.get(key); if (obj == null) { return null; } if (obj instanceof List) { return (List<String>) obj; } return null; } /** * 获取所有的key * * @return */ public Set<String> getParameterNames() { return parameterMap.keySet(); } public String getRequestMethod() { return requestMethod; } /** * 解析请求 */ public void parseRequest() { if (isParser) { return; } isParser = true; //这里用了BufferedReader 没有考虑性能问题 BufferedReader lineNumberReader = new BufferedReader(new InputStreamReader(inputStream)); try { //获取请求行 请求行格式 Method URI 协议 String str = lineNumberReader.readLine(); if (str != null) { String[] strArray = str.split(" "); requestMethod = strArray[0]; parseUrl(strArray[1]); } String headerStr = null; String[] strArr = null; //解析头信息 while ((headerStr = lineNumberReader.readLine()) != null) { if ("".equals(headerStr)) { break; } strArr = headerStr.split(":"); if (strArr.length == 2) { headerMap.put(strArr[0].toLowerCase(), strArr[1].trim()); } } //如果是POST请求 String contentType = null; if ("POST".equals(requestMethod)) { //文件上传 if ((contentType = headerMap.get("content-type")) != null && headerMap.get("content-type").startsWith("multipart/form-data")) { //解析文件上传 parseUploadFile(lineNumberReader, contentType); } else { //非文件上传 String postParameter = ""; while ((postParameter = lineNumberReader.readLine()) != null) { if ("".equals(postParameter)) { break; } wrapperParameterValue(postParameter); } } } System.out.println(JSON.toJSONString(parameterMap)); } catch (IOException e) { e.printStackTrace(); } System.out.println("执行完了。。。"); } private void parseUploadFile(BufferedReader lineNumberReader, String contentType) throws IOException { String str;//文件上传的分割位 这里只处理单个文件的上传 String boundary = contentType.substring(contentType.indexOf("boundary") + "boundary=".length()); //解析消息体 while ((str = lineNumberReader.readLine()) != null) { //解析结束的标记 do { //读取boundary中的内容 //读取Content-Disposition str = lineNumberReader.readLine(); //说明是文件上传 if (str.indexOf("Content-Disposition:") >= 0 && str.indexOf("filename") > 0) { str = str.substring("Content-Disposition:".length()); String[] strs = str.split(";"); String fileName = strs[strs.length - 1].replace("\"", "").split("=")[1]; System.out.println("fileName = " + fileName); //这一行是Content-Type lineNumberReader.readLine(); //这一行是换行 lineNumberReader.readLine(); //正式去读文件的内容 BufferedWriter bw = null; try { bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("G:\\LearnVideo\\fileLoad" + File.separator + fileName), "UTF-8")); while (true) { str = lineNumberReader.readLine(); if (str.startsWith("--" + boundary)) { break; } bw.write(str); bw.newLine(); } bw.flush(); } catch (Exception e) { } finally { if (bw != null) { bw.close(); } } } if (str.indexOf("Content-Disposition:") >= 0) { str = str.substring("Content-Disposition:".length()); String[] strs = str.split(";"); String name = strs[strs.length - 1].replace("\"", "").split("=")[1]; lineNumberReader.readLine(); StringBuilder stringBuilder = new StringBuilder(); while (true) { str = lineNumberReader.readLine(); if (str.startsWith("--" + boundary)) { break; } stringBuilder.append(str); } parameterMap.put(name, stringBuilder.toString()); } } while (("--" + boundary).equals(str)); //解析结束 if (str.equals("--" + boundary + "--")) { break; } } } /** * 解析URI * * @param s */ private void parseUrl(String s) { if ("/".equals(s)) { uri = "/"; return; } String tempStr = s; /** * 说明可能带参数 */ int flag = 0; if ((flag = tempStr.indexOf("?")) > 0) { uri = tempStr.substring(0, flag); if (tempStr.length() > (flag + 1)) { tempStr = tempStr.substring(flag + 1, tempStr.length()); String[] strArray = tempStr.split("&"); for (String str : strArray) { wrapperParameterValue(str); } } return; } uri = s; } /** * 组装参数值 * * @param str */ private void wrapperParameterValue(String str) { Object value; String[] strArr = str.split("="); if (strArr.length == 2) { value = parameterMap.get(strArr[0]); if (value == null) { parameterMap.put(strArr[0], strArr[1]); } else { if (value instanceof List) { ((List) value).add(strArr[1]); } else { List<String> list = new ArrayList<>(2); list.add((String) value); list.add(strArr[1]); parameterMap.put(strArr[0], strArr[1]); } } } } public String getUri() { return uri; }Response这里只处理了返回简单字符串和返回静态资源文件,Response的代码如下:
public class Response { /** * 输出流 */ private OutputStream outputStream; /** * 字符输出流 */ private PrintWriter printWriter; /** * 请求类 */ private Request request; /** * Cookie信息 */ private List<Cookie> cookieList = new ArrayList<>(2); public Response(OutputStream outputStream, Request request) { this.outputStream = outputStream; this.request = request; } public void sendStaticResource(String path) { FileInputStream fis = null; try { if ("/".equals(path)) { path = "/static/html/index.html"; } else { path = request.getUri(); } URL url = this.getClass().getResource(path); if (url != null) { File file = new File(url.getFile()); if (file.exists() && !file.isDirectory() && file.canRead()) { fis = new FileInputStream(file); int flag = 0; byte[] bytes = new byte[1024]; while ((flag = fis.read(bytes)) != -1) { outputStream.write(bytes, 0, flag); } } } else { PrintWriter printWriter = getWriter(); //这里用PrintWriter字符输出流,设置自动刷新 printWriter.write("HTTP/1.1 404 File Not Found \r\n"); printWriter.write("Content-Type: text/html\r\n"); printWriter.write("Content-Length: 23\r\n"); printWriter.write("\r\n"); printWriter.write("<h1>File Not Found</h1>"); printWriter.close(); } } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } public PrintWriter getWriter() throws IOException { printWriter = new PrintWriter(outputStream, true); return printWriter; } public void sendSuccess() { PrintWriter printWriter = null; try { printWriter = getWriter(); //这里用PrintWriter字符输出流,设置自动刷新 printWriter.write("HTTP/1.1 200 OK \r\n"); printWriter.write("Content-Type: text/html;charset=utf-8\r\n"); printWriter.write("Content-Length: " + "成功了".getBytes().length + "\r\n"); if (cookieList != null && !cookieList.isEmpty()) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < cookieList.size(); i++) { //设置多个Cookie sb.append("Set-Cookie: ").append(cookieList.get(i).getKey()).append("=").append(cookieList.get(i).getValue()).append("\r\n"); } printWriter.write(sb.toString()); } printWriter.write("\r\n"); printWriter.write("成功了"); } catch (IOException e) { e.printStackTrace(); } finally { printWriter.close(); } } public void addCookie(Cookie cookie) { cookieList.add(cookie); } }这里我们模仿Servlet,也自定义一个Servlet接口。代码如下:
public interface Servlet { void init(); void service(Request request, Response response) throws Exception; void destory(); }它的一个实现类如下,在这个类中我们根据URI找到对应的请求处理类,并调用响应的请求方法。
public class HttpServletImpl implements Servlet { private StaticResourceProcessor resouce = new StaticResourceProcessor(); @Override public void init() { System.out.println("我被初始化了、、、、、"); } @Override public void service(Request request, Response response) throws Exception { String uri = request.getUri(); if ("/".equals(uri) || (!StringUtils.isEmpty(uri) && uri.startsWith("/static/"))) { //处理静态资源 resouce.process(request, response); } else { RequestMappingInfo mappingInfo = ApplicationContext.mappingMap.get(uri); if (mappingInfo != null) { List<String> parameterList = mappingInfo.getParameter(); int parLen = mappingInfo.getParameter().size() - 1; Class<?>[] clazzs = mappingInfo.getFormalParameter(); List<Object> list = new ArrayList<>(); Object obj = null; if (clazzs != null) { for (int i = 0; i < clazzs.length; i++) { obj = getObject(request, response, parameterList, parLen < i, clazzs[i], i); list.add(obj); } } mappingInfo.getMethod().invoke(mappingInfo.getObj(), list.toArray()); response.sendSuccess(); } } } /** * 组装方法的参数 * * @param request * @param response * @param parameterList * @param b * @param clazz * @param i * @return * @throws InstantiationException * @throws IllegalAccessException */ private Object getObject(Request request, Response response, List<String> parameterList, boolean b, Class<?> clazz, int i) throws InstantiationException, IllegalAccessException { Object obj = null; //如果参数类型为Request if (clazz.isAssignableFrom(Request.class)) { obj = request; } else if (clazz.isAssignableFrom(Response.class)) { //如果参数类型为Response obj = response; } //如果是字节类型(包含基本类型和包装类) else if (clazz == byte.class || clazz == Byte.class) { if (!b) { obj = Byte.parseByte(request.getParameterValue(parameterList.get(i))); } } //如果是short类型(包含基本类型和包装类) else if (clazz == short.class || clazz == Short.class) { if (!b) { obj = Short.parseShort(request.getParameterValue(parameterList.get(i))); } } //如果是char类型(包含基本类型和包装类) else if (clazz == char.class || clazz == Character.class) { } //如果是整型(包含基本类型和包装类) else if (clazz == int.class || clazz == Integer.class) { if (!b) { obj = Integer.parseInt(request.getParameterValue(parameterList.get(i))); } } //如果是float(包含基本类型和包装类) else if (clazz == float.class || clazz == Float.class) { if (!b) { obj = Float.parseFloat(request.getParameterValue(parameterList.get(i))); } } //如果是double(包含基本类型和包装类) else if (clazz == double.class || clazz == Double.class) { if (!b) { obj = Double.parseDouble(request.getParameterValue(parameterList.get(i))); } } //如果是double(包含基本类型和包装类) else if (clazz == long.class || clazz == Long.class) { if (!b) { obj = Long.parseLong(request.getParameterValue(parameterList.get(i))); } } //如果是boolean(包含基本类型和包装类) else if (clazz == boolean.class || clazz == Boolean.class) { if (!b) { obj = Boolean.parseBoolean(request.getParameterValue(parameterList.get(i))); } } //如果是boolean(包含基本类型和包装类) else if (clazz == String.class) { if (!b) { obj = request.getParameterValue(parameterList.get(i)); } } //如果是日期类型,先不做处理 else if (clazz == Date.class) { obj = new Date(); } else { //暂不考虑数组、集合、Map等类型 obj = clazz.newInstance(); Field[] fields = obj.getClass().getDeclaredFields(); wrapperObjectFieldValue(request, obj, fields); } return obj; } /** * 组装属性对象值 * * @param request * @param obj * @param fields * @throws IllegalAccessException */ private void wrapperObjectFieldValue(Request request, Object obj, Field[] fields) throws IllegalAccessException { if (fields != null) { Field field = null; for (int j = 0; j < fields.length; j++) { field = fields[j]; String fieldName = field.getName(); field.setAccessible(true); String value = request.getParameterValue(fieldName); if (value != null && !"".equals(value)) { if (field.getType() == byte.class || field.getType() == Byte.class) { field.set(obj, Byte.parseByte(value)); } //如果是short类型(包含基本类型和包装类) else if (field.getType() == short.class || field.getType() == Short.class) { field.set(obj, Short.parseShort(value)); } //如果是char类型(包含基本类型和包装类) else if (field.getType() == char.class || field.getType() == Character.class) { field.set(obj, value.toCharArray()[0]); } //如果是整型(包含基本类型和包装类) else if (field.getType() == int.class || field.getType() == Integer.class) { field.set(obj, Integer.parseInt((value))); } //如果是float(包含基本类型和包装类) else if (field.getType() == float.class || field.getType() == Float.class) { field.set(obj, Float.parseFloat((value))); } //如果是double(包含基本类型和包装类) else if (field.getType() == double.class || field.getType() == Double.class) { field.set(obj, Double.parseDouble((value))); } //如果是double(包含基本类型和包装类) else if (field.getType() == long.class || field.getType() == Long.class) { field.set(obj, Long.parseLong((value))); } //如果是boolean(包含基本类型和包装类) else if (field.getType() == boolean.class || field.getType() == Boolean.class) { field.set(obj, Boolean.parseBoolean((value))); } //如果是boolean(包含基本类型和包装类) else if (field.getType() == String.class) { field.set(obj, value); } } } } } @Override public void destory() { } }接着我们模仿Spring写几个注解:
模仿Spring的Autowire注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface CustomAutowire { String name() default ""; }模仿Spring的Component注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface CustomComponent { }模仿Controller注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface CustomController { }模仿RequestMapping注解:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE,ElementType.METHOD}) public @interface CustomRequestMapping { /** * URI * @return */ String value(); /** * 参数信息 * @return */ String[] parameter() default ""; }这里根据请求找到对应的处理类和处理方法的思路是:定义一个Map,key是请求URI,value是自定义的一个类。这个自定义的类(RequestMappingInfo)包含这几个信息:Class信息、Method类、对象、请求参数和方法参数 。java类在编译为class的时候有release和debug模式之分,在命令行中直接使用javac进行编译的时候,默认的时候release模式,使用release模式会改变形参中的参数名。而IDE都是使用debug模式进行编译的。ant编译的时候,需要在ant的配置文件中指定debug="true"。 如果要修改javac编译类文件的方式的话,需要指定-g参数。即:javac -g 类文件。通常我们都是用IDE进行项目开发的,所以我们的java类在编译成class的时候参数是不会变的 ,而SpringMVC在处理参数这个地方用到了ASM技术,来获取参数的信息,并且是在第一次处理请求的时候,来获取参数信息并放到缓存中,以后都从缓存中获取参数信息。RequestMappingInfo代码如下:
public class RequestMappingInfo { /** * 类名 */ private Class<?> clazz; /** * 方法名 */ private Method method; /** * 对象 */ private Object obj; /** * 参数 */ private List<String> parameter; /** * 方法的参数 */ private Class<?>[] formalParameter; //省略get set方法 }接着我们定义一个类方便IOC:
public class BeanDefinitionInfo implements Serializable { private static final long serialVersionUID = -5988012842492544219L; /** * 类信息 */ private Class<?> clazz; /** * 对象 */ private Object object; /** * 父类 */ private List<Class<?>> superClass; //省略 get set }接着就是我们比较重要的类了ApplicationContext,我们会在这里类中,简单模仿Spring IOC的过程,扫描固定包下固定注解的类。在这里遇到了一个问题,一开始在加载类的时候自己写了一个类加载器,但是一个类加载器在他的生命周期中只会加载这个类一次,所以会出现多次加载同一个类的情况。后来别人推荐了一个小工具类: Reflections,这个问题才比较完美的解决,Reflections是一个很不错的工具类,可以扫描Classpath下面任意的类,并且让反射更容易。如下:扫描带某个注解的类,获取含有方法名为某个字符串的类等等。github地址在这儿:https://github.com/ronmamo/reflections,里面有很多例子。自定义的ApplicationContext的代码如下:
public class ApplicationContext { public static final Map<String, RequestMappingInfo> mappingMap = new HashMap<>(); /** * 所有扫描到的类 */ private static final Map<Class<?>, BeanDefinitionInfo> allScanClazz = new HashMap<>(); private static final List<Class<?>> allClass = Lists.newArrayList(); private static Servlet servlet; private CustomInputStreamSource streamSource = null; public ApplicationContext(Servlet servlet, String location) { this.servlet = servlet; streamSource = new CustomClasspathResource(location); } public void init() throws Exception { Properties properties = new Properties(); properties.load(streamSource.getInputStream()); String componentScan = properties.getProperty("component.scan"); wrapperCompontent(componentScan); imitateIOC(); servlet.init(); } private void wrapperCompontent(String componentScan) throws InstantiationException, IllegalAccessException { Reflections reflection = new Reflections(componentScan); //扫描所有有CustomController注解的类 Set<Class<?>> controllerClazz = reflection.getTypesAnnotatedWith(CustomController.class); //扫描所有有CustomComponent注解的类 Set<Class<?>> componentClazz = reflection.getTypesAnnotatedWith(CustomComponent.class); //扫描所有有CustomService注解的类 Set<Class<?>> serviceClazz = reflection.getTypesAnnotatedWith(CustomService.class); for (Iterator<Class<?>> it = controllerClazz.iterator(); it.hasNext(); ) { wrapperController(it.next()); } componentClazz.addAll(serviceClazz); for (Iterator<Class<?>> it = componentClazz.iterator(); it.hasNext(); ) { Class<?> clazz = it.next(); BeanDefinitionInfo beanDefinitionInfo = new BeanDefinitionInfo(); beanDefinitionInfo.setClazz(clazz); wrapperSuperClass(clazz, beanDefinitionInfo); allScanClazz.put(clazz, beanDefinitionInfo); allClass.add(clazz); } } /** * 模仿IOC * * @throws InstantiationException * @throws IllegalAccessException */ private void imitateIOC() throws InstantiationException, IllegalAccessException { Object instance = null; BeanDefinitionInfo beanDefinitionInfo = null; for (Map.Entry<Class<?>, BeanDefinitionInfo> entry : allScanClazz.entrySet()) { Class clazz = entry.getKey(); beanDefinitionInfo = entry.getValue(); instance = beanDefinitionInfo.getObject(); if (instance == null) { instance = clazz.newInstance(); beanDefinitionInfo.setObject(instance); } Field[] fields = clazz.getDeclaredFields(); if (fields != null && fields.length > 0) { for (int i = 0; i < fields.length; i++) { if (!fields[i].isAccessible()) { fields[i].setAccessible(true); } if (AnnotationUtil.isAutowire(fields[i])) { Class tmpClass = fields[i].getType(); if (tmpClass.isInterface()) { BeanDefinitionInfo tmpBean = null; for (int j = 0; j < allClass.size(); j++) { tmpBean = allScanClazz.get(allClass.get(j)); if (tmpClass.isAssignableFrom(tmpBean.getClazz())) { if (tmpBean.getObject() == null) { Object tmp = tmpBean.getClazz().newInstance(); tmpBean.setObject(tmp); } fields[i].set(instance, tmpBean.getObject()); break; } } } else { BeanDefinitionInfo tmpBean = allScanClazz.get(tmpClass); if (tmpBean.getObject() == null) { tmpBean.setObject(tmpBean.getClazz().newInstance()); } fields[i].set(instance, tmpBean.getObject()); } } } } } } /** * 组装Controller * * @param clazz * @throws IllegalAccessException * @throws InstantiationException */ private void wrapperController(Class<?> clazz) throws IllegalAccessException, InstantiationException { Object obj = clazz.newInstance(); BeanDefinitionInfo beanDefinitionInfo = new BeanDefinitionInfo(); beanDefinitionInfo.setClazz(clazz); beanDefinitionInfo.setObject(obj); wrapperSuperClass(clazz, beanDefinitionInfo); allScanClazz.put(clazz, beanDefinitionInfo); String str = ""; CustomRequestMapping customRequestMapping = null; if ((customRequestMapping = isRequestMapping(clazz)) != null) { if (customRequestMapping.value().startsWith("/")) { str = customRequestMapping.value(); } else { str = "/" + customRequestMapping.value(); } } Method[] methodArray = clazz.getMethods(); if (methodArray != null) { RequestMappingInfo requestMappingInfo = null; for (Method method : methodArray) { customRequestMapping = method.getAnnotation(CustomRequestMapping.class); if (customRequestMapping != null) { requestMappingInfo = new RequestMappingInfo(); requestMappingInfo.setClazz(clazz); requestMappingInfo.setMethod(method); requestMappingInfo.setObj(obj); Class<?>[] clazzs = method.getParameterTypes(); String strInner = ""; if (clazzs != null) { requestMappingInfo.setFormalParameter(clazzs); } if (customRequestMapping.value().startsWith("/")) { strInner = customRequestMapping.value(); } else { strInner = "/" + customRequestMapping.value(); } String[] parameter = customRequestMapping.parameter(); if (parameter != null && parameter.length > 0) { requestMappingInfo.setParameter(Arrays.asList(parameter)); } mappingMap.put(str + strInner, requestMappingInfo); } } } } /** * 组装父类 * * @param clazz * @param beanDefinitionInfo */ private void wrapperSuperClass(Class<?> clazz, BeanDefinitionInfo beanDefinitionInfo) { Class<?> tmp = clazz; List<Class<?>> superList = Lists.newArrayList(); while (tmp.getSuperclass() != null && tmp.getSuperclass() != Object.class) { superList.add(clazz.getSuperclass()); tmp = clazz.getSuperclass(); } beanDefinitionInfo.setSuperClass(superList); } public CustomRequestMapping isRequestMapping(Class<?> clazz) { return clazz.getAnnotation(CustomRequestMapping.class); } public static Servlet getServlet() { return servlet; }下面我们写个Controller类来测试一下:
@CustomController @CustomRequestMapping(value = "/custom") public class FirstPageController { @CustomAutowire private UserService userService; @CustomRequestMapping(value = "/myFirstPage.do") public void myFirstPage() { System.out.println("我被调用了、、、、"); } /** * 插入操作 * * @param userScope */ @CustomRequestMapping(value = "/inserUser.do") public void inserUser(UserScope userScope, Response response) { Cookie cookie = new Cookie("test", "testcookie"); Cookie cookie2 = new Cookie("test02", "testcookie02"); response.addCookie(cookie); response.addCookie(cookie2); System.out.println("我是插入操作的Controller层、、、、"); userService.insert(userScope); } }我们在浏览器中输入:http://localhost:8005/custom/myFirstPage.do来看一下结果:
控制台输出如下:
返回结果如下:
和我们程序写的结果一样。
接着我们写一个稍微复杂一点的,定义一个javaBean、DAO类、Service类。
UserScope
public class UserScope implements Serializable{ private static final long serialVersionUID = -8340887359752275426L; /** * 用户名 */ private String userName; /** * 密码 */ private String passWord; //省略get set }DAO
public interface UserDAO { /** * 插入用户信息 * @param user * @return */ Integer insert(UserScope user); }
@CustomComponent public class UserDAOImpl implements UserDAO { private Random random = new Random(); @Override public Integer insert(UserScope user) { System.out.println("我是DAO层。。。。进行插入操作......"); System.out.println(JSON.toJSONString(user)); return random.nextInt(); } }Service:
public interface UserService { /** * 插入用户信息 * @param userScope * @return */ Integer insert(UserScope userScope); }
@CustomService public class UserServiceImpl implements UserService { @CustomAutowire private UserDAO userDAO; /** * 插入用户信息 * * @param userScope * @return */ @Override public Integer insert(UserScope userScope) { System.out.println("我是Service层。。。。进行插入操作......"); return userDAO.insert(userScope); } }从上面的代码中我们可以看到在DAO的实现类上我们用了CustomComponent注解,在Service的实现类上我们用了CustomService的注解。在我们的那个Controller中我们又用了CustomAutowire这个注解。下面我们访问一下看看效果,我们在浏览器中输入:http://localhost:8005/custom/inserUser.do?userName=hangssewe&passWord=2ewewe
控制台输出如下:
浏览器输出为:
我们在Controller中的inserUser这个方法中设置了两个Cookie,我们来看一下Cookie有没有设置成功:
结果和我们预想的是一样的。
接着我们写一个静态资源的处理类:
public class StaticResourceProcessor { public void process(Request request, Response response) { response.sendStaticResource(request.getUri()); } }访问一下看看效果如何:
这里遇到的一个问题是在Chrome浏览器中访问的时候会报错,在IE浏览器中访问则正常显示,还没搞清楚为什么会出现这样的问题。