1.Annotation
在JDK5之后,增加Annotation注解的基本语法,通过注解可以省略XML的配置信息,简化代码的编写形式。 在Annotation中,如果想要自定义,可以通过如下 语法:
@Target(ElementType.xxxx)
@Retention(RetentionPolicy.xxxx)
public @interface 注解名 {
}
Target:对应的是当前的注解能够定义在那个位置。
- ElementType.Type -- 类之前
- ElementType.Field --字段之前(domain中)
- ElementType.Method --方法之前
Retention:在什么场景下起作用。
- RetentionPolicy.CLASS - 定义类时
- RetentionPolicy.SOURCE - 编写代码时
- RetentionPolicy.RUNTIME --运行时(最常用)
1.1代码编写
根据当前自定义MVC框架的一个需求,我们定义了两个Annotation:
@Controller
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
}
@RequestMapping
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
//在使用RequestMapping的时候可以携带参数value,default为默认值。
String value() default "";
}
1.2工具类
将所有包含了@Controller类进行遍历
package util;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* 获得包下面的所有的以.class结尾的java文件
*/
public class ClassScanner {
/**
* 获得包下面的所有的class
*/
public static List<Class<?>> getClassFromPackage(String packageName) {
List<Class<?>> clazzs = new ArrayList<>();
//是否循环搜索子包
boolean recursive = true;
//包名对应的路径名称
String packageDirName = packageName.replace(".", "/");
//从当前正在运行的线程中,加载类加载器,通过给定的包名,找到所有该包下的类
Enumeration<URL> dirs;
try {
//currentThread()方法返回正在被执行的线程的信息。currenThread()和this的区别(currentThread()方法返回的是当前正在被执行的线程,而this是自定义线程对象。)
//Thread.currentThread().getContextClassLoader()方法返回当前正在运行的线程的上下文,如果没有,则默认返回父线程的上下文。
//getResource():getResource接受一个字符串参数,如果以”/”开头,就在classpath根目录下找(不会递归查找子目录),如果不以”/”开头,就在调用getResource的字节码对象所在目录下找(同样不会递归查找子目录)。
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while (dirs.hasMoreElements()) {
URL url = dirs.nextElement();
String protocol = url.getProtocol();
//getProtocol: 返回指定 URL 的协议。如:url=https:// www.geeksforgeeks.org;url.getProtocol()返回https
if ("file".equals(protocol)) {
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
findClassInPackageByFile(packageName, filePath, recursive, clazzs);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return clazzs;
}
/**
* 在package对应的路径下找到所有的class
*/
public static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive, List<Class<?>> clazzs) {
File dir = new File(filePath);
if (!dir.exists() || !dir.isDirectory()) {
return;
}
File[] dirFiles = dir.listFiles(new FileFilter() {
public boolean accept(File file) {
boolean acceptDir = recursive && file.isDirectory();// 接受dir目录
boolean acceptClass = file.getName().endsWith("class");// 接受class文件
return acceptDir || acceptClass;
}
});
for (File file : dirFiles) {
if (file.isDirectory()) {
findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs);
} else {
String className = file.getName().substring(0, file.getName().length() - 6);
try {
clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
1.3监听器
ClassLoaderContextListener:
package listener;
import annotation.Controller;
import annotation.RequestMapping;
import util.ClassScanner;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.lang.reflect.Method;
import java.util.List;
public class ClassLoaderContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
initClassLoader() ;
}
private void initClassLoader(){
List<Class<?>> classList = ClassScanner.getClassFromPackage("controller");
for (Class clazz : classList){
//如果当前类上存在Controller.class,就要获取方法
if (clazz.isAnnotationPresent(Controller.class)){
//Java反射
Method[] methods = clazz.getMethods();
//遍历当前包含了controller注解的所有方法
for (Method method : methods){
//判断方法上是否添加了RequestMapping注解
if (method.isAnnotationPresent(RequestMapping.class)){
//获取到包含了RequestMapping注解的value值
String urlPath = method.getAnnotation(RequestMapping.class).value();
//将值作为键,将方法作为值,存储在map集合中
WebApplicationContext.methodMap.put(urlPath,method);
}
}
}
}
}
}
WebApplicationContext:
package listener;
import javax.servlet.ServletContextListener;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
public class WebApplicationContext {
public static ConcurrentHashMap<String, Method> methodMap = new ConcurrentHashMap<>();
}
1.4解析用户的请求路径
package servlet;
import listener.WebApplicationContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DispatcherServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//步骤1:获取到用户请求的URL
String urlPath = req.getServletPath();
//根据URL获取到对应的method
Method method = WebApplicationContext.methodMap.get(urlPath);
if (method!=null){
//步骤2:调用对应的method方法
//如何找到对应的类
Object instance = null;
try {
instance = method.getDeclaringClass().newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
//如何传输参数,request,response
try {
method.invoke(instance,req,resp);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}else{
resp.sendRedirect("failure.jsp");
}
}
}
1.5将上述项目打包jar
1.6使用
- 新建项目
- 需要在工程下建立com.csi.controller的包
- 在包中建立类,在该类上,添加@Controller的注解
- 建立类中的方法,根据需求,在适当的方法上添加@RequestMapping注解
- 在@RequestMapping注解中添加url请求的路径
1.6.1添加依赖
在pom.xml中添加依赖
添加依赖之后需要在web.xml中配置jar中的servlet和listener
注:servlet中的路径配置*.do,代表只要@RequestMapping()中的value参数是以.do结束的路径,就都可以匹配到。
1.6.2在domain包中写好product相关的字段
package domain;
import java.util.Set;
public class Product {
private int id;
private String name;
private String description;
private double price;
private int stock;
private int categoryLevel1Id;
private int categoryLevel2Id;
private int categoryLevel3Id;
private String fileName;
private int idDelete;
private int brand_id;
private Set<Comment> comments;
private PageInfo<Comment> pageInfo;
public PageInfo<Comment> getPageInfo() {
return pageInfo;
}
public void setPageInfo(PageInfo<Comment> pageInfo) {
this.pageInfo = pageInfo;
}
public Set<Comment> getComments() {
return comments;
}
public void setComments(Set<Comment> comments) {
this.comments = comments;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getStock() {
return stock;
}
public void setStock(int stock) {
this.stock = stock;
}
public int getCategoryLevel1Id() {
return categoryLevel1Id;
}
public void setCategoryLevel1Id(int categoryLevel1Id) {
this.categoryLevel1Id = categoryLevel1Id;
}
public int getCategoryLevel2Id() {
return categoryLevel2Id;
}
public void setCategoryLevel2Id(int categoryLevel2Id) {
this.categoryLevel2Id = categoryLevel2Id;
}
public int getCategoryLevel3Id() {
return categoryLevel3Id;
}
public void setCategoryLevel3Id(int categoryLevel3Id) {
this.categoryLevel3Id = categoryLevel3Id;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int getIdDelete() {
return idDelete;
}
public void setIdDelete(int idDelete) {
this.idDelete = idDelete;
}
public int getBrand_id() {
return brand_id;
}
public void setBrand_id(int brand_id) {
this.brand_id = brand_id;
}
}
1.6.3在dao中实现查询所有商品
public class ProductDaoImpl extends JDBCUtils implements ProductDao {
@Override
public List<Product> listByCategory4Index(int categoryId) throws SQLException {
final String SQL = "SELECT * FROM easybuy_product WHERE categoryLevel1Id = ? limit 6";
Connection connection = this.getConnection();
PreparedStatement ps = connection.prepareStatement(SQL);
ps.setInt(1,categoryId);
ResultSet rs = ps.executeQuery();
//建立List对象
List<Product> products = new ArrayList<>();
while (rs.next()) {
Product product = new Product();
product.setId(rs.getInt("productId"));
product.setName(rs.getString("name"));
product.setPrice(rs.getDouble("price"));
product.setFileName(rs.getString("fileName"));
products.add(product);
}
this.release(rs,ps,connection);
return products;
}
}
1.6.4编写controller
package controller;
import annotation.Controller;
import annotation.RequestMapping;
import com.alibaba.fastjson.JSON;
import domain.Product;
import domain.Result;
import service.Impl.ProductServiceImpl;
import service.ProductService;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.List;
@Controller
public class controller {
@RequestMapping("/list.do")
public void list(HttpServletRequest request,HttpServletResponse response) throws IOException, SQLException {
response.setContentType("application/json;charset=utf-8");
String categoryId = request.getParameter("categoryLevel1Id");
int cate = 0;
if (categoryId!=null){
cate = Integer.parseInt(categoryId);
}
ProductService productService = new ProductServiceImpl();
List<Product> list = productService.listByCategory4Index(cate);
System.out.println(list.size());
Result result = new Result();
if (list.size()!=0){
result.setCode(200);
result.setMsg("success");
result.setData(list);
}else{
result.setCode(400);
result.setMsg("数据为空");
}
//转为JSON数据
String s = JSON.toJSONString(result);
PrintWriter out = response.getWriter();
out.println(s);
}
}
1.6.5JSP实现效果
此处演示了两种AJAX实现方式
<%--
Created by IntelliJ IDEA.
User: wyq
Date: 2022/8/23
Time: 21:28
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<script src="http://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"
integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous">
</script>
<script src="http://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="container">
<div class="row">
</div>
</div>
</body>
<script>
$(function (){
/*$.ajax({
type:"get",
url:"/list.do?categoryLevel1Id=742",
dataType:"JSON",
success:function (list){
$.each(list,function (i,v){
var d = $("<div class='col-sm-6 col-md-4'>" +
"<div class='thumbnail' style='width: 300px'>" +
"<img src="+v.fileName+" alt='...'>" +
"<div class='caption'>" +
"<h3 style='color: red'>¥"+v.price+"</h3>" +
"<p><span style='color: red'>"+v.name+"</span>,"+v.description+"</p>" +
"<p style='color: darkgrey'><span style='color: blue'>2万+</span>条评论</p>" +
"<p style='color: darkgrey'>三星京东旗舰店</p>" +
"</div>" +
"</div>" +
"</div>");
$(".row").append(d);
});
},
error:function (){
alert("没有数据");
}
})*/
$.get("/list.do?categoryLevel1Id=548",function (list){
if (list.code==200){
$(list.data).each(function (i,v){
var d = $("<div class='col-sm-6 col-md-4'>" +
"<div class='thumbnail' style='width: 300px'>" +
"<img src="+v.fileName+" alt='...'>" +
"<div class='caption'>" +
"<h3 style='color: red'>¥"+v.price+"</h3>" +
"<p><span style='color: red'>"+v.name+"</span>,"+v.description+"</p>" +
"<p style='color: darkgrey'><span style='color: blue'>2万+</span>条评论</p>" +
"<p style='color: darkgrey'>三星京东旗舰店</p>" +
"</div>" +
"</div>" +
"</div>");
$(".row").append(d);
});
}else{
$(".row").html(list.msg);
}
})
});
</script>
</html>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。